diff --git a/autonomous-ai-agents/README.md b/autonomous-ai-agents/README.md index 46c9219..8c976af 100644 --- a/autonomous-ai-agents/README.md +++ b/autonomous-ai-agents/README.md @@ -1,77 +1,300 @@ -# Autonomous AI Agents — Quick Install Guide (OCI Object Storage + OCI Vault) +# Autonomous AI Agents for OCI (Oracle Autonomous Database) -This guide shows how to install and use the two SQL installer scripts: -- oci_object_storage_agent_install.sql -- oci_vault_agent_install.sql +## Overview -What gets installed -- A config table in your target schema: OCI_AGENT_CONFIG -- A PL/SQL package with ready-to-use functions -- AI Agent tools (DBMS_CLOUD_AI_AGENT) mapped to those functions +This repository provides a **modular, extensible framework** for building **OCI AI Agents** using **Oracle Autonomous Database** and **`DBMS_CLOUD_AI_AGENT` (Select AI)**. -Important -- INSTALL_SCHEMA is mandatory. Always set it. +Each OCI service (Vault, Object Storage, Autonomous Database, Network Load Balancer, etc.) is implemented using a **two-layer model**: -Prerequisites -- A DBMS_CLOUD credential with OCI permissions for the target compartment(s) -- The target schema name (INSTALL_SCHEMA) where packages/tools/config will live +- **Tools Layer** + - Installs reusable PL/SQL functions + - Registers them as AI tools +- **Agent Layer** + - Creates sample tasks, agents, and teams + - Consumes the tools created in the Tools layer -1) Create or identify a DBMS_CLOUD credential -Example (if needed): -``` -BEGIN - DBMS_CLOUD.CREATE_CREDENTIAL( - credential_name => 'MY_CRED', - username => '', - password => '' - ); -END; -/ -``` +### Benefits of This Design -2) Install — set variables and run the scripts -Use SQL*Plus q'(...)' quoting for JSON so you don't need to escape quotes. +- Reuse tools across multiple agents +- Allow end users to create custom agents and tasks +- Clear separation of: + - Infrastructure logic + - AI orchestration logic -Connect: -``` -sqlplus admin@ -``` +--- -Set variables (mandatory INSTALL_SCHEMA, optional INSTALL_CONFIG_JSON): -``` -DEFINE INSTALL_SCHEMA = 'YOUR_APP_SCHEMA'; -DEFINE INSTALL_CONFIG_JSON = q'({"credential_name": "MY_CRED", "compartment_name": "MY_COMP"})'; -``` +## Design Principles -Run one or both installers: -``` -@autonomous_ai_agents/oci_object_storage_agent_install.sql -@autonomous_ai_agents/oci_vault_agent_install.sql -``` +### 1. Two-Layer Architecture + +Each OCI service is implemented using **two SQL scripts**: + +| Layer | Script Pattern | Purpose | +|------|---------------|---------| +| Tools Layer | `*_tools.sql` | Installs core PL/SQL logic and registers AI tools | +| Agent Layer | `*_agent.sql` | Creates a sample Task, Agent, and Team using those tools | + +This design ensures: +- Tools are reusable across multiple agents +- Agent behavior remains customizable + +--- -Notes -- INSTALL_CONFIG_JSON is optional (defaults to NULL). -- Recommended keys to include if you pass JSON: - - credential_name: your DBMS_CLOUD credential name - - compartment_name: name of the compartment +## Tools Scripts (`*_tools.sql`) -3) If you didn’t pass INSTALL_CONFIG_JSON, you can still configure the -agent after installation by adding rows to YOUR_APP_SCHEMA.OCI_AGENT_CONFIG. -Each agent has its own AGENT value -- For object storage use OCI_OBJECT_STORAGE -- For vault use OCI_VAULT +### Purpose -Examples (Object Storage) +Tools scripts are responsible for **infrastructure and capability enablement**. -Set credential name for Object Storage operations: +**Example:** +- `oci_vault_tools.sql` + +--- + +### What a Tools Script Does + +A tools script typically performs the following steps: + +#### 1. Grant Required Privileges + +- Grants access to: + - `DBMS_CLOUD` + - `DBMS_CLOUD_AI` + - `DBMS_CLOUD_AI_AGENT` + - Relevant OCI typed API packages +- Privileges are scoped to the **target schema** + +--- + +#### 2. Create Configuration Table + +Creates a generic configuration table: + +```sql +OCI_AGENT_CONFIG ``` -INSERT INTO YOUR_APP_SCHEMA.OCI_AGENT_CONFIG ("KEY","VALUE","AGENT") -VALUES ('CREDENTIAL_NAME', 'MY_CRED', 'OCI_OBJECT_STORAGE'); + +**Stores configuration such as:** +- Credential name +- Compartment name / OCID +- Resource principal enablement + +> Configuration is **agent-specific** and persisted for runtime use. + +--- + +#### 3. Initialize Configuration + +- Parses optional JSON configuration input +- Enables resource principal authentication if requested +- Persists configuration values + +--- + +#### 4. Create PL/SQL Package + +**Example package:** + +```sql +oci_vault_agents ``` -Set compartment name for Vault +**Package responsibilities:** +- Implements core OCI API logic +- Calls OCI APIs using `DBMS_CLOUD_OCI_*` +- Each function: + - Returns **CLOB JSON** + - Includes: + - Status codes + - Headers + - Response payloads + +--- + +#### 5. Register AI Tools + +- Uses `DBMS_CLOUD_AI_AGENT.CREATE_TOOL` +- Maps each PL/SQL function to an AI tool +- Adds rich instructions describing: + - When to use the tool + - Safety rules (e.g. no secret exposure) + - Expected behavior + +--- + +### Key Characteristics of Tools + +- Service-specific but **agent-agnostic** +- Reusable by any task or agent +- Safe to re-run (drop & recreate logic) +- Designed for **human-readable AI responses** + +--- + +## Agent Scripts (`*_agent.sql`) + +### Purpose + +Agent scripts create **example AI agents** demonstrating how to use the tools. + +**Example:** +- `oci_vault_agent.sql` + +--- + +### What an Agent Script Does + +#### 1. Interactive Execution + +Prompts for: +- Target schema name +- AI Profile name + +This makes scripts **portable across environments**. + +--- + +#### 2. Grant Required Privileges + +Grants: +- `DBMS_CLOUD_AI_AGENT` +- `DBMS_CLOUD` + +To the target schema. + +--- + +#### 3. Create Installer Procedure + +- Creates an installer procedure in the target schema +- Keeps all agent logic **schema-local** + +--- + +#### 4. Create AI Task + +Defines: +- User intent detection +- Allowed tools +- Safety rules +- Formatting expectations + +Enforces: +- Confirmation for destructive actions +- Human-readable output + +--- + +#### 5. Create AI Agent + +- Binds the agent to the specified AI Profile +- Defines the agent’s role and behavior + +--- + +#### 6. Create AI Team + +- Links the agent and task +- Uses **sequential execution** + +--- + +#### 7. Execute Installer + +- Runs the installer procedure +- Completes agent setup + +--- + +### Key Characteristics of Agents + +- Agents are **examples**, not hard dependencies +- End users can: + - Modify tasks + - Create new agents + - Create multiple teams +- Tools remain unchanged and reusable + +--- + +## Example: OCI Vault + +### Files + +| File | Description | +|-----|------------| +| `oci_vault_tools.sql` | Installs Vault PL/SQL package, config table, and AI tools | +| `oci_vault_agent.sql` | Creates a sample Vault task, agent, and team | + +--- + +### Supported Capabilities + +The Vault tools support: + +- List secrets +- Get secret metadata +- Create secrets +- Update secrets / rotate versions +- List secret versions +- Get specific secret versions +- Schedule and cancel deletions +- Change secret compartment + +**All operations:** +- Use persisted configuration +- Require confirmation for destructive actions +- Never expose secret payloads unintentionally + +--- + +## Installation Order (Recommended) + +For each OCI service: + +1. Run `*_tools.sql` +2. Run `*_agent.sql` (optional, for sample agent) + +### Example (OCI Vault) + +```sql +-- Step 1: Install tools +sqlplus admin@db @oci_vault_tools.sql + +-- Step 2: Install sample agent +sqlplus admin@db @oci_vault_agent.sql ``` -INSERT INTO YOUR_APP_SCHEMA.OCI_AGENT_CONFIG ("KEY","VALUE","AGENT") -VALUES ('COMPARTMENT_NAME', 'MY_COMP', 'OCI_VAULT'); + +--- + +## Customization & Extension + +- Create your own tasks, agents, and teams +- Tools remain stable and reusable +- Multiple agents can share the same tools +- Configuration can be updated in: + +```sql +OCI_AGENT_CONFIG ``` +--- + +## Error Handling & Safety + +- Scripts exit immediately on SQL errors +- All destructive OCI operations require confirmation +- Tools return structured JSON containing: + - Status + - Headers + - Payload +- Fully re-runnable with safe drop-and-create logic + +--- + +## License + +This project is licensed under the **Universal Permissive License (UPL), Version 1.0**. + +See: +https://oss.oracle.com/licenses/upl/ diff --git a/autonomous-ai-agents/oci_autonomous_database/oci_autonomous_database_agent.sql b/autonomous-ai-agents/oci_autonomous_database/oci_autonomous_database_agent.sql new file mode 100644 index 0000000..02d6ac4 --- /dev/null +++ b/autonomous-ai-agents/oci_autonomous_database/oci_autonomous_database_agent.sql @@ -0,0 +1,250 @@ +rem ============================================================================ +rem LICENSE +rem Copyright (c) 2025 Oracle and/or its affiliates. +rem Licensed under the Universal Permissive License (UPL), Version 1.0 +rem https://oss.oracle.com/licenses/upl/ +rem +rem NAME +rem oci_autonomous_database_agent.sql +rem +rem DESCRIPTION +rem Installer and configuration script for OCI Autonomous Database +rem AI Agent using DBMS_CLOUD_AI_AGENT +rem (Select AI / Oracle AI Database). +rem +rem This script performs an interactive installation of an +rem OCI Autonomous Database AI Agent by: +rem - Prompting for target schema and AI Profile +rem - Granting required privileges to the target schema +rem - Creating an installer procedure in the target schema +rem - Registering an OCI Autonomous Database Task +rem - Creating an OCI Autonomous Database AI Agent bound +rem to the specified AI Profile +rem - Creating an OCI Autonomous Database Team linking +rem the agent and task +rem - Executing the installer procedure to complete setup +rem +rem RELEASE VERSION +rem 1.0 +rem +rem RELEASE DATE +rem 26-Jan-2026 +rem +rem MAJOR CHANGES IN THIS RELEASE +rem - Initial release +rem - Added OCI Autonomous Database task, agent, and team +rem - Interactive installer with schema and AI profile prompts +rem +rem SCRIPT STRUCTURE +rem 1. Initialization: +rem - Enable SQL*Plus settings and error handling +rem - Prompt for target schema and AI profile +rem +rem 2. Grants: +rem - Grant DBMS_CLOUD_AI_AGENT and DBMS_CLOUD privileges +rem to the target schema +rem +rem 3. Installer Procedure Creation: +rem - Create INSTALL_OCI_AUTONOMOUS_DATABASE_AGENT +rem procedure in the target schema +rem +rem 4. AI Registration: +rem - Drop and create OCI_AUTONOMOUS_DATABASE_TASKS +rem - Drop and create OCI_AUTONOMOUS_DATABASE_ADVISOR +rem agent +rem - Drop and create OCI_AUTONOMOUS_DATABASE_TEAM +rem +rem 5. Execution: +rem - Execute installer procedure with AI profile parameter +rem +rem INSTALL INSTRUCTIONS +rem 1. Connect as ADMIN or a user with required privileges +rem +rem 2. Run the script using SQL*Plus or SQLcl: +rem +rem sqlplus admin@db @oci_autonomous_database_agent.sql +rem +rem 3. Provide inputs when prompted: +rem - Target schema name +rem - AI Profile name +rem +rem 4. Verify installation by confirming: +rem - OCI_AUTONOMOUS_DATABASE_TASKS task exists +rem - OCI_AUTONOMOUS_DATABASE_ADVISOR agent is created +rem - OCI_AUTONOMOUS_DATABASE_TEAM team is registered +rem +rem PARAMETERS +rem INSTALL_SCHEMA (Prompted) +rem Target schema where the installer procedure, +rem task, agent, and team are created. +rem +rem PROFILE_NAME (Prompted) +rem AI Profile name used to bind the OCI Autonomous +rem Database agent. +rem +rem NOTES +rem - Script is safe to re-run; existing tasks, agents, +rem and teams are dropped and recreated. +rem +rem - Destructive Autonomous Database operations require +rem explicit user confirmation as enforced by task instructions. +rem +rem - Script exits immediately on SQL errors. +rem +rem ============================================================================ + + +SET SERVEROUTPUT ON +SET VERIFY OFF +WHENEVER SQLERROR EXIT SQL.SQLCODE + +PROMPT ====================================================== +PROMPT OCI Autonomous Database AI Agent Installer +PROMPT ====================================================== + +-- Target schema +ACCEPT SCHEMA_NAME CHAR PROMPT 'Enter target schema name: ' +DEFINE INSTALL_SCHEMA = '&SCHEMA_NAME' + +-- AI Profileda +ACCEPT PROFILE_NAME CHAR PROMPT 'Enter AI Profile name to be used with the Agent: ' +DEFINE PROFILE_NAME = '&PROFILE_NAME' + +PROMPT ------------------------------------------------------ +PROMPT Installing into schema: &&INSTALL_SCHEMA +PROMPT Using AI Profile : &&PROFILE_NAME +PROMPT ------------------------------------------------------ + +---------------------------------------------------------------- +-- 1. Grants (safe to re-run) +---------------------------------------------------------------- +BEGIN + DBMS_OUTPUT.PUT_LINE('Granting required privileges to &&INSTALL_SCHEMA ...'); + EXECUTE IMMEDIATE 'GRANT EXECUTE ON DBMS_CLOUD_AI_AGENT TO &&INSTALL_SCHEMA'; + EXECUTE IMMEDIATE 'GRANT EXECUTE ON DBMS_CLOUD TO &&INSTALL_SCHEMA'; + DBMS_OUTPUT.PUT_LINE('Grants completed.'); +END; +/ + +---------------------------------------------------------------- +-- 2. Create installer procedure in target schema +---------------------------------------------------------------- +PROMPT Creating installer procedure in &&INSTALL_SCHEMA ... + +CREATE OR REPLACE PROCEDURE &&INSTALL_SCHEMA..install_oci_autonomous_database_agent ( + p_profile_name IN VARCHAR2 +) +AUTHID DEFINER +AS +BEGIN + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); + DBMS_OUTPUT.PUT_LINE('Starting OCI Autonomous Database AI installation'); + DBMS_OUTPUT.PUT_LINE('Schema : ' || USER); + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); + + ------------------------------------------------------------ + -- DROP & CREATE TASK + ------------------------------------------------------------ + BEGIN + DBMS_CLOUD_AI_AGENT.DROP_TASK('OCI_AUTONOMOUS_DATABASE_TASKS'); + EXCEPTION + WHEN OTHERS THEN NULL; + END; + + DBMS_CLOUD_AI_AGENT.CREATE_TASK( + task_name => 'OCI_AUTONOMOUS_DATABASE_TASKS', + description => 'Task for provisioning and managing OCI Autonomous Databases.', + attributes => '{ + "instruction": "Identify the intent of the user request and determine the correct Autonomous Database operation. ' + || 'Prompt the user only for necessary missing details. ' + || 'Ask clarifying questions if intent is ambiguous. ' + || 'When presenting any list, object, or JSON structure to the user, format it in a human-readable way. ' + || 'Confirm destructive actions before execution. ' + || 'User request: {query}", + "tools": [ + "LIST_SUBSCRIBED_REGIONS_TOOL", + "LIST_COMPARTMENTS_TOOL", + "GET_COMPARTMENT_OCID_BY_NAME_TOOL", + "LIST_AUTONOMOUS_DATABASES_TOOL", + "GET_AUTONOMOUS_DATABASE_DETAILS_TOOL", + "ADBS_PROVISIONING_TOOL", + "ADBS_UNPROVISION_TOOL", + "START_AUTONOMOUS_DATABASE_TOOL", + "STOP_AUTONOMOUS_DATABASE_TOOL", + "DATABASE_RESTART_TOOL", + "MANAGE_AUTONOMOUS_DB_POWER_TOOL", + "UPDATE_AUTONOMOUS_DB_RESOURCES_TOOL", + "GET_MAINTENANCE_RUN_HISTORY_TOOL", + "UPDATE_AUTONOMOUS_DATABASE_TOOL", + "LIST_KEY_STORES_TOOL", + "LIST_DB_HOMES_TOOL", + "SHRINK_AUTONOMOUS_DATABASE_TOOL", + "DELETE_KEY_STORE_TOOL", + "LIST_ACDS_TOOL", + "LIST_ADB_BACKUPS_TOOL" + ], + "enable_human_tool": "true" + }' + ); + DBMS_OUTPUT.PUT_LINE('Created task OCI_AUTONOMOUS_DATABASE_TASKS'); + + ------------------------------------------------------------ + -- DROP & CREATE AGENT + ------------------------------------------------------------ + BEGIN + DBMS_CLOUD_AI_AGENT.DROP_AGENT('OCI_AUTONOMOUS_DATABASE_ADVISOR'); + DBMS_OUTPUT.PUT_LINE('Dropped agent OCI_AUTONOMOUS_DATABASE_ADVISOR'); + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Agent OCI_AUTONOMOUS_DATABASE_ADVISOR does not exist, skipping'); + END; + + DBMS_CLOUD_AI_AGENT.CREATE_AGENT( + agent_name => 'OCI_AUTONOMOUS_DATABASE_ADVISOR', + attributes => + '{' || + '"profile_name":"' || p_profile_name || '",' || + '"role":"You are an OCI Autonomous Database Advisor. You help users provision, list, start/stop/restart, resize, update configuration, and inspect ADB-related resources safely. You confirm destructive actions and present results clearly."' || + '}', + description => 'AI agent for advising and automating OCI Autonomous Database operations' + ); + DBMS_OUTPUT.PUT_LINE('Created agent OCI_AUTONOMOUS_DATABASE_ADVISOR'); + + ------------------------------------------------------------ + -- DROP & CREATE TEAM + ------------------------------------------------------------ + BEGIN + DBMS_CLOUD_AI_AGENT.DROP_TEAM('OCI_AUTONOMOUS_DATABASE_TEAM'); + DBMS_OUTPUT.PUT_LINE('Dropped team OCI_AUTONOMOUS_DATABASE_TEAM'); + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Team OCI_AUTONOMOUS_DATABASE_TEAM does not exist, skipping'); + END; + + DBMS_CLOUD_AI_AGENT.CREATE_TEAM( + team_name => 'OCI_AUTONOMOUS_DATABASE_TEAM', + attributes => '{ + "agents":[{"name":"OCI_AUTONOMOUS_DATABASE_ADVISOR","task":"OCI_AUTONOMOUS_DATABASE_TASKS"}], + "process":"sequential" + }' + ); + DBMS_OUTPUT.PUT_LINE('Created team OCI_AUTONOMOUS_DATABASE_TEAM'); + + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); + DBMS_OUTPUT.PUT_LINE('OCI Autonomous Database AI installation COMPLETE'); + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); +END install_oci_autonomous_database_agent; +/ + +---------------------------------------------------------------- +-- 3. Execute installer in target schema +---------------------------------------------------------------- +PROMPT Executing installer procedure ... +BEGIN + &&INSTALL_SCHEMA..install_oci_autonomous_database_agent('&&PROFILE_NAME'); +END; +/ + +PROMPT ====================================================== +PROMPT Installation finished successfully +PROMPT ====================================================== diff --git a/autonomous-ai-agents/oci_autonomous_database/oci_autonomous_database_tools.sql b/autonomous-ai-agents/oci_autonomous_database/oci_autonomous_database_tools.sql new file mode 100644 index 0000000..7c6eebd --- /dev/null +++ b/autonomous-ai-agents/oci_autonomous_database/oci_autonomous_database_tools.sql @@ -0,0 +1,1856 @@ +rem ============================================================================ +rem LICENSE +rem Copyright (c) 2025 Oracle and/or its affiliates. +rem Licensed under the Universal Permissive License (UPL), Version 1.0 +rem https://oss.oracle.com/licenses/upl/ +rem +rem NAME +rem oci_autonomous_database_tools.sql +rem +rem DESCRIPTION +rem Installer script for OCI Autonomous Database AI tools +rem (Select AI Agent / Oracle AI Database). +rem +rem This script installs a consolidated PL/SQL package and registers +rem AI Agent tools used to automate OCI Autonomous Database operations +rem via Select AI Agent (Oracle AI Database). +rem +rem RELEASE VERSION +rem 1.0 +rem +rem RELEASE DATE +rem 26-Jan-2026 +rem +rem MAJOR CHANGES IN THIS RELEASE +rem - Initial release +rem - Added Autonomous Database AI agent tool registrations +rem +rem SCRIPT STRUCTURE +rem 1. Initialization: +rem - Grants +rem - Configuration setup +rem +rem 2. Package Deployment: +rem - &&INSTALL_SCHEMA.oci_autonomous_database_agents +rem (package specification and body) +rem +rem 3. AI Tool Setup: +rem - Creation of all Autonomous Database agent tools +rem +rem INSTALL INSTRUCTIONS +rem 1. Connect as ADMIN or a user with required privileges +rem 2. Run the script using SQL*Plus or SQLcl: +rem +rem sqlplus admin@db @oci_autonomous_database_tools.sql [CONFIG_JSON] +rem +rem 3. Verify installation by checking tool registration +rem and package compilation status. +rem +rem PARAMETERS +rem INSTALL_SCHEMA (Required) +rem Schema in which the package and tools will be created. +rem +rem CONFIG_JSON (Optional) +rem JSON string used to configure OCI access. +rem +rem NOTES +rem - Optional CONFIG_JSON keys: +rem * use_resource_principal (boolean) +rem * credential_name (string) +rem * compartment_name (string) +rem * compartment_ocid (string) +rem +rem - Configuration can also be updated post-install +rem in the OCI_AGENT_CONFIG table. +rem +rem - This script is idempotent only if DROP logic +rem is explicitly enabled. +rem +rem ============================================================================ + + +SET SERVEROUTPUT ON +SET VERIFY OFF + +-- First argument: Schema Name (Required) +ACCEPT SCHEMA_NAME CHAR PROMPT 'Enter schema name: ' +DEFINE INSTALL_SCHEMA = '&SCHEMA_NAME' + +-- Second argument: JSON config (optional) +-- DEFINE INSTALL_CONFIG_JSON = q'({"credential_name": "MY_CRED", "compartment_name": "MY_COMP"})' +DEFINE INSTALL_CONFIG_JSON = NULL + +------------------------------------------------------------------------------- +-- Initializes the OCI Autonomous Database AI Agent. +------------------------------------------------------------------------------- +CREATE OR REPLACE PROCEDURE initialize_autonomous_database_agent( + p_install_schema_name IN VARCHAR2, + p_config_json IN CLOB +) +IS + l_use_rp BOOLEAN := NULL; + l_credential_name VARCHAR2(4000) := NULL; + l_compartment_ocid VARCHAR2(4000) := NULL; + l_compartment_name VARCHAR2(4000) := NULL; + l_schema_name VARCHAR2(128); + c_adb_agent CONSTANT VARCHAR2(64) := 'OCI_AUTONOMOUS_DATABASE'; + + TYPE priv_list_t IS VARRAY(250) OF VARCHAR2(4000); + l_priv_list CONSTANT priv_list_t := priv_list_t( + 'DBMS_CLOUD', + 'DBMS_CLOUD_ADMIN', + 'DBMS_CLOUD_AI_AGENT', + 'DBMS_CLOUD_OCI_DB_DATABASE', + -- Types used by common responses / requests (best-effort) + 'DBMS_CLOUD_OCI_DATABASE_CREATE_AUTONOMOUS_DATABASE_BASE_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_CREATE_AUTONOMOUS_DATABASE_RESPONSE_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_DELETE_AUTONOMOUS_DATABASE_RESPONSE_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_GET_AUTONOMOUS_DATABASE_RESPONSE_T', + 'DBMS_CLOUD_OCI_DATABASE_AUTONOMOUS_DATABASE_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_STOP_AUTONOMOUS_DATABASE_RESPONSE_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_START_AUTONOMOUS_DATABASE_RESPONSE_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_RESTART_AUTONOMOUS_DATABASE_RESPONSE_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_GET_MAINTENANCE_RUN_HISTORY_RESPONSE_T', + 'DBMS_CLOUD_OCI_DATABASE_UPDATE_AUTONOMOUS_DATABASE_DETAILS_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_UPDATE_AUTONOMOUS_DATABASE_RESPONSE_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_LIST_KEY_STORES_RESPONSE_T', + 'DBMS_CLOUD_OCI_DATABASE_KEY_STORE_SUMMARY_TBL', + 'DBMS_CLOUD_OCI_DATABASE_KEY_STORE_SUMMARY_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_LIST_DB_HOMES_RESPONSE_T', + 'DBMS_CLOUD_OCI_DATABASE_DB_HOME_SUMMARY_TBL', + 'DBMS_CLOUD_OCI_DATABASE_DB_HOME_SUMMARY_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_SHRINK_AUTONOMOUS_DATABASE_RESPONSE_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_DELETE_KEY_STORE_RESPONSE_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_LIST_APPLICATION_VIPS_RESPONSE_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_LIST_AUTONOMOUS_CONTAINER_DATABASES_RESPONSE_T', + 'DBMS_CLOUD_OCI_DB_DATABASE_LIST_AUTONOMOUS_DATABASE_BACKUPS_RESPONSE_T', + 'DBMS_CLOUD_OCI_DATABASE_VARCHAR2_TBL', + 'DBMS_CLOUD_OCI_DATABASE_CUSTOMER_CONTACT_TBL', + 'DBMS_CLOUD_OCI_DATABASE_RESOURCE_POOL_SUMMARY_T', + 'DBMS_CLOUD_OCI_DATABASE_SCHEDULED_OPERATION_DETAILS_TBL', + 'DBMS_CLOUD_OCI_DATABASE_DATABASE_TOOL_TBL', + 'DBMS_CLOUD_OCI_DATABASE_LONG_TERM_BACK_UP_SCHEDULE_DETAILS_T' + ); + + ---------------------------------------------------------------------------- + -- Helper: grant execute on list of objects + ---------------------------------------------------------------------------- + PROCEDURE execute_grants(p_schema IN VARCHAR2, p_objects IN priv_list_t) IS + BEGIN + EXECUTE IMMEDIATE 'GRANT SELECT ON SYS.V_$PDBS TO ' || p_schema; + FOR i IN 1 .. p_objects.COUNT LOOP + BEGIN + EXECUTE IMMEDIATE 'GRANT EXECUTE ON ' || p_objects(i) || ' TO ' || p_schema; + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Warning: failed to grant ' || p_objects(i) || + ' to ' || p_schema || ' - ' || SQLERRM); + END; + END LOOP; + END execute_grants; + + ---------------------------------------------------------------------------- + -- get_config: returns parsed values via OUT params (no globals modified) + ---------------------------------------------------------------------------- + PROCEDURE get_config( + p_config_json IN CLOB, + o_use_rp OUT BOOLEAN, + o_credential_name OUT VARCHAR2, + o_compartment_name OUT VARCHAR2, + o_compartment_ocid OUT VARCHAR2 + ) IS + l_cfg JSON_OBJECT_T := NULL; + BEGIN + o_use_rp := NULL; + o_credential_name := NULL; + o_compartment_name := NULL; + o_compartment_ocid := NULL; + + IF p_config_json IS NOT NULL AND TRIM(p_config_json) IS NOT NULL THEN + BEGIN + l_cfg := JSON_OBJECT_T.parse(p_config_json); + + IF l_cfg.has('use_resource_principal') THEN + o_use_rp := l_cfg.get_boolean('use_resource_principal'); + END IF; + IF l_cfg.has('credential_name') THEN + o_credential_name := l_cfg.get_string('credential_name'); + END IF; + IF l_cfg.has('compartment_name') THEN + o_compartment_name := l_cfg.get_string('compartment_name'); + END IF; + IF l_cfg.has('compartment_ocid') THEN + o_compartment_ocid := l_cfg.get_string('compartment_ocid'); + END IF; + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Config JSON parse failed: ' || SQLERRM); + o_use_rp := NULL; + o_credential_name := NULL; + o_compartment_name := NULL; + o_compartment_ocid := NULL; + END; + ELSE + DBMS_OUTPUT.PUT_LINE('No config JSON provided, using defaults.'); + END IF; + END get_config; + + ---------------------------------------------------------------------------- + -- Helper: generic MERGE for a single config key/value (schema-qualified) + ---------------------------------------------------------------------------- + PROCEDURE merge_config_key( + p_schema IN VARCHAR2, + p_key IN VARCHAR2, + p_val IN CLOB, + p_agent IN VARCHAR2 + ) IS + l_sql CLOB; + BEGIN + l_sql := + 'MERGE INTO ' || p_schema || '.OCI_AGENT_CONFIG c + USING (SELECT :k AS "KEY", :v AS "VALUE", :a AS "AGENT" FROM DUAL) src + ON (c."KEY" = src."KEY" AND c."AGENT" = src."AGENT") + WHEN MATCHED THEN + UPDATE SET c."VALUE" = src."VALUE" + WHEN NOT MATCHED THEN + INSERT ("KEY", "VALUE", "AGENT") VALUES (src."KEY", src."VALUE", src."AGENT")'; + + EXECUTE IMMEDIATE l_sql USING p_key, p_val, p_agent; + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Warning: failed to persist ' || p_key || ' config: ' || SQLERRM); + END merge_config_key; + + ---------------------------------------------------------------------------- + -- Apply config and persist in OCI_AGENT_CONFIG + ---------------------------------------------------------------------------- + PROCEDURE apply_config( + p_schema IN VARCHAR2, + p_use_rp IN BOOLEAN, + p_credential_name IN VARCHAR2, + p_compartment_name IN VARCHAR2, + p_compartment_ocid IN VARCHAR2 + ) IS + l_effective_use_rp BOOLEAN; + l_enable_rp_str VARCHAR2(3); + BEGIN + l_effective_use_rp := CASE WHEN p_use_rp IS NULL THEN TRUE ELSE p_use_rp END; + + IF p_credential_name IS NOT NULL THEN + merge_config_key(p_schema, 'CREDENTIAL_NAME', p_credential_name, c_adb_agent); + END IF; + IF p_compartment_name IS NOT NULL THEN + merge_config_key(p_schema, 'COMPARTMENT_NAME', p_compartment_name, c_adb_agent); + END IF; + IF p_compartment_ocid IS NOT NULL THEN + merge_config_key(p_schema, 'COMPARTMENT_OCID', p_compartment_ocid, c_adb_agent); + END IF; + + l_enable_rp_str := CASE WHEN l_effective_use_rp THEN 'YES' ELSE 'NO' END; + merge_config_key(p_schema, 'ENABLE_RESOURCE_PRINCIPAL', l_enable_rp_str, c_adb_agent); + + IF l_effective_use_rp THEN + BEGIN + DBMS_CLOUD_ADMIN.ENABLE_RESOURCE_PRINCIPAL(USERNAME => p_schema); + DBMS_OUTPUT.PUT_LINE('Resource principal enabled for ' || p_schema); + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Failed to enable resource principal for ' || p_schema || ' - ' || SQLERRM); + END; + ELSE + DBMS_OUTPUT.PUT_LINE( + 'Resource principal NOT enabled per config. Using credential: ' + || NVL(p_credential_name, '') + ); + END IF; + END apply_config; + +BEGIN + l_schema_name := DBMS_ASSERT.SIMPLE_SQL_NAME(p_install_schema_name); + + execute_grants(l_schema_name, l_priv_list); + + get_config( + p_config_json => p_config_json, + o_use_rp => l_use_rp, + o_credential_name => l_credential_name, + o_compartment_name => l_compartment_name, + o_compartment_ocid => l_compartment_ocid + ); + + BEGIN + EXECUTE IMMEDIATE + 'CREATE TABLE ' || l_schema_name || '.OCI_AGENT_CONFIG ( + "ID" NUMBER GENERATED BY DEFAULT AS IDENTITY, + "KEY" VARCHAR2(200) NOT NULL, + "VALUE" CLOB, + "AGENT" VARCHAR2(128) NOT NULL, + CONSTRAINT OCI_AGENT_CONFIG_PK PRIMARY KEY ("ID"), + CONSTRAINT OCI_AGENT_CONFIG_UK UNIQUE ("KEY","AGENT") + )'; + EXCEPTION + WHEN OTHERS THEN + IF SQLCODE = -955 THEN + NULL; -- already exists + ELSE + RAISE; + END IF; + END; + + apply_config( + p_schema => l_schema_name, + p_use_rp => l_use_rp, + p_credential_name => l_credential_name, + p_compartment_name => l_compartment_name, + p_compartment_ocid => l_compartment_ocid + ); + + DBMS_OUTPUT.PUT_LINE('initialize_autonomous_database_agent completed for schema ' || l_schema_name); +EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Fatal error in initialize_autonomous_database_agent: ' || SQLERRM); + RAISE; +END initialize_autonomous_database_agent; +/ + +------------------------------------------------------------------------------- +-- Run initialization +------------------------------------------------------------------------------- +BEGIN + initialize_autonomous_database_agent( + p_install_schema_name => '&&INSTALL_SCHEMA', + p_config_json => &&INSTALL_CONFIG_JSON + ); +END; +/ + +alter session set current_schema = &&INSTALL_SCHEMA; + +------------------------------------------------------------------------ +-- Package specification +------------------------------------------------------------------------ +CREATE OR REPLACE PACKAGE oci_autonomous_database_agents +AS + FUNCTION list_subscribed_regions RETURN CLOB; + FUNCTION list_compartments RETURN CLOB; + FUNCTION get_compartment_ocid_by_name(p_compartment_name IN VARCHAR2) RETURN CLOB; + + FUNCTION provision_adbs_tool( + compartment_name IN VARCHAR2, + db_name IN VARCHAR2, + display_name IN VARCHAR2 DEFAULT NULL, + workload_type IN VARCHAR2, + ecpu_count IN NUMBER, + storage_gb IN NUMBER, + region IN VARCHAR2, + data_guard IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL, + oci_vault_secret_id IN VARCHAR2, + is_auto_scaling_enabled IN NUMBER + ) RETURN CLOB; + + FUNCTION list_autonomous_databases( + region IN VARCHAR2, + compartment_name IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION drop_autonomous_database( + db_ocid IN VARCHAR2, + region IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION manage_autonomous_db_power( + db_ocid IN VARCHAR2, + region IN VARCHAR2, + action IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION update_autonomous_db_resources( + db_ocid IN VARCHAR2, + region IN VARCHAR2, + cpu_count IN NUMBER DEFAULT NULL, + storage_tbs IN NUMBER DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION get_autonomous_database_details( + db_ocid IN VARCHAR2, + region IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION stop_autonomous_database( + db_ocid IN VARCHAR2, + region IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION start_autonomous_database( + db_ocid IN VARCHAR2, + region IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION restart_autonomous_database( + db_ocid IN VARCHAR2, + region IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION get_maintenance_run_history_json( + maintenance_run_history_id IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION update_autonomous_database( + autonomous_database_id IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL, + backup_retention_period_in_days IN NUMBER DEFAULT NULL, + compute_model IN VARCHAR2 DEFAULT NULL, + in_memory_percentage IN NUMBER DEFAULT NULL, + local_adg_auto_failover_max_data_loss_limit IN NUMBER DEFAULT NULL, + cpu_core_count IN NUMBER DEFAULT NULL, + long_term_backup_schedule IN dbms_cloud_oci_database_long_term_back_up_schedule_details_t DEFAULT NULL, + compute_count IN NUMBER DEFAULT NULL, + ocpu_count IN NUMBER DEFAULT NULL, + data_storage_size_in_t_bs IN NUMBER DEFAULT NULL, + data_storage_size_in_g_bs IN NUMBER DEFAULT NULL, + display_name IN VARCHAR2 DEFAULT NULL, + is_free_tier IN NUMBER DEFAULT NULL, + admin_password IN VARCHAR2 DEFAULT NULL, + db_name IN VARCHAR2 DEFAULT NULL, + freeform_tags IN json_element_t DEFAULT NULL, + defined_tags IN json_element_t DEFAULT NULL, + db_workload IN VARCHAR2 DEFAULT NULL, + license_model IN VARCHAR2 DEFAULT NULL, + is_access_control_enabled IN NUMBER DEFAULT NULL, + whitelisted_ips IN dbms_cloud_oci_database_varchar2_tbl DEFAULT NULL, + are_primary_whitelisted_ips_used IN NUMBER DEFAULT NULL, + standby_whitelisted_ips IN dbms_cloud_oci_database_varchar2_tbl DEFAULT NULL, + is_auto_scaling_enabled IN NUMBER DEFAULT NULL, + is_refreshable_clone IN NUMBER DEFAULT NULL, + refreshable_mode IN VARCHAR2 DEFAULT NULL, + is_local_data_guard_enabled IN NUMBER DEFAULT NULL, + is_data_guard_enabled IN NUMBER DEFAULT NULL, + peer_db_id IN VARCHAR2 DEFAULT NULL, + db_version IN VARCHAR2 DEFAULT NULL, + open_mode IN VARCHAR2 DEFAULT NULL, + permission_level IN VARCHAR2 DEFAULT NULL, + subnet_id IN VARCHAR2 DEFAULT NULL, + private_endpoint_label IN VARCHAR2 DEFAULT NULL, + private_endpoint_ip IN VARCHAR2 DEFAULT NULL, + nsg_ids IN dbms_cloud_oci_database_varchar2_tbl DEFAULT NULL, + customer_contacts IN dbms_cloud_oci_database_customer_contact_tbl DEFAULT NULL, + is_mtls_connection_required IN NUMBER DEFAULT NULL, + resource_pool_leader_id IN VARCHAR2 DEFAULT NULL, + resource_pool_summary IN dbms_cloud_oci_database_resource_pool_summary_t DEFAULT NULL, + scheduled_operations IN dbms_cloud_oci_database_scheduled_operation_details_tbl DEFAULT NULL, + is_auto_scaling_for_storage_enabled IN NUMBER DEFAULT NULL, + max_cpu_core_count IN NUMBER DEFAULT NULL, + database_edition IN VARCHAR2 DEFAULT NULL, + db_tools_details IN dbms_cloud_oci_database_database_tool_tbl DEFAULT NULL, + secret_id IN VARCHAR2 DEFAULT NULL, + secret_version_number IN NUMBER DEFAULT NULL + ) RETURN CLOB; + + FUNCTION list_key_stores( + compartment_id IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION list_db_homes( + compartment_id IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION shrink_autonomous_database( + db_ocid IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION delete_key_store( + key_store_id IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION list_autonomous_container_database( + compartment_id IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION list_autonomous_database_backups( + compartment_id IN VARCHAR2, + autonomous_database_id IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; +END oci_autonomous_database_agents; +/ + +------------------------------------------------------------------------ +-- Package body +------------------------------------------------------------------------ +CREATE OR REPLACE PACKAGE BODY oci_autonomous_database_agents +AS + c_adb_agent CONSTANT VARCHAR2(64) := 'OCI_AUTONOMOUS_DATABASE'; + + FUNCTION get_agent_config( + schema_name IN VARCHAR2, + table_name IN VARCHAR2, + agent_name IN VARCHAR2 + ) RETURN CLOB + IS + l_sql VARCHAR2(4000); + l_cursor SYS_REFCURSOR; + l_config_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_key VARCHAR2(200); + l_value CLOB; + l_result_json JSON_OBJECT_T := JSON_OBJECT_T(); + BEGIN + l_sql := 'SELECT "KEY", "VALUE" FROM ' || schema_name || '.' || table_name || + ' WHERE "AGENT" = :agent'; + OPEN l_cursor FOR l_sql USING agent_name; + LOOP + FETCH l_cursor INTO l_key, l_value; + EXIT WHEN l_cursor%NOTFOUND; + l_config_json.put(l_key, l_value); + END LOOP; + CLOSE l_cursor; + + l_result_json.put('status', 'success'); + l_result_json.put('config_params', l_config_json); + RETURN l_result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + BEGIN + IF l_cursor%ISOPEN THEN + CLOSE l_cursor; + END IF; + EXCEPTION + WHEN OTHERS THEN NULL; + END; + l_result_json := JSON_OBJECT_T(); + l_result_json.put('status', 'error'); + l_result_json.put('message', 'Error: ' || SQLERRM); + RETURN l_result_json.to_clob(); + END get_agent_config; + + PROCEDURE resolve_credential( + p_credential_name IN VARCHAR2, + o_credential_name OUT VARCHAR2 + ) IS + l_current_user VARCHAR2(128) := SYS_CONTEXT('USERENV', 'CURRENT_USER'); + l_cfg_json CLOB; + l_cfg JSON_OBJECT_T; + l_params JSON_OBJECT_T; + BEGIN + o_credential_name := p_credential_name; + IF o_credential_name IS NOT NULL THEN + RETURN; + END IF; + + l_cfg_json := get_agent_config(l_current_user, 'OCI_AGENT_CONFIG', c_adb_agent); + l_cfg := JSON_OBJECT_T.parse(l_cfg_json); + IF l_cfg.get_string('status') = 'success' THEN + l_params := l_cfg.get_object('config_params'); + IF l_params.has('CREDENTIAL_NAME') THEN + o_credential_name := l_params.get_string('CREDENTIAL_NAME'); + END IF; + END IF; + EXCEPTION + WHEN OTHERS THEN + o_credential_name := p_credential_name; + END resolve_credential; + + FUNCTION list_subscribed_regions RETURN CLOB + IS + l_result_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_regions JSON_ARRAY_T := JSON_ARRAY_T(); + l_credential_name VARCHAR2(256); + tenancy_id VARCHAR2(128); + l_region VARCHAR2(128); + l_endpoint VARCHAR2(1000); + l_response CLOB; + l_data JSON_ARRAY_T; + l_obj JSON_OBJECT_T; + BEGIN + resolve_credential(NULL, l_credential_name); + IF l_credential_name IS NULL THEN + l_result_json.put('status','error'); + l_result_json.put('message','Missing credential_name (set in OCI_AGENT_CONFIG for OCI_AUTONOMOUS_DATABASE).'); + RETURN l_result_json.to_clob(); + END IF; + + SELECT + JSON_VALUE(cloud_identity, '$.TENANT_OCID') AS tenant_ocid, + JSON_VALUE(cloud_identity, '$.REGION') AS region + INTO tenancy_id, l_region + FROM v$pdbs; + + l_endpoint := + 'https://identity.' || l_region || '.oci.oraclecloud.com/20160918/regionSubscriptions?tenancyId=' || tenancy_id; + + l_response := DBMS_CLOUD.get_response_text( + DBMS_CLOUD.send_request( + credential_name => l_credential_name, + uri => l_endpoint, + method => DBMS_CLOUD.METHOD_GET + ) + ); + + l_data := JSON_ARRAY_T.parse(l_response); + FOR i IN 0 .. l_data.get_size() - 1 LOOP + l_obj := JSON_OBJECT_T(l_data.get(i)); + l_regions.append( + JSON_OBJECT( + 'region_name' VALUE l_obj.get_string('regionName'), + 'region_key' VALUE l_obj.get_string('regionKey'), + 'status' VALUE l_obj.get_string('status'), + 'is_home_region' VALUE CASE WHEN l_obj.get_boolean('isHomeRegion') THEN 'Yes' ELSE 'No' END + ) + ); + END LOOP; + + l_result_json.put('status','success'); + l_result_json.put('message','Successfully retrieved subscribed regions'); + l_result_json.put('total_regions', l_regions.get_size()); + l_result_json.put('regions', l_regions); + RETURN l_result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result_json := JSON_OBJECT_T(); + l_result_json.put('status','error'); + l_result_json.put('message','Failed to retrieve subscribed regions: ' || SQLERRM); + l_result_json.put('endpoint_used', l_endpoint); + RETURN l_result_json.to_clob(); + END list_subscribed_regions; + + FUNCTION list_compartments RETURN CLOB + IS + l_result_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_compartments JSON_ARRAY_T := JSON_ARRAY_T(); + l_credential_name VARCHAR2(256); + tenancy_id VARCHAR2(128); + l_region VARCHAR2(128); + l_endpoint VARCHAR2(1000); + l_response CLOB; + l_data JSON_ARRAY_T; + l_obj JSON_OBJECT_T; + BEGIN + resolve_credential(NULL, l_credential_name); + IF l_credential_name IS NULL THEN + l_result_json.put('status','error'); + l_result_json.put('message','Missing credential_name (set in OCI_AGENT_CONFIG for OCI_AUTONOMOUS_DATABASE).'); + RETURN l_result_json.to_clob(); + END IF; + + SELECT + JSON_VALUE(cloud_identity, '$.TENANT_OCID') AS tenant_ocid, + JSON_VALUE(cloud_identity, '$.REGION') AS region + INTO tenancy_id, l_region + FROM v$pdbs; + + l_endpoint := + 'https://identity.' || l_region || '.oci.oraclecloud.com/20160918/compartments?compartmentId=' || tenancy_id; + + l_response := DBMS_CLOUD.get_response_text( + DBMS_CLOUD.send_request( + credential_name => l_credential_name, + uri => l_endpoint, + method => DBMS_CLOUD.METHOD_GET + ) + ); + + l_data := JSON_ARRAY_T.parse(l_response); + FOR i IN 0 .. l_data.get_size() - 1 LOOP + l_obj := JSON_OBJECT_T(l_data.get(i)); + l_compartments.append( + JSON_OBJECT( + 'name' VALUE l_obj.get_string('name'), + 'id' VALUE l_obj.get_string('id'), + 'description' VALUE l_obj.get_string('description'), + 'lifecycle_state' VALUE l_obj.get_string('lifecycleState'), + 'time_created' VALUE l_obj.get_string('timeCreated') + ) + ); + END LOOP; + + l_result_json.put('status','success'); + l_result_json.put('message','Successfully retrieved compartments'); + l_result_json.put('total_compartments', l_compartments.get_size()); + l_result_json.put('compartments', l_compartments); + RETURN l_result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result_json := JSON_OBJECT_T(); + l_result_json.put('status','error'); + l_result_json.put('message','Failed to retrieve compartments: ' || SQLERRM); + l_result_json.put('endpoint_used', l_endpoint); + RETURN l_result_json.to_clob(); + END list_compartments; + + FUNCTION get_compartment_ocid_by_name(p_compartment_name IN VARCHAR2) RETURN CLOB + IS + l_comp_json_clob CLOB; + l_root JSON_OBJECT_T; + l_arr JSON_ARRAY_T; + l_obj JSON_OBJECT_T; + l_result_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_ocid VARCHAR2(4000); + BEGIN + l_comp_json_clob := list_compartments(); + l_root := JSON_OBJECT_T.parse(l_comp_json_clob); + IF l_root.get_string('status') <> 'success' THEN + RETURN l_comp_json_clob; + END IF; + + l_arr := l_root.get_array('compartments'); + FOR i IN 0 .. l_arr.get_size() - 1 LOOP + l_obj := JSON_OBJECT_T(l_arr.get(i)); + IF l_obj.get_string('name') = p_compartment_name THEN + l_ocid := l_obj.get_string('id'); + EXIT; + END IF; + END LOOP; + + IF l_ocid IS NOT NULL THEN + l_result_json.put('status','success'); + l_result_json.put('compartment_name', p_compartment_name); + l_result_json.put('compartment_ocid', l_ocid); + ELSE + l_result_json.put('status','error'); + l_result_json.put('message','Compartment "' || p_compartment_name || '" not found'); + END IF; + RETURN l_result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result_json := JSON_OBJECT_T(); + l_result_json.put('status','error'); + l_result_json.put('message','Unexpected error: ' || SQLERRM); + RETURN l_result_json.to_clob(); + END get_compartment_ocid_by_name; + + FUNCTION provision_adbs_tool( + compartment_name IN VARCHAR2, + db_name IN VARCHAR2, + display_name IN VARCHAR2 DEFAULT NULL, + workload_type IN VARCHAR2, + ecpu_count IN NUMBER, + storage_gb IN NUMBER, + region IN VARCHAR2, + data_guard IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL, + oci_vault_secret_id IN VARCHAR2, + is_auto_scaling_enabled IN NUMBER + ) RETURN CLOB + IS + in_details DBMS_CLOUD_OCI_DATABASE_CREATE_AUTONOMOUS_DATABASE_BASE_T := + DBMS_CLOUD_OCI_DATABASE_CREATE_AUTONOMOUS_DATABASE_BASE_T(); + resp DBMS_CLOUD_OCI_DB_DATABASE_CREATE_AUTONOMOUS_DATABASE_RESPONSE_T; + result_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_workload VARCHAR2(20); + l_compartment_id VARCHAR2(256); + l_credential VARCHAR2(256); + l_comp_json CLOB; + l_comp_obj JSON_OBJECT_T; + BEGIN + resolve_credential(credential_name, l_credential); + + l_comp_json := get_compartment_ocid_by_name(p_compartment_name => compartment_name); + l_comp_obj := JSON_OBJECT_T.parse(l_comp_json); + IF l_comp_obj.has('compartment_ocid') THEN + l_compartment_id := l_comp_obj.get_string('compartment_ocid'); + END IF; + + IF l_compartment_id IS NULL THEN + result_json.put('status','error'); + result_json.put('message','Failed to resolve compartment OCID for compartment_name=' || compartment_name); + RETURN result_json.to_clob(); + END IF; + + CASE UPPER(workload_type) + WHEN 'OLTP' THEN l_workload := 'OLTP'; + WHEN 'ADW' THEN l_workload := 'DW'; + WHEN 'JSON' THEN l_workload := 'JSON'; + WHEN 'APEX' THEN l_workload := 'APEX'; + ELSE l_workload := 'OLTP'; + END CASE; + + in_details.compartment_id := l_compartment_id; + in_details.db_name := UPPER(db_name); + in_details.compute_model := 'ECPU'; + in_details.compute_count := ecpu_count; + in_details.secret_id := oci_vault_secret_id; + in_details.db_workload := l_workload; + in_details.data_storage_size_in_g_bs := storage_gb; + in_details.display_name := display_name; + in_details.is_auto_scaling_enabled := is_auto_scaling_enabled; + + IF data_guard IS NOT NULL AND UPPER(data_guard) = 'ENABLED' THEN + in_details.is_data_guard_enabled := 1; + result_json.put('data_guard_enabled', 'ENABLED'); + ELSE + in_details.is_data_guard_enabled := 0; + result_json.put('data_guard_enabled', 'DISABLED'); + END IF; + + resp := DBMS_CLOUD_OCI_DB_DATABASE.CREATE_AUTONOMOUS_DATABASE( + create_autonomous_database_details => in_details, + credential_name => l_credential, + region => region + ); + + result_json.put('status', 'success'); + result_json.put('message', 'Autonomous Database provisioning initiated successfully'); + result_json.put('status_code', resp.status_code); + result_json.put('database_ocid', resp.response_body.id); + result_json.put('database_name', db_name); + result_json.put('workload_type', l_workload); + result_json.put('ecpu_count', ecpu_count); + result_json.put('storage_gb', storage_gb); + result_json.put('region', region); + RETURN result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + result_json := JSON_OBJECT_T(); + result_json.put('status', 'error'); + result_json.put('message', 'Failed to provision Autonomous Database: ' || SQLERRM); + RETURN result_json.to_clob(); + END provision_adbs_tool; + + FUNCTION list_autonomous_databases( + region IN VARCHAR2, + compartment_name IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_response CLOB; + l_endpoint VARCHAR2(1000); + l_result_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_db_array JSON_ARRAY_T := JSON_ARRAY_T(); + l_dbs_data JSON_ARRAY_T; + l_db_obj JSON_OBJECT_T; + l_db_ocid VARCHAR2(256); + l_credential VARCHAR2(256); + l_compartment_id VARCHAR2(256); + l_comp_json CLOB; + l_comp_obj JSON_OBJECT_T; + BEGIN + resolve_credential(credential_name, l_credential); + + l_comp_json := get_compartment_ocid_by_name(p_compartment_name => compartment_name); + l_comp_obj := JSON_OBJECT_T.parse(l_comp_json); + IF l_comp_obj.has('compartment_ocid') THEN + l_compartment_id := l_comp_obj.get_string('compartment_ocid'); + END IF; + IF l_compartment_id IS NULL THEN + l_result_json.put('status','error'); + l_result_json.put('message','Failed to resolve compartment OCID for compartment_name=' || compartment_name); + RETURN l_result_json.to_clob(); + END IF; + + l_endpoint := 'https://database.' || region || + '.oraclecloud.com/20160918/autonomousDatabases?compartmentId=' || l_compartment_id; + + l_response := DBMS_CLOUD.get_response_text( + DBMS_CLOUD.send_request( + credential_name => l_credential, + uri => l_endpoint, + method => DBMS_CLOUD.METHOD_GET + ) + ); + + l_dbs_data := JSON_ARRAY_T.parse(l_response); + FOR i IN 0 .. l_dbs_data.get_size() - 1 LOOP + l_db_obj := JSON_OBJECT_T(l_dbs_data.get(i)); + l_db_ocid := l_db_obj.get_string('id'); + l_db_array.append( + JSON_OBJECT( + 'display_name' VALUE l_db_obj.get_string('displayName'), + 'db_ocid' VALUE l_db_ocid, + 'db_workload' VALUE l_db_obj.get_string('dbWorkload'), + 'lifecycle' VALUE l_db_obj.get_string('lifecycleState'), + 'computeModel' VALUE l_db_obj.get_string('computeModel'), + 'computeCount' VALUE l_db_obj.get_string('computeCount'), + 'dataStorageSizeInGBs' VALUE l_db_obj.get_string('dataStorageSizeInGBs'), + 'dataStorageSizeInTBs' VALUE l_db_obj.get_string('dataStorageSizeInTBs') + ) + ); + END LOOP; + + l_result_json.put('status','success'); + l_result_json.put('message','Successfully retrieved Autonomous Databases'); + l_result_json.put('total_databases', l_db_array.get_size()); + l_result_json.put('databases', l_db_array); + RETURN l_result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result_json := JSON_OBJECT_T(); + l_result_json.put('status','error'); + l_result_json.put('message','Failed to list Autonomous Databases: ' || SQLERRM); + RETURN l_result_json.to_clob(); + END list_autonomous_databases; + + FUNCTION drop_autonomous_database( + db_ocid IN VARCHAR2, + region IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + resp DBMS_CLOUD_OCI_DB_DATABASE_DELETE_AUTONOMOUS_DATABASE_RESPONSE_T; + result_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + resp := DBMS_CLOUD_OCI_DB_DATABASE.DELETE_AUTONOMOUS_DATABASE( + autonomous_database_id => db_ocid, + region => region, + credential_name => l_credential + ); + + result_json.put('status', 'success'); + result_json.put('message', 'Autonomous Database deletion initiated successfully'); + result_json.put('status_code', resp.status_code); + result_json.put('database_ocid', db_ocid); + result_json.put('region', region); + RETURN result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + result_json := JSON_OBJECT_T(); + result_json.put('status', 'error'); + result_json.put('message', 'Failed to delete Autonomous Database: ' || SQLERRM); + result_json.put('database_ocid', db_ocid); + RETURN result_json.to_clob(); + END drop_autonomous_database; + + FUNCTION manage_autonomous_db_power( + db_ocid IN VARCHAR2, + region IN VARCHAR2, + action IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_endpoint VARCHAR2(1000); + l_response CLOB; + result_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + IF UPPER(action) = 'START' THEN + l_endpoint := 'https://database.' || region || '.oraclecloud.com/20160918/autonomousDatabases/' || db_ocid || '/actions/start'; + ELSIF UPPER(action) = 'STOP' THEN + l_endpoint := 'https://database.' || region || '.oraclecloud.com/20160918/autonomousDatabases/' || db_ocid || '/actions/stop'; + ELSE + result_json.put('status', 'error'); + result_json.put('message', 'Invalid action. Use START or STOP.'); + RETURN result_json.to_clob(); + END IF; + + l_response := DBMS_CLOUD.get_response_text( + DBMS_CLOUD.send_request( + credential_name => l_credential, + uri => l_endpoint, + method => DBMS_CLOUD.METHOD_POST, + headers => JSON_OBJECT('Content-Type' VALUE 'application/json') + ) + ); + + result_json.put('status', 'success'); + result_json.put('message', 'Database ' || LOWER(action) || ' request sent successfully'); + result_json.put('database_ocid', db_ocid); + result_json.put('region', region); + RETURN result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + result_json := JSON_OBJECT_T(); + result_json.put('status', 'error'); + result_json.put('message', 'Failed to ' || LOWER(action) || ' database: ' || SQLERRM); + RETURN result_json.to_clob(); + END manage_autonomous_db_power; + + FUNCTION update_autonomous_db_resources( + db_ocid IN VARCHAR2, + region IN VARCHAR2, + cpu_count IN NUMBER DEFAULT NULL, + storage_tbs IN NUMBER DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_endpoint VARCHAR2(1000); + l_response CLOB; + l_body VARCHAR2(4000); + result_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + l_endpoint := 'https://database.' || region || '.oraclecloud.com/20160918/autonomousDatabases/' || db_ocid; + + l_body := '{'; + IF cpu_count IS NOT NULL THEN + l_body := l_body || '"cpuCoreCount": ' || TO_CHAR(cpu_count); + END IF; + IF storage_tbs IS NOT NULL THEN + IF cpu_count IS NOT NULL THEN + l_body := l_body || ', '; + END IF; + l_body := l_body || '"dataStorageSizeInTBs": ' || TO_CHAR(storage_tbs); + END IF; + l_body := l_body || '}'; + + l_response := DBMS_CLOUD.get_response_text( + DBMS_CLOUD.send_request( + credential_name => l_credential, + uri => l_endpoint, + method => DBMS_CLOUD.METHOD_PUT, + headers => JSON_OBJECT('Content-Type' VALUE 'application/json'), + body => UTL_RAW.cast_to_raw(l_body) + ) + ); + + result_json.put('status', 'success'); + result_json.put('message', 'Database resource update request sent successfully'); + result_json.put('database_ocid', db_ocid); + result_json.put('region', region); + result_json.put('cpu_count', NVL(TO_CHAR(cpu_count), 'unchanged')); + result_json.put('storage_tbs', NVL(TO_CHAR(storage_tbs), 'unchanged')); + RETURN result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + result_json := JSON_OBJECT_T(); + result_json.put('status', 'error'); + result_json.put('message', 'Failed to update database resources: ' || SQLERRM); + RETURN result_json.to_clob(); + END update_autonomous_db_resources; + + FUNCTION get_autonomous_database_details( + db_ocid IN VARCHAR2, + region IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_resp DBMS_CLOUD_OCI_DB_DATABASE_GET_AUTONOMOUS_DATABASE_RESPONSE_T; + l_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + l_resp := DBMS_CLOUD_OCI_DB_DATABASE.GET_AUTONOMOUS_DATABASE( + autonomous_database_id => db_ocid, + opc_request_id => NULL, + region => region, + endpoint => NULL, + credential_name => l_credential + ); + + l_json.put('status', 'success'); + l_json.put('status_code', l_resp.status_code); + l_json.put('headers', l_resp.headers); + IF l_resp.response_body IS NOT NULL THEN + l_json.put('database_id', l_resp.response_body.id); + l_json.put('display_name', l_resp.response_body.display_name); + l_json.put('lifecycle_state', l_resp.response_body.lifecycle_state); + l_json.put('db_workload', l_resp.response_body.db_workload); + END IF; + RETURN l_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_json := JSON_OBJECT_T(); + l_json.put('status','error'); + l_json.put('message', SQLERRM); + RETURN l_json.to_clob(); + END get_autonomous_database_details; + + FUNCTION stop_autonomous_database( + db_ocid IN VARCHAR2, + region IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_response DBMS_CLOUD_OCI_DB_DATABASE_STOP_AUTONOMOUS_DATABASE_RESPONSE_T; + l_result_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + l_response := DBMS_CLOUD_OCI_DB_DATABASE.STOP_AUTONOMOUS_DATABASE( + autonomous_database_id => db_ocid, + if_match => NULL, + region => region, + endpoint => NULL, + credential_name => l_credential + ); + + l_result_json.put('status', 'success'); + l_result_json.put('message', 'Stop initiated'); + l_result_json.put('status_code', l_response.status_code); + l_result_json.put('headers', l_response.headers); + RETURN l_result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result_json := JSON_OBJECT_T(); + l_result_json.put('status','error'); + l_result_json.put('message', SQLERRM); + RETURN l_result_json.to_clob(); + END stop_autonomous_database; + + FUNCTION start_autonomous_database( + db_ocid IN VARCHAR2, + region IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_response DBMS_CLOUD_OCI_DB_DATABASE_START_AUTONOMOUS_DATABASE_RESPONSE_T; + l_result_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + l_response := DBMS_CLOUD_OCI_DB_DATABASE.START_AUTONOMOUS_DATABASE( + autonomous_database_id => db_ocid, + if_match => NULL, + region => region, + endpoint => NULL, + credential_name => l_credential + ); + + l_result_json.put('status', 'success'); + l_result_json.put('message', 'Start initiated'); + l_result_json.put('status_code', l_response.status_code); + l_result_json.put('headers', l_response.headers); + RETURN l_result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result_json := JSON_OBJECT_T(); + l_result_json.put('status','error'); + l_result_json.put('message', SQLERRM); + RETURN l_result_json.to_clob(); + END start_autonomous_database; + + FUNCTION restart_autonomous_database( + db_ocid IN VARCHAR2, + region IN VARCHAR2, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_response DBMS_CLOUD_OCI_DB_DATABASE_RESTART_AUTONOMOUS_DATABASE_RESPONSE_T; + l_result_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + l_response := DBMS_CLOUD_OCI_DB_DATABASE.RESTART_AUTONOMOUS_DATABASE( + autonomous_database_id => db_ocid, + if_match => NULL, + region => region, + endpoint => NULL, + credential_name => l_credential + ); + + l_result_json.put('status', 'success'); + l_result_json.put('message', 'Restart initiated'); + l_result_json.put('status_code', l_response.status_code); + l_result_json.put('headers', l_response.headers); + RETURN l_result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result_json := JSON_OBJECT_T(); + l_result_json.put('status','error'); + l_result_json.put('message', SQLERRM); + RETURN l_result_json.to_clob(); + END restart_autonomous_database; + + FUNCTION get_maintenance_run_history_json( + maintenance_run_history_id IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_response DBMS_CLOUD_OCI_DB_DATABASE_GET_MAINTENANCE_RUN_HISTORY_RESPONSE_T; + l_result_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + l_response := DBMS_CLOUD_OCI_DB_DATABASE.GET_MAINTENANCE_RUN_HISTORY( + maintenance_run_history_id => maintenance_run_history_id, + region => region, + endpoint => NULL, + credential_name => l_credential + ); + + l_result_json.put('status', 'success'); + l_result_json.put('message', 'Maintenance run history retrieved'); + l_result_json.put('status_code', l_response.status_code); + l_result_json.put('headers', l_response.headers); + IF l_response.response_body IS NOT NULL THEN + l_result_json.put('history_id', l_response.response_body.id); + END IF; + RETURN l_result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result_json := JSON_OBJECT_T(); + l_result_json.put('status','error'); + l_result_json.put('message', SQLERRM); + RETURN l_result_json.to_clob(); + END get_maintenance_run_history_json; + + FUNCTION update_autonomous_database( + autonomous_database_id IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL, + backup_retention_period_in_days IN NUMBER DEFAULT NULL, + compute_model IN VARCHAR2 DEFAULT NULL, + in_memory_percentage IN NUMBER DEFAULT NULL, + local_adg_auto_failover_max_data_loss_limit IN NUMBER DEFAULT NULL, + cpu_core_count IN NUMBER DEFAULT NULL, + long_term_backup_schedule IN dbms_cloud_oci_database_long_term_back_up_schedule_details_t DEFAULT NULL, + compute_count IN NUMBER DEFAULT NULL, + ocpu_count IN NUMBER DEFAULT NULL, + data_storage_size_in_t_bs IN NUMBER DEFAULT NULL, + data_storage_size_in_g_bs IN NUMBER DEFAULT NULL, + display_name IN VARCHAR2 DEFAULT NULL, + is_free_tier IN NUMBER DEFAULT NULL, + admin_password IN VARCHAR2 DEFAULT NULL, + db_name IN VARCHAR2 DEFAULT NULL, + freeform_tags IN json_element_t DEFAULT NULL, + defined_tags IN json_element_t DEFAULT NULL, + db_workload IN VARCHAR2 DEFAULT NULL, + license_model IN VARCHAR2 DEFAULT NULL, + is_access_control_enabled IN NUMBER DEFAULT NULL, + whitelisted_ips IN dbms_cloud_oci_database_varchar2_tbl DEFAULT NULL, + are_primary_whitelisted_ips_used IN NUMBER DEFAULT NULL, + standby_whitelisted_ips IN dbms_cloud_oci_database_varchar2_tbl DEFAULT NULL, + is_auto_scaling_enabled IN NUMBER DEFAULT NULL, + is_refreshable_clone IN NUMBER DEFAULT NULL, + refreshable_mode IN VARCHAR2 DEFAULT NULL, + is_local_data_guard_enabled IN NUMBER DEFAULT NULL, + is_data_guard_enabled IN NUMBER DEFAULT NULL, + peer_db_id IN VARCHAR2 DEFAULT NULL, + db_version IN VARCHAR2 DEFAULT NULL, + open_mode IN VARCHAR2 DEFAULT NULL, + permission_level IN VARCHAR2 DEFAULT NULL, + subnet_id IN VARCHAR2 DEFAULT NULL, + private_endpoint_label IN VARCHAR2 DEFAULT NULL, + private_endpoint_ip IN VARCHAR2 DEFAULT NULL, + nsg_ids IN dbms_cloud_oci_database_varchar2_tbl DEFAULT NULL, + customer_contacts IN dbms_cloud_oci_database_customer_contact_tbl DEFAULT NULL, + is_mtls_connection_required IN NUMBER DEFAULT NULL, + resource_pool_leader_id IN VARCHAR2 DEFAULT NULL, + resource_pool_summary IN dbms_cloud_oci_database_resource_pool_summary_t DEFAULT NULL, + scheduled_operations IN dbms_cloud_oci_database_scheduled_operation_details_tbl DEFAULT NULL, + is_auto_scaling_for_storage_enabled IN NUMBER DEFAULT NULL, + max_cpu_core_count IN NUMBER DEFAULT NULL, + database_edition IN VARCHAR2 DEFAULT NULL, + db_tools_details IN dbms_cloud_oci_database_database_tool_tbl DEFAULT NULL, + secret_id IN VARCHAR2 DEFAULT NULL, + secret_version_number IN NUMBER DEFAULT NULL + ) RETURN CLOB + IS + l_details DBMS_CLOUD_OCI_DATABASE_UPDATE_AUTONOMOUS_DATABASE_DETAILS_T := + DBMS_CLOUD_OCI_DATABASE_UPDATE_AUTONOMOUS_DATABASE_DETAILS_T(); + l_response DBMS_CLOUD_OCI_DB_DATABASE_UPDATE_AUTONOMOUS_DATABASE_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + + IF backup_retention_period_in_days IS NOT NULL THEN l_details.backup_retention_period_in_days := backup_retention_period_in_days; END IF; + IF compute_model IS NOT NULL THEN l_details.compute_model := compute_model; END IF; + IF in_memory_percentage IS NOT NULL THEN l_details.in_memory_percentage := in_memory_percentage; END IF; + IF local_adg_auto_failover_max_data_loss_limit IS NOT NULL THEN l_details.local_adg_auto_failover_max_data_loss_limit := local_adg_auto_failover_max_data_loss_limit; END IF; + IF cpu_core_count IS NOT NULL THEN l_details.cpu_core_count := cpu_core_count; END IF; + IF long_term_backup_schedule IS NOT NULL THEN l_details.long_term_backup_schedule := long_term_backup_schedule; END IF; + IF compute_count IS NOT NULL THEN l_details.compute_count := compute_count; END IF; + IF ocpu_count IS NOT NULL THEN l_details.ocpu_count := ocpu_count; END IF; + IF data_storage_size_in_t_bs IS NOT NULL THEN l_details.data_storage_size_in_t_bs := data_storage_size_in_t_bs; END IF; + IF data_storage_size_in_g_bs IS NOT NULL THEN l_details.data_storage_size_in_g_bs := data_storage_size_in_g_bs; END IF; + IF display_name IS NOT NULL THEN l_details.display_name := display_name; END IF; + IF is_free_tier IS NOT NULL THEN l_details.is_free_tier := is_free_tier; END IF; + IF admin_password IS NOT NULL THEN l_details.admin_password := admin_password; END IF; + IF db_name IS NOT NULL THEN l_details.db_name := db_name; END IF; + IF freeform_tags IS NOT NULL THEN l_details.freeform_tags := freeform_tags; END IF; + IF defined_tags IS NOT NULL THEN l_details.defined_tags := defined_tags; END IF; + IF db_workload IS NOT NULL THEN l_details.db_workload := db_workload; END IF; + IF license_model IS NOT NULL THEN l_details.license_model := license_model; END IF; + IF is_access_control_enabled IS NOT NULL THEN l_details.is_access_control_enabled := is_access_control_enabled; END IF; + IF whitelisted_ips IS NOT NULL THEN l_details.whitelisted_ips := whitelisted_ips; END IF; + IF are_primary_whitelisted_ips_used IS NOT NULL THEN l_details.are_primary_whitelisted_ips_used := are_primary_whitelisted_ips_used; END IF; + IF standby_whitelisted_ips IS NOT NULL THEN l_details.standby_whitelisted_ips := standby_whitelisted_ips; END IF; + IF is_auto_scaling_enabled IS NOT NULL THEN l_details.is_auto_scaling_enabled := is_auto_scaling_enabled; END IF; + IF is_refreshable_clone IS NOT NULL THEN l_details.is_refreshable_clone := is_refreshable_clone; END IF; + IF refreshable_mode IS NOT NULL THEN l_details.refreshable_mode := refreshable_mode; END IF; + IF is_local_data_guard_enabled IS NOT NULL THEN l_details.is_local_data_guard_enabled := is_local_data_guard_enabled; END IF; + IF is_data_guard_enabled IS NOT NULL THEN l_details.is_data_guard_enabled := is_data_guard_enabled; END IF; + IF peer_db_id IS NOT NULL THEN l_details.peer_db_id := peer_db_id; END IF; + IF db_version IS NOT NULL THEN l_details.db_version := db_version; END IF; + IF open_mode IS NOT NULL THEN l_details.open_mode := open_mode; END IF; + IF permission_level IS NOT NULL THEN l_details.permission_level := permission_level; END IF; + IF subnet_id IS NOT NULL THEN l_details.subnet_id := subnet_id; END IF; + IF private_endpoint_label IS NOT NULL THEN l_details.private_endpoint_label := private_endpoint_label; END IF; + IF private_endpoint_ip IS NOT NULL THEN l_details.private_endpoint_ip := private_endpoint_ip; END IF; + IF nsg_ids IS NOT NULL THEN l_details.nsg_ids := nsg_ids; END IF; + IF customer_contacts IS NOT NULL THEN l_details.customer_contacts := customer_contacts; END IF; + IF is_mtls_connection_required IS NOT NULL THEN l_details.is_mtls_connection_required := is_mtls_connection_required; END IF; + IF resource_pool_leader_id IS NOT NULL THEN l_details.resource_pool_leader_id := resource_pool_leader_id; END IF; + IF resource_pool_summary IS NOT NULL THEN l_details.resource_pool_summary := resource_pool_summary; END IF; + IF scheduled_operations IS NOT NULL THEN l_details.scheduled_operations := scheduled_operations; END IF; + IF is_auto_scaling_for_storage_enabled IS NOT NULL THEN l_details.is_auto_scaling_for_storage_enabled := is_auto_scaling_for_storage_enabled; END IF; + IF max_cpu_core_count IS NOT NULL THEN l_details.max_cpu_core_count := max_cpu_core_count; END IF; + IF database_edition IS NOT NULL THEN l_details.database_edition := database_edition; END IF; + IF db_tools_details IS NOT NULL THEN l_details.db_tools_details := db_tools_details; END IF; + IF secret_id IS NOT NULL THEN l_details.secret_id := secret_id; END IF; + IF secret_version_number IS NOT NULL THEN l_details.secret_version_number := secret_version_number; END IF; + + l_response := DBMS_CLOUD_OCI_DB_DATABASE.UPDATE_AUTONOMOUS_DATABASE( + autonomous_database_id => autonomous_database_id, + update_autonomous_database_details => l_details, + if_match => NULL, + opc_request_id => NULL, + region => region, + endpoint => NULL, + credential_name => l_credential + ); + + l_result.put('status','success'); + l_result.put('message','Update initiated'); + l_result.put('status_code', l_response.status_code); + l_result.put('headers', l_response.headers); + IF l_response.response_body IS NOT NULL THEN + l_result.put('database_id', l_response.response_body.id); + l_result.put('display_name', l_response.response_body.display_name); + l_result.put('lifecycle_state', l_response.response_body.lifecycle_state); + END IF; + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status','error'); + l_result.put('message', SQLERRM); + RETURN l_result.to_clob(); + END update_autonomous_database; + + FUNCTION list_key_stores( + compartment_id IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_response DBMS_CLOUD_OCI_DB_DATABASE_LIST_KEY_STORES_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_keystores JSON_ARRAY_T := JSON_ARRAY_T(); + l_summary_tbl DBMS_CLOUD_OCI_DATABASE_KEY_STORE_SUMMARY_TBL; + l_summary DBMS_CLOUD_OCI_DATABASE_KEY_STORE_SUMMARY_T; + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + l_response := DBMS_CLOUD_OCI_DB_DATABASE.LIST_KEY_STORES( + compartment_id => compartment_id, + limit => NULL, + page => NULL, + opc_request_id => NULL, + region => region, + endpoint => NULL, + credential_name => l_credential + ); + + l_result.put('status','success'); + l_result.put('status_code', l_response.status_code); + l_result.put('headers', l_response.headers); + l_summary_tbl := l_response.response_body; + FOR i IN 1 .. l_summary_tbl.COUNT LOOP + l_summary := l_summary_tbl(i); + l_keystores.append( + JSON_OBJECT( + 'id' VALUE l_summary.id, + 'display_name' VALUE l_summary.display_name, + 'compartment_id' VALUE l_summary.compartment_id, + 'lifecycle_state' VALUE l_summary.lifecycle_state, + 'time_created' VALUE TO_CHAR(l_summary.time_created, 'YYYY-MM-DD"T"HH24:MI:SS"Z"') + ) + ); + END LOOP; + l_result.put('keystores', l_keystores); + l_result.put('next_page', l_response.headers.get_string('opc-next-page')); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status','error'); + l_result.put('message', SQLERRM); + RETURN l_result.to_clob(); + END list_key_stores; + + FUNCTION list_db_homes( + compartment_id IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_response DBMS_CLOUD_OCI_DB_DATABASE_LIST_DB_HOMES_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_array JSON_ARRAY_T := JSON_ARRAY_T(); + l_summaries DBMS_CLOUD_OCI_DATABASE_DB_HOME_SUMMARY_TBL; + l_summary DBMS_CLOUD_OCI_DATABASE_DB_HOME_SUMMARY_T; + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + l_response := DBMS_CLOUD_OCI_DB_DATABASE.LIST_DB_HOMES( + compartment_id => compartment_id, + db_system_id => NULL, + vm_cluster_id => NULL, + backup_id => NULL, + db_version => NULL, + limit => NULL, + page => NULL, + sort_by => NULL, + sort_order => NULL, + lifecycle_state => NULL, + display_name => NULL, + region => region, + endpoint => NULL, + credential_name => l_credential + ); + + l_result.put('status','success'); + l_result.put('status_code', l_response.status_code); + l_result.put('headers', l_response.headers); + l_summaries := l_response.response_body; + FOR i IN 1 .. l_summaries.COUNT LOOP + l_summary := l_summaries(i); + l_array.append( + JSON_OBJECT( + 'id' VALUE l_summary.id, + 'display_name' VALUE l_summary.display_name, + 'db_version' VALUE l_summary.db_version, + 'lifecycle_state' VALUE l_summary.lifecycle_state + ) + ); + END LOOP; + l_result.put('db_homes', l_array); + l_result.put('next_page', l_response.headers.get_string('opc-next-page')); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status','error'); + l_result.put('message', SQLERRM); + RETURN l_result.to_clob(); + END list_db_homes; + + FUNCTION shrink_autonomous_database( + db_ocid IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_response DBMS_CLOUD_OCI_DB_DATABASE_SHRINK_AUTONOMOUS_DATABASE_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + l_response := DBMS_CLOUD_OCI_DB_DATABASE.SHRINK_AUTONOMOUS_DATABASE( + autonomous_database_id => db_ocid, + if_match => NULL, + region => region, + endpoint => NULL, + credential_name => l_credential + ); + + l_result.put('status','success'); + l_result.put('message','Shrink initiated'); + l_result.put('status_code', l_response.status_code); + l_result.put('headers', l_response.headers); + IF l_response.response_body IS NOT NULL THEN + l_result.put('database_id', l_response.response_body.id); + l_result.put('display_name', l_response.response_body.display_name); + l_result.put('lifecycle_state', l_response.response_body.lifecycle_state); + END IF; + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status','error'); + l_result.put('message', SQLERRM); + RETURN l_result.to_clob(); + END shrink_autonomous_database; + + FUNCTION delete_key_store( + key_store_id IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_response DBMS_CLOUD_OCI_DB_DATABASE_DELETE_KEY_STORE_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + l_response := DBMS_CLOUD_OCI_DB_DATABASE.DELETE_KEY_STORE( + key_store_id => key_store_id, + if_match => NULL, + opc_request_id => NULL, + region => region, + endpoint => NULL, + credential_name => l_credential + ); + + l_result.put('status','success'); + l_result.put('message','Key store deletion initiated'); + l_result.put('status_code', l_response.status_code); + l_result.put('headers', l_response.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status','error'); + l_result.put('message', SQLERRM); + RETURN l_result.to_clob(); + END delete_key_store; + + FUNCTION list_autonomous_container_database( + compartment_id IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_response DBMS_CLOUD_OCI_DB_DATABASE_LIST_AUTONOMOUS_CONTAINER_DATABASES_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_array JSON_ARRAY_T := JSON_ARRAY_T(); + l_item JSON_OBJECT_T; + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + l_response := DBMS_CLOUD_OCI_DB_DATABASE.LIST_AUTONOMOUS_CONTAINER_DATABASES( + compartment_id => compartment_id, + region => region, + credential_name => l_credential + ); + + FOR i IN 1 .. l_response.response_body.COUNT LOOP + l_item := JSON_OBJECT_T(); + l_item.put('id', l_response.response_body(i).id); + l_item.put('display_name', l_response.response_body(i).display_name); + l_item.put('db_unique_name', l_response.response_body(i).db_unique_name); + l_item.put('db_name', l_response.response_body(i).db_name); + l_item.put('lifecycle_state', l_response.response_body(i).lifecycle_state); + l_item.put('time_created', TO_CHAR(l_response.response_body(i).time_created, 'YYYY-MM-DD"T"HH24:MI:SS"Z"')); + l_item.put('db_version', l_response.response_body(i).db_version); + l_item.put('availability_domain', l_response.response_body(i).availability_domain); + l_item.put('compute_model', l_response.response_body(i).compute_model); + l_item.put('available_cpus', l_response.response_body(i).available_cpus); + l_item.put('total_cpus', l_response.response_body(i).total_cpus); + l_array.append(l_item); + END LOOP; + + l_result.put('status','success'); + l_result.put('message','Autonomous Container Databases listed'); + l_result.put('autonomous_containers', l_array); + l_result.put('status_code', l_response.status_code); + l_result.put('headers', l_response.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status','error'); + l_result.put('message', SQLERRM); + RETURN l_result.to_clob(); + END list_autonomous_container_database; + + FUNCTION list_autonomous_database_backups( + compartment_id IN VARCHAR2, + autonomous_database_id IN VARCHAR2, + region IN VARCHAR2 DEFAULT NULL, + credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_response DBMS_CLOUD_OCI_DB_DATABASE_LIST_AUTONOMOUS_DATABASE_BACKUPS_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_array JSON_ARRAY_T := JSON_ARRAY_T(); + l_item JSON_OBJECT_T; + l_dest_obj JSON_OBJECT_T; + l_credential VARCHAR2(256); + BEGIN + resolve_credential(credential_name, l_credential); + l_response := DBMS_CLOUD_OCI_DB_DATABASE.LIST_AUTONOMOUS_DATABASE_BACKUPS( + compartment_id => compartment_id, + autonomous_database_id => autonomous_database_id, + region => region, + credential_name => l_credential + ); + + FOR i IN 1 .. l_response.response_body.COUNT LOOP + l_item := JSON_OBJECT_T(); + l_item.put('id', l_response.response_body(i).id); + l_item.put('display_name', l_response.response_body(i).display_name); + l_item.put('lifecycle_state', l_response.response_body(i).lifecycle_state); + l_item.put('db_version', l_response.response_body(i).db_version); + l_item.put('size_in_t_bs', l_response.response_body(i).size_in_t_bs); + l_item.put('database_size_in_t_bs', l_response.response_body(i).database_size_in_t_bs); + l_item.put('retention_period_in_days', l_response.response_body(i).retention_period_in_days); + l_item.put('time_started', TO_CHAR(l_response.response_body(i).time_started, 'YYYY-MM-DD"T"HH24:MI:SS"Z"')); + l_item.put('time_ended', TO_CHAR(l_response.response_body(i).time_ended, 'YYYY-MM-DD"T"HH24:MI:SS"Z"')); + l_item.put('time_available_till', TO_CHAR(l_response.response_body(i).time_available_till, 'YYYY-MM-DD"T"HH24:MI:SS"Z"')); + + l_dest_obj := JSON_OBJECT_T(); + IF l_response.response_body(i).backup_destination_details IS NOT NULL THEN + l_dest_obj.put('id', l_response.response_body(i).backup_destination_details.id); + l_dest_obj.put('type', l_response.response_body(i).backup_destination_details.l_type); + l_dest_obj.put('vpc_user', l_response.response_body(i).backup_destination_details.vpc_user); + END IF; + l_item.put('backup_destination', l_dest_obj); + + l_array.append(l_item); + END LOOP; + + l_result.put('status','success'); + l_result.put('message','Autonomous DB backups retrieved'); + l_result.put('backups', l_array); + l_result.put('status_code', l_response.status_code); + l_result.put('headers', l_response.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status','error'); + l_result.put('message', SQLERRM); + RETURN l_result.to_clob(); + END list_autonomous_database_backups; + +END oci_autonomous_database_agents; +/ + +------------------------------------------------------------------------------- +-- This procedure installs or refreshes the OCI Autonomous Database AI Agent tools. +------------------------------------------------------------------------------- +CREATE OR REPLACE PROCEDURE initialize_autonomous_database_tools +IS + PROCEDURE drop_tool_if_exists (tool_name IN VARCHAR2) IS + l_tool_count NUMBER; + l_sql CLOB; + BEGIN + l_sql := 'SELECT COUNT(*) FROM USER_AI_AGENT_TOOLS WHERE TOOL_NAME = :1'; + EXECUTE IMMEDIATE l_sql INTO l_tool_count USING tool_name; + IF l_tool_count > 0 THEN + DBMS_CLOUD_AI_AGENT.DROP_TOOL(tool_name); + END IF; + END drop_tool_if_exists; +BEGIN + drop_tool_if_exists(tool_name => 'LIST_SUBSCRIBED_REGIONS_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_SUBSCRIBED_REGIONS_TOOL', + attributes => '{ + "instruction": "Lists all Oracle Cloud regions subscribed by the current tenancy. Use to help the user pick a region.", + "function": "oci_autonomous_database_agents.list_subscribed_regions" + }', + description => 'Tool for listing subscribed OCI regions' + ); + + drop_tool_if_exists(tool_name => 'LIST_COMPARTMENTS_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_COMPARTMENTS_TOOL', + attributes => '{ + "instruction": "Lists compartments in the tenancy. Use to help the user pick a compartment for Autonomous Database operations.", + "function": "oci_autonomous_database_agents.list_compartments" + }', + description => 'Tool for listing compartments' + ); + + drop_tool_if_exists(tool_name => 'GET_COMPARTMENT_OCID_BY_NAME_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'GET_COMPARTMENT_OCID_BY_NAME_TOOL', + attributes => '{ + "instruction": "Given a compartment name, return its OCID (uses LIST_COMPARTMENTS_TOOL internally).", + "function": "oci_autonomous_database_agents.get_compartment_ocid_by_name" + }', + description => 'Tool to get compartment OCID by name' + ); + + drop_tool_if_exists(tool_name => 'ADBS_PROVISIONING_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'ADBS_PROVISIONING_TOOL', + attributes => '{ + "instruction": "Provisions an Oracle Autonomous Database. Use LIST_SUBSCRIBED_REGIONS_TOOL and LIST_COMPARTMENTS_TOOL to gather prerequisites, then confirm all choices before provisioning.", + "function": "oci_autonomous_database_agents.provision_adbs_tool" + }', + description => 'Tool for provisioning Oracle Autonomous Databases' + ); + + drop_tool_if_exists(tool_name => 'LIST_AUTONOMOUS_DATABASES_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_AUTONOMOUS_DATABASES_TOOL', + attributes => '{ + "instruction": "Lists Oracle Autonomous Databases in a given compartment and region.", + "function": "oci_autonomous_database_agents.list_autonomous_databases" + }', + description => 'Tool for listing Oracle Autonomous Databases' + ); + + drop_tool_if_exists(tool_name => 'ADBS_UNPROVISION_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'ADBS_UNPROVISION_TOOL', + attributes => '{ + "instruction": "Drops an Oracle Autonomous Database (confirm before calling).", + "function": "oci_autonomous_database_agents.drop_autonomous_database" + }', + description => 'Tool for dropping Oracle Autonomous Databases' + ); + + drop_tool_if_exists(tool_name => 'MANAGE_AUTONOMOUS_DB_POWER_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'MANAGE_AUTONOMOUS_DB_POWER_TOOL', + attributes => '{ + "instruction": "Starts or stops an Autonomous Database based on action START or STOP (confirm before calling).", + "function": "oci_autonomous_database_agents.manage_autonomous_db_power" + }', + description => 'Tool for starting or stopping an Autonomous Database' + ); + + drop_tool_if_exists(tool_name => 'UPDATE_AUTONOMOUS_DB_RESOURCES_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'UPDATE_AUTONOMOUS_DB_RESOURCES_TOOL', + attributes => '{ + "instruction": "Updates the CPU core count and/or storage size (TB) for an Autonomous Database (confirm before calling).", + "function": "oci_autonomous_database_agents.update_autonomous_db_resources" + }', + description => 'Tool for updating CPU and storage for an Autonomous Database' + ); + + drop_tool_if_exists(tool_name => 'GET_AUTONOMOUS_DATABASE_DETAILS_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'GET_AUTONOMOUS_DATABASE_DETAILS_TOOL', + attributes => '{ + "instruction": "Fetches metadata for a specific Autonomous Database by OCID.", + "function": "oci_autonomous_database_agents.get_autonomous_database_details" + }', + description => 'Tool for getting Autonomous Database details' + ); + + drop_tool_if_exists(tool_name => 'STOP_AUTONOMOUS_DATABASE_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'STOP_AUTONOMOUS_DATABASE_TOOL', + attributes => '{ + "instruction": "Stops the specified Autonomous Database (confirm before calling).", + "function": "oci_autonomous_database_agents.stop_autonomous_database" + }', + description => 'Tool for stopping an Autonomous Database' + ); + + drop_tool_if_exists(tool_name => 'START_AUTONOMOUS_DATABASE_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'START_AUTONOMOUS_DATABASE_TOOL', + attributes => '{ + "instruction": "Starts the specified Autonomous Database.", + "function": "oci_autonomous_database_agents.start_autonomous_database" + }', + description => 'Tool for starting an Autonomous Database' + ); + + drop_tool_if_exists(tool_name => 'DATABASE_RESTART_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'DATABASE_RESTART_TOOL', + attributes => '{ + "instruction": "Restarts the specified Autonomous Database (confirm before calling).", + "function": "oci_autonomous_database_agents.restart_autonomous_database" + }', + description => 'Tool for restarting an Autonomous Database' + ); + + drop_tool_if_exists(tool_name => 'GET_MAINTENANCE_RUN_HISTORY_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'GET_MAINTENANCE_RUN_HISTORY_TOOL', + attributes => '{ + "instruction": "Retrieve details for a specific maintenance run history by maintenance_run_history_id.", + "function": "oci_autonomous_database_agents.get_maintenance_run_history_json" + }', + description => 'Tool to fetch Autonomous Database maintenance run history' + ); + + drop_tool_if_exists(tool_name => 'UPDATE_AUTONOMOUS_DATABASE_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'UPDATE_AUTONOMOUS_DATABASE_TOOL', + attributes => '{ + "instruction": "Update one or more attributes of an Autonomous Database. Only include parameters explicitly provided by the user; omit any omitted values.", + "function": "oci_autonomous_database_agents.update_autonomous_database" + }', + description => 'Tool for updating Autonomous Database attributes' + ); + + drop_tool_if_exists(tool_name => 'LIST_KEY_STORES_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_KEY_STORES_TOOL', + attributes => '{ + "instruction": "List key stores in a given compartment.", + "function": "oci_autonomous_database_agents.list_key_stores" + }', + description => 'Tool for listing Autonomous Database key stores' + ); + + drop_tool_if_exists(tool_name => 'LIST_DB_HOMES_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_DB_HOMES_TOOL', + attributes => '{ + "instruction": "List DB homes in a given compartment.", + "function": "oci_autonomous_database_agents.list_db_homes" + }', + description => 'Tool for listing DB homes' + ); + + drop_tool_if_exists(tool_name => 'SHRINK_AUTONOMOUS_DATABASE_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'SHRINK_AUTONOMOUS_DATABASE_TOOL', + attributes => '{ + "instruction": "Shrink an Autonomous Database''s storage (confirm before calling).", + "function": "oci_autonomous_database_agents.shrink_autonomous_database" + }', + description => 'Tool for shrinking an Autonomous Database storage' + ); + + drop_tool_if_exists(tool_name => 'DELETE_KEY_STORE_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'DELETE_KEY_STORE_TOOL', + attributes => '{ + "instruction": "Delete a key store by key_store_id (confirm before calling).", + "function": "oci_autonomous_database_agents.delete_key_store" + }', + description => 'Tool for deleting a key store' + ); + + drop_tool_if_exists(tool_name => 'LIST_ACDS_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_ACDS_TOOL', + attributes => '{ + "instruction": "List Autonomous Container Databases in a compartment.", + "function": "oci_autonomous_database_agents.list_autonomous_container_database" + }', + description => 'Tool to list Autonomous Container Databases' + ); + + drop_tool_if_exists(tool_name => 'LIST_ADB_BACKUPS_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_ADB_BACKUPS_TOOL', + attributes => '{ + "instruction": "List Autonomous Database backups for a given compartment and autonomous_database_id.", + "function": "oci_autonomous_database_agents.list_autonomous_database_backups" + }', + description => 'Tool to list Autonomous Database backups' + ); + + DBMS_OUTPUT.PUT_LINE('initialize_autonomous_database_tools completed.'); +EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Error in initialize_autonomous_database_tools: ' || SQLERRM); + RAISE; +END initialize_autonomous_database_tools; +/ + +BEGIN + initialize_autonomous_database_tools; +END; +/ + +alter session set current_schema = ADMIN; diff --git a/autonomous-ai-agents/oci_network_load_balancer/oci_network_load_balancer_agent.sql b/autonomous-ai-agents/oci_network_load_balancer/oci_network_load_balancer_agent.sql new file mode 100644 index 0000000..76f0f43 --- /dev/null +++ b/autonomous-ai-agents/oci_network_load_balancer/oci_network_load_balancer_agent.sql @@ -0,0 +1,250 @@ +rem ============================================================================ +rem LICENSE +rem Copyright (c) 2025 Oracle and/or its affiliates. +rem Licensed under the Universal Permissive License (UPL), Version 1.0 +rem https://oss.oracle.com/licenses/upl/ +rem +rem NAME +rem oci_network_load_balancer_agent.sql +rem +rem DESCRIPTION +rem Installer and configuration script for OCI Network Load Balancer +rem AI Agent using DBMS_CLOUD_AI_AGENT +rem (Select AI / Oracle AI Database). +rem +rem This script performs an interactive installation of an +rem OCI Network Load Balancer AI Agent by: +rem - Prompting for target schema and AI Profile +rem - Granting required privileges to the target schema +rem - Creating an installer procedure in the target schema +rem - Registering an OCI Network Load Balancer Task +rem - Creating an OCI Network Load Balancer AI Agent +rem bound to the specified AI Profile +rem - Creating an OCI Network Load Balancer Team linking +rem the agent and task +rem - Executing the installer procedure to complete setup +rem +rem RELEASE VERSION +rem 1.0 +rem +rem RELEASE DATE +rem 26-Jan-2026 +rem +rem MAJOR CHANGES IN THIS RELEASE +rem - Initial release +rem - Added OCI Network Load Balancer task, agent, and team +rem - Interactive installer with schema and AI profile prompts +rem +rem SCRIPT STRUCTURE +rem 1. Initialization: +rem - Enable SQL*Plus settings and error handling +rem - Prompt for target schema and AI profile +rem +rem 2. Grants: +rem - Grant DBMS_CLOUD_AI_AGENT and DBMS_CLOUD privileges +rem to the target schema +rem +rem 3. Installer Procedure Creation: +rem - Create INSTALL_OCI_NETWORK_LOAD_BALANCER_AGENT +rem procedure in the target schema +rem +rem 4. AI Registration: +rem - Drop and create OCI_NETWORK_LOAD_BALANCER_TASKS +rem - Drop and create OCI_NETWORK_LOAD_BALANCER_ADVISOR +rem agent +rem - Drop and create OCI_NETWORK_LOAD_BALANCER_TEAM +rem +rem 5. Execution: +rem - Execute installer procedure with AI profile parameter +rem +rem INSTALL INSTRUCTIONS +rem 1. Connect as ADMIN or a user with required privileges +rem +rem 2. Run the script using SQL*Plus or SQLcl: +rem +rem sqlplus admin@db @oci_network_load_balancer_agent.sql +rem +rem 3. Provide inputs when prompted: +rem - Target schema name +rem - AI Profile name +rem +rem 4. Verify installation by confirming: +rem - OCI_NETWORK_LOAD_BALANCER_TASKS task exists +rem - OCI_NETWORK_LOAD_BALANCER_ADVISOR agent is created +rem - OCI_NETWORK_LOAD_BALANCER_TEAM team is registered +rem +rem PARAMETERS +rem INSTALL_SCHEMA (Prompted) +rem Target schema where the installer procedure, +rem task, agent, and team are created. +rem +rem PROFILE_NAME (Prompted) +rem AI Profile name used to bind the OCI Network Load +rem Balancer agent. +rem +rem NOTES +rem - Script is safe to re-run; existing tasks, agents, +rem and teams are dropped and recreated. +rem +rem - Destructive Network Load Balancer operations require +rem explicit user confirmation as enforced by task instructions. +rem +rem - Script exits immediately on SQL errors. +rem +rem ============================================================================ + + +SET SERVEROUTPUT ON +SET VERIFY OFF +WHENEVER SQLERROR EXIT SQL.SQLCODE + +PROMPT ====================================================== +PROMPT OCI Network Load Balancer AI Agent Installer +PROMPT ====================================================== + +-- Target schema +ACCEPT SCHEMA_NAME CHAR PROMPT 'Enter target schema name: ' +DEFINE INSTALL_SCHEMA = '&SCHEMA_NAME' + +-- AI Profile +ACCEPT PROFILE_NAME CHAR PROMPT 'Enter AI Profile name to be used with the Agent: ' +DEFINE PROFILE_NAME = '&PROFILE_NAME' + +PROMPT ------------------------------------------------------ +PROMPT Installing into schema: &&INSTALL_SCHEMA +PROMPT Using AI Profile : &&PROFILE_NAME +PROMPT ------------------------------------------------------ + +---------------------------------------------------------------- +-- 1. Grants (safe to re-run) +---------------------------------------------------------------- +BEGIN + DBMS_OUTPUT.PUT_LINE('Granting required privileges to &&INSTALL_SCHEMA ...'); + EXECUTE IMMEDIATE 'GRANT EXECUTE ON DBMS_CLOUD_AI_AGENT TO &&INSTALL_SCHEMA'; + EXECUTE IMMEDIATE 'GRANT EXECUTE ON DBMS_CLOUD TO &&INSTALL_SCHEMA'; + DBMS_OUTPUT.PUT_LINE('Grants completed.'); +END; +/ + +---------------------------------------------------------------- +-- 2. Create installer procedure in target schema +---------------------------------------------------------------- +PROMPT Creating installer procedure in &&INSTALL_SCHEMA ... + +CREATE OR REPLACE PROCEDURE &&INSTALL_SCHEMA..install_oci_network_load_balancer_agent ( + p_profile_name IN VARCHAR2 +) +AUTHID DEFINER +AS +BEGIN + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); + DBMS_OUTPUT.PUT_LINE('Starting OCI Network Load Balancer AI installation'); + DBMS_OUTPUT.PUT_LINE('Schema : ' || USER); + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); + + ------------------------------------------------------------ + -- DROP & CREATE TASK + ------------------------------------------------------------ + BEGIN + DBMS_CLOUD_AI_AGENT.DROP_TASK('OCI_NETWORK_LOAD_BALANCER_TASKS'); + EXCEPTION + WHEN OTHERS THEN NULL; + END; + + DBMS_CLOUD_AI_AGENT.CREATE_TASK( + task_name => 'OCI_NETWORK_LOAD_BALANCER_TASKS', + description => 'Task for managing OCI Network Load Balancers.', + attributes => '{ + "instruction": "Identify the intent of the user request and determine the correct OCI Network Load Balancer operation. ' + || 'Prompt the user only for necessary missing details. ' + || 'Ask clarifying questions if intent is ambiguous. ' + || 'Format lists/objects in a human-readable way. ' + || 'Use LIST_SUBSCRIBED_REGIONS_TOOL to list regions and confirm with the user. ' + || 'Use LIST_COMPARTMENTS_TOOL to list compartments and confirm with the user. ' + || 'Confirm destructive actions before execution. ' + || 'User request: {query}", + "tools": [ + "LIST_SUBSCRIBED_REGIONS_TOOL", + "LIST_COMPARTMENTS_TOOL", + "LIST_NETWORK_LOAD_BALANCERS_TOOL", + "CREATE_NETWORK_LOAD_BALANCER_TOOL", + "UPDATE_NETWORK_LOAD_BALANCER_TOOL", + "DELETE_NETWORK_LOAD_BALANCER_TOOL", + "CHANGE_NLB_COMPARTMENT_TOOL", + "LIST_LISTENERS_TOOL", + "GET_LISTENER_TOOL", + "CREATE_LISTENER_TOOL", + "UPDATE_LISTENER_TOOL", + "DELETE_LISTENER_TOOL", + "CREATE_BACKEND_SET_TOOL", + "LIST_BACKEND_SETS_TOOL", + "LIST_BACKENDS_TOOL", + "LIST_NLB_HEALTHS_TOOL", + "LIST_NLB_POLICIES_TOOL", + "LIST_NLB_PROTOCOLS_TOOL" + ], + "enable_human_tool": "true" + }' + ); + DBMS_OUTPUT.PUT_LINE('Created task OCI_NETWORK_LOAD_BALANCER_TASKS'); + + ------------------------------------------------------------ + -- DROP & CREATE AGENT + ------------------------------------------------------------ + BEGIN + DBMS_CLOUD_AI_AGENT.DROP_AGENT('OCI_NETWORK_LOAD_BALANCER_ADVISOR'); + DBMS_OUTPUT.PUT_LINE('Dropped agent OCI_NETWORK_LOAD_BALANCER_ADVISOR'); + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Agent OCI_NETWORK_LOAD_BALANCER_ADVISOR does not exist, skipping'); + END; + + DBMS_CLOUD_AI_AGENT.CREATE_AGENT( + agent_name => 'OCI_NETWORK_LOAD_BALANCER_ADVISOR', + attributes => + '{' || + '"profile_name":"' || p_profile_name || '",' || + '"role":"You are an OCI Network Load Balancer expert. You help users list, create, update, and delete NLBs, listeners, backend sets, and review health. You confirm destructive actions and present results clearly."' || + '}', + description => 'AI agent for advising and automating OCI Network Load Balancer operations' + ); + DBMS_OUTPUT.PUT_LINE('Created agent OCI_NETWORK_LOAD_BALANCER_ADVISOR'); + + ------------------------------------------------------------ + -- DROP & CREATE TEAM + ------------------------------------------------------------ + BEGIN + DBMS_CLOUD_AI_AGENT.DROP_TEAM('OCI_NETWORK_LOAD_BALANCER_TEAM'); + DBMS_OUTPUT.PUT_LINE('Dropped team OCI_NETWORK_LOAD_BALANCER_TEAM'); + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Team OCI_NETWORK_LOAD_BALANCER_TEAM does not exist, skipping'); + END; + + DBMS_CLOUD_AI_AGENT.CREATE_TEAM( + team_name => 'OCI_NETWORK_LOAD_BALANCER_TEAM', + attributes => '{ + "agents":[{"name":"OCI_NETWORK_LOAD_BALANCER_ADVISOR","task":"OCI_NETWORK_LOAD_BALANCER_TASKS"}], + "process":"sequential" + }' + ); + DBMS_OUTPUT.PUT_LINE('Created team OCI_NETWORK_LOAD_BALANCER_TEAM'); + + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); + DBMS_OUTPUT.PUT_LINE('OCI Network Load Balancer AI installation COMPLETE'); + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); +END install_oci_network_load_balancer_agent; +/ + +---------------------------------------------------------------- +-- 3. Execute installer in target schema +---------------------------------------------------------------- +PROMPT Executing installer procedure ... +BEGIN + &&INSTALL_SCHEMA..install_oci_network_load_balancer_agent('&&PROFILE_NAME'); +END; +/ + +PROMPT ====================================================== +PROMPT Installation finished successfully +PROMPT ====================================================== diff --git a/autonomous-ai-agents/oci_network_load_balancer/oci_network_load_balancer_tools.sql b/autonomous-ai-agents/oci_network_load_balancer/oci_network_load_balancer_tools.sql new file mode 100644 index 0000000..caedd68 --- /dev/null +++ b/autonomous-ai-agents/oci_network_load_balancer/oci_network_load_balancer_tools.sql @@ -0,0 +1,1741 @@ +rem ============================================================================ +rem LICENSE +rem Copyright (c) 2025 Oracle and/or its affiliates. +rem Licensed under the Universal Permissive License (UPL), Version 1.0 +rem https://oss.oracle.com/licenses/upl/ +rem +rem NAME +rem oci_network_load_balancer_tools.sql +rem +rem DESCRIPTION +rem Installer script for OCI Network Load Balancer AI tools +rem (Select AI Agent / Oracle AI Database). +rem +rem This script installs a consolidated PL/SQL package and registers +rem AI Agent tools used to automate OCI Network Load Balancer operations +rem via Select AI Agent (Oracle AI Database). +rem +rem RELEASE VERSION +rem 1.0 +rem +rem RELEASE DATE +rem 26-Jan-2026 +rem +rem MAJOR CHANGES IN THIS RELEASE +rem - Initial release +rem - Added Network Load Balancer AI agent tool registrations +rem +rem SCRIPT STRUCTURE +rem 1. Initialization: +rem - Grants +rem - Configuration setup +rem +rem 2. Package Deployment: +rem - &&INSTALL_SCHEMA.oci_network_load_balancer_agents +rem (package specification and body) +rem +rem 3. AI Tool Setup: +rem - Creation of all Network Load Balancer agent tools +rem +rem INSTALL INSTRUCTIONS +rem 1. Connect as ADMIN or a user with required privileges +rem 2. Run the script using SQL*Plus or SQLcl: +rem +rem sqlplus admin@db @oci_network_load_balancer_tools.sql [CONFIG_JSON] +rem +rem 3. Verify installation by checking tool registration +rem and package compilation status. +rem +rem PARAMETERS +rem INSTALL_SCHEMA (Required) +rem Schema in which the package and tools will be created. +rem +rem CONFIG_JSON (Optional) +rem JSON string used to configure OCI access. +rem +rem NOTES +rem - Optional CONFIG_JSON keys: +rem * use_resource_principal (boolean) +rem * credential_name (string) +rem * compartment_name (string) +rem * compartment_ocid (string) +rem +rem - Configuration can also be updated post-install +rem in the OCI_AGENT_CONFIG table. +rem +rem - This script is idempotent only if DROP logic +rem is explicitly enabled. +rem +rem +rem ============================================================================ + + +SET SERVEROUTPUT ON +SET VERIFY OFF + +-- First argument: Schema Name (Required) +ACCEPT SCHEMA_NAME CHAR PROMPT 'Enter schema name: ' +DEFINE INSTALL_SCHEMA = '&SCHEMA_NAME' + +-- Second argument: JSON config (optional) +-- DEFINE INSTALL_CONFIG_JSON = q'({"credential_name": "MY_CRED", "compartment_name": "MY_COMP"})' +DEFINE INSTALL_CONFIG_JSON = NULL + +------------------------------------------------------------------------------- +-- Initializes the OCI Network Load Balancer AI Agent. This procedure: +-- • Grants required DBMS_CLOUD_OCI NLB type privileges. +-- • Creates the OCI_AGENT_CONFIG table. +-- • Parses the JSON config and persists credential, compartment, and RP flag. +------------------------------------------------------------------------------- +CREATE OR REPLACE PROCEDURE initialize_network_load_balancer_agent( + p_install_schema_name IN VARCHAR2, + p_config_json IN CLOB +) +IS + l_use_rp BOOLEAN := NULL; + l_credential_name VARCHAR2(4000) := NULL; + l_compartment_ocid VARCHAR2(4000) := NULL; + l_compartment_name VARCHAR2(4000) := NULL; + l_schema_name VARCHAR2(128); + c_nlb_agent CONSTANT VARCHAR2(64) := 'OCI_NETWORK_LOAD_BALANCER'; + + TYPE priv_list_t IS VARRAY(200) OF VARCHAR2(4000); + l_priv_list CONSTANT priv_list_t := priv_list_t( + 'DBMS_CLOUD', + 'DBMS_CLOUD_ADMIN', + 'DBMS_CLOUD_AI_AGENT', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER', + -- Response types used by wrappers + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_GET_LISTENER_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_LIST_LISTENERS_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_DELETE_LISTENER_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_DELETE_NETWORK_LOAD_BALANCER_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_CREATE_NETWORK_LOAD_BALANCER_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_CREATE_LISTENER_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_CHANGE_NETWORK_LOAD_BALANCER_COMPARTMENT_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_LIST_BACKEND_SETS_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_LIST_BACKENDS_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_LIST_NETWORK_LOAD_BALANCER_HEALTHS_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_LIST_NETWORK_LOAD_BALANCERS_POLICIES_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_LIST_NETWORK_LOAD_BALANCERS_PROTOCOLS_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_LIST_NETWORK_LOAD_BALANCERS_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_UPDATE_NETWORK_LOAD_BALANCER_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_UPDATE_LISTENER_RESPONSE_T', + 'DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_CREATE_BACKEND_SET_RESPONSE_T', + -- Model/detail types used by wrappers + 'DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_CREATE_NETWORK_LOAD_BALANCER_DETAILS_T', + 'DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_RESERVED_IP_TBL', + 'DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_RESERVED_IP_T', + 'DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_VARCHAR2_TBL', + 'DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_LISTENER_SUMMARY_TBL', + 'DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_NETWORK_LOAD_BALANCER_SUMMARY_T', + 'DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_UPDATE_NETWORK_LOAD_BALANCER_DETAILS_T', + 'DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_CREATE_LISTENER_DETAILS_T', + 'DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_UPDATE_LISTENER_DETAILS_T', + 'DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_CHANGE_NETWORK_LOAD_BALANCER_COMPARTMENT_DETAILS_T', + 'DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_HEALTH_CHECKER_DETAILS_T', + 'DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_CREATE_BACKEND_SET_DETAILS_T', + 'DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_BACKEND_DETAILS_TBL' + ); + + ---------------------------------------------------------------------------- + -- Helper: grant execute on list of objects + ---------------------------------------------------------------------------- + PROCEDURE execute_grants(p_schema IN VARCHAR2, p_objects IN priv_list_t) IS + BEGIN + EXECUTE IMMEDIATE 'GRANT SELECT ON SYS.V_$PDBS TO ' || p_schema; + FOR i IN 1 .. p_objects.COUNT LOOP + BEGIN + EXECUTE IMMEDIATE 'GRANT EXECUTE ON ' || p_objects(i) || ' TO ' || p_schema; + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Warning: failed to grant ' || p_objects(i) || + ' to ' || p_schema || ' - ' || SQLERRM); + END; + END LOOP; + END execute_grants; + + ---------------------------------------------------------------------------- + -- get_config: returns parsed values via OUT params (no globals modified) + ---------------------------------------------------------------------------- + PROCEDURE get_config( + p_config_json IN CLOB, + o_use_rp OUT BOOLEAN, + o_credential_name OUT VARCHAR2, + o_compartment_name OUT VARCHAR2, + o_compartment_ocid OUT VARCHAR2 + ) IS + l_cfg JSON_OBJECT_T := NULL; + BEGIN + o_use_rp := NULL; + o_credential_name := NULL; + o_compartment_name := NULL; + o_compartment_ocid := NULL; + + IF p_config_json IS NOT NULL AND TRIM(p_config_json) IS NOT NULL THEN + BEGIN + l_cfg := JSON_OBJECT_T.parse(p_config_json); + + IF l_cfg.has('use_resource_principal') THEN + o_use_rp := l_cfg.get_boolean('use_resource_principal'); + END IF; + + IF l_cfg.has('credential_name') THEN + o_credential_name := l_cfg.get_string('credential_name'); + END IF; + + IF l_cfg.has('compartment_name') THEN + o_compartment_name := l_cfg.get_string('compartment_name'); + END IF; + + IF l_cfg.has('compartment_ocid') THEN + o_compartment_ocid := l_cfg.get_string('compartment_ocid'); + END IF; + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Config JSON parse failed: ' || SQLERRM); + o_use_rp := NULL; + o_credential_name := NULL; + o_compartment_name := NULL; + o_compartment_ocid := NULL; + END; + ELSE + DBMS_OUTPUT.PUT_LINE('No config JSON provided, using defaults.'); + END IF; + END get_config; + + ---------------------------------------------------------------------------- + -- Helper: generic MERGE for a single config key/value (schema-qualified) + ---------------------------------------------------------------------------- + PROCEDURE merge_config_key( + p_schema IN VARCHAR2, + p_key IN VARCHAR2, + p_val IN CLOB, + p_agent IN VARCHAR2 + ) IS + l_sql CLOB; + BEGIN + l_sql := + 'MERGE INTO ' || p_schema || '.OCI_AGENT_CONFIG c + USING (SELECT :k AS "KEY", :v AS "VALUE", :a AS "AGENT" FROM DUAL) src + ON (c."KEY" = src."KEY" AND c."AGENT" = src."AGENT") + WHEN MATCHED THEN + UPDATE SET c."VALUE" = src."VALUE" + WHEN NOT MATCHED THEN + INSERT ("KEY", "VALUE", "AGENT") VALUES (src."KEY", src."VALUE", src."AGENT")'; + + EXECUTE IMMEDIATE l_sql USING p_key, p_val, p_agent; + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Warning: failed to persist ' || p_key || ' config: ' || SQLERRM); + END merge_config_key; + + ---------------------------------------------------------------------------- + -- Combined helper: Apply config and insert into config table + ---------------------------------------------------------------------------- + PROCEDURE apply_config( + p_schema IN VARCHAR2, + p_use_rp IN BOOLEAN, + p_credential_name IN VARCHAR2, + p_compartment_name IN VARCHAR2, + p_compartment_ocid IN VARCHAR2 + ) IS + l_effective_use_rp BOOLEAN; + l_enable_rp_str VARCHAR2(3); + BEGIN + l_effective_use_rp := CASE WHEN p_use_rp IS NULL THEN TRUE ELSE p_use_rp END; + + IF p_credential_name IS NOT NULL THEN + merge_config_key(p_schema, 'CREDENTIAL_NAME', p_credential_name, c_nlb_agent); + END IF; + + IF p_compartment_name IS NOT NULL THEN + merge_config_key(p_schema, 'COMPARTMENT_NAME', p_compartment_name, c_nlb_agent); + END IF; + + IF p_compartment_ocid IS NOT NULL THEN + merge_config_key(p_schema, 'COMPARTMENT_OCID', p_compartment_ocid, c_nlb_agent); + END IF; + + l_enable_rp_str := CASE WHEN l_effective_use_rp THEN 'YES' ELSE 'NO' END; + merge_config_key(p_schema, 'ENABLE_RESOURCE_PRINCIPAL', l_enable_rp_str, c_nlb_agent); + + IF l_effective_use_rp THEN + BEGIN + DBMS_CLOUD_ADMIN.ENABLE_RESOURCE_PRINCIPAL(USERNAME => p_schema); + DBMS_OUTPUT.PUT_LINE('Resource principal enabled for ' || p_schema); + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Failed to enable resource principal for ' || p_schema || ' - ' || SQLERRM); + END; + ELSE + DBMS_OUTPUT.PUT_LINE( + 'Resource principal NOT enabled per config. Using credential: ' + || NVL(p_credential_name, '') + ); + END IF; + END apply_config; + +BEGIN + l_schema_name := DBMS_ASSERT.SIMPLE_SQL_NAME(p_install_schema_name); + + execute_grants(l_schema_name, l_priv_list); + + get_config( + p_config_json => p_config_json, + o_use_rp => l_use_rp, + o_credential_name => l_credential_name, + o_compartment_name => l_compartment_name, + o_compartment_ocid => l_compartment_ocid + ); + + BEGIN + EXECUTE IMMEDIATE + 'CREATE TABLE ' || l_schema_name || '.OCI_AGENT_CONFIG ( + "ID" NUMBER GENERATED BY DEFAULT AS IDENTITY, + "KEY" VARCHAR2(200) NOT NULL, + "VALUE" CLOB, + "AGENT" VARCHAR2(128) NOT NULL, + CONSTRAINT OCI_AGENT_CONFIG_PK PRIMARY KEY ("ID"), + CONSTRAINT OCI_AGENT_CONFIG_UK UNIQUE ("KEY","AGENT") + )'; + EXCEPTION + WHEN OTHERS THEN + IF SQLCODE = -955 THEN + NULL; -- already exists + ELSE + RAISE; + END IF; + END; + + apply_config( + p_schema => l_schema_name, + p_use_rp => l_use_rp, + p_credential_name => l_credential_name, + p_compartment_name => l_compartment_name, + p_compartment_ocid => l_compartment_ocid + ); + + DBMS_OUTPUT.PUT_LINE('initialize_network_load_balancer_agent completed for schema ' || l_schema_name); +EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Fatal error in initialize_network_load_balancer_agent: ' || SQLERRM); + RAISE; +END initialize_network_load_balancer_agent; +/ + +------------------------------------------------------------------------------- +-- Run the setup for the Network Load Balancer AI agent. +------------------------------------------------------------------------------- +BEGIN + initialize_network_load_balancer_agent( + p_install_schema_name => '&&INSTALL_SCHEMA', + p_config_json => &&INSTALL_CONFIG_JSON + ); +END; +/ + +alter session set current_schema = &&INSTALL_SCHEMA; + +------------------------------------------------------------------------ +-- Package specification +------------------------------------------------------------------------ +CREATE OR REPLACE PACKAGE oci_network_load_balancer_agents +AS + FUNCTION list_subscribed_regions RETURN CLOB; + FUNCTION list_compartments RETURN CLOB; + + FUNCTION get_listener ( + p_network_load_balancer_id IN VARCHAR2, + p_listener_name IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION list_listeners ( + p_network_load_balancer_id IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION delete_listener ( + p_network_load_balancer_id IN VARCHAR2, + p_listener_name IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION delete_network_load_balancer ( + p_network_load_balancer_id IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION create_network_load_balancer ( + p_compartment_name IN VARCHAR2, + p_display_name IN VARCHAR2, + p_is_preserve_source_destination IN NUMBER, + p_reserved_ips_json IN CLOB, + p_is_private IN NUMBER, + p_subnet_id IN VARCHAR2, + p_network_security_group_ids_json IN CLOB, + p_nlb_ip_version IN VARCHAR2, + p_listener_name IN VARCHAR2, + p_listener_backend_set_name IN VARCHAR2, + p_listener_port IN NUMBER, + p_listener_protocol IN VARCHAR2, + p_backend_set_name IN VARCHAR2, + p_backend_policy IN VARCHAR2, + p_health_protocol IN VARCHAR2, + p_health_port IN NUMBER, + p_freeform_tags IN CLOB, + p_defined_tags IN CLOB, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION create_listener ( + p_network_load_balancer_id IN VARCHAR2, + p_name IN VARCHAR2, + p_default_backend_set_name IN VARCHAR2, + p_port IN NUMBER, + p_protocol IN VARCHAR2, + p_ip_version IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB; + + FUNCTION change_nlb_compartment ( + p_network_load_balancer_id IN VARCHAR2, + p_new_compartment_id IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB; + + FUNCTION list_backend_sets ( + p_network_load_balancer_id IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB; + + FUNCTION list_backends ( + p_network_load_balancer_id IN VARCHAR2, + p_backend_set_name IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB; + + FUNCTION list_nlb_healths ( + p_compartment_id IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB; + + FUNCTION list_nlb_policies ( + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB; + + FUNCTION list_nlb_protocols ( + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB; + + FUNCTION list_network_load_balancers ( + p_compartment_id IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB; + + FUNCTION update_network_load_balancer ( + p_network_load_balancer_id IN VARCHAR2, + p_display_name IN VARCHAR2, + p_is_preserve_source_destination IN NUMBER, + p_nlb_ip_version IN VARCHAR2, + p_freeform_tags IN CLOB, + p_defined_tags IN CLOB, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB; + + FUNCTION update_listener ( + p_network_load_balancer_id IN VARCHAR2, + p_listener_name IN VARCHAR2, + p_default_backend_set_name IN VARCHAR2, + p_port IN NUMBER, + p_protocol IN VARCHAR2, + p_ip_version IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB; + + FUNCTION create_backend_set ( + p_network_load_balancer_id IN VARCHAR2, + p_name IN VARCHAR2, + p_policy IN VARCHAR2, + p_protocol IN VARCHAR2, + p_port IN NUMBER, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB; + +END oci_network_load_balancer_agents; +/ + +------------------------------------------------------------------------ +-- Package body +------------------------------------------------------------------------ +CREATE OR REPLACE PACKAGE BODY oci_network_load_balancer_agents +AS + c_nlb_agent CONSTANT VARCHAR2(64) := 'OCI_NETWORK_LOAD_BALANCER'; + + -- Helper function to get configuration parameters for the current user + FUNCTION get_agent_config( + schema_name IN VARCHAR2, + table_name IN VARCHAR2, + agent_name IN VARCHAR2 + ) RETURN CLOB + IS + l_sql VARCHAR2(4000); + l_cursor SYS_REFCURSOR; + l_config_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_key VARCHAR2(200); + l_value CLOB; + l_result_json JSON_OBJECT_T := JSON_OBJECT_T(); + BEGIN + l_sql := 'SELECT "KEY", "VALUE" FROM ' || schema_name || '.' || table_name || + ' WHERE "AGENT" = :agent'; + + OPEN l_cursor FOR l_sql USING agent_name; + LOOP + FETCH l_cursor INTO l_key, l_value; + EXIT WHEN l_cursor%NOTFOUND; + l_config_json.put(l_key, l_value); + END LOOP; + CLOSE l_cursor; + + l_result_json.put('status', 'success'); + l_result_json.put('config_params', l_config_json); + RETURN l_result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + BEGIN + IF l_cursor%ISOPEN THEN + CLOSE l_cursor; + END IF; + EXCEPTION + WHEN OTHERS THEN NULL; + END; + l_result_json := JSON_OBJECT_T(); + l_result_json.put('status', 'error'); + l_result_json.put('message', 'Error: ' || SQLERRM); + RETURN l_result_json.to_clob(); + END get_agent_config; + + ---------------------------------------------------------------------- + -- resolve_credential: uses explicit credential if provided, else config + ---------------------------------------------------------------------- + PROCEDURE resolve_credential( + p_credential_name IN VARCHAR2, + o_credential_name OUT VARCHAR2 + ) IS + l_current_user VARCHAR2(128) := SYS_CONTEXT('USERENV', 'CURRENT_USER'); + l_cfg_json CLOB; + l_cfg JSON_OBJECT_T; + l_params JSON_OBJECT_T; + BEGIN + o_credential_name := p_credential_name; + IF o_credential_name IS NOT NULL THEN + RETURN; + END IF; + + l_cfg_json := get_agent_config(l_current_user, 'OCI_AGENT_CONFIG', c_nlb_agent); + l_cfg := JSON_OBJECT_T.parse(l_cfg_json); + IF l_cfg.get_string('status') = 'success' THEN + l_params := l_cfg.get_object('config_params'); + IF l_params.has('CREDENTIAL_NAME') THEN + o_credential_name := l_params.get_string('CREDENTIAL_NAME'); + END IF; + END IF; + EXCEPTION + WHEN OTHERS THEN + o_credential_name := p_credential_name; + END resolve_credential; + + ---------------------------------------------------------------------- + -- list_subscribed_regions: REST call to Identity regionSubscriptions + ---------------------------------------------------------------------- + FUNCTION list_subscribed_regions RETURN CLOB + IS + l_result_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_regions JSON_ARRAY_T := JSON_ARRAY_T(); + l_current_user VARCHAR2(128) := SYS_CONTEXT('USERENV','CURRENT_USER'); + l_cfg_json CLOB; + l_cfg JSON_OBJECT_T; + l_params JSON_OBJECT_T; + l_credential_name VARCHAR2(256); + tenancy_id VARCHAR2(128); + l_region VARCHAR2(128); + l_endpoint VARCHAR2(1000); + l_response CLOB; + l_data JSON_ARRAY_T; + l_obj JSON_OBJECT_T; + BEGIN + resolve_credential(NULL, l_credential_name); + IF l_credential_name IS NULL THEN + l_result_json.put('status','error'); + l_result_json.put('message','Missing credential_name (set in OCI_AGENT_CONFIG for OCI_NETWORK_LOAD_BALANCER).'); + RETURN l_result_json.to_clob(); + END IF; + + SELECT + JSON_VALUE(cloud_identity, '$.TENANT_OCID') AS tenant_ocid, + JSON_VALUE(cloud_identity, '$.REGION') AS region + INTO tenancy_id, l_region + FROM v$pdbs; + + l_endpoint := + 'https://identity.' || l_region || '.oci.oraclecloud.com/20160918/regionSubscriptions?tenancyId=' || tenancy_id; + + l_response := DBMS_CLOUD.get_response_text( + DBMS_CLOUD.send_request( + credential_name => l_credential_name, + uri => l_endpoint, + method => DBMS_CLOUD.METHOD_GET + ) + ); + + l_data := JSON_ARRAY_T.parse(l_response); + FOR i IN 0 .. l_data.get_size() - 1 LOOP + l_obj := JSON_OBJECT_T(l_data.get(i)); + l_regions.append( + JSON_OBJECT( + 'region_name' VALUE l_obj.get_string('regionName'), + 'region_key' VALUE l_obj.get_string('regionKey'), + 'status' VALUE l_obj.get_string('status') + ) + ); + END LOOP; + + l_result_json.put('status','success'); + l_result_json.put('message','Successfully retrieved subscribed regions'); + l_result_json.put('regions', l_regions); + RETURN l_result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result_json := JSON_OBJECT_T(); + l_result_json.put('status','error'); + l_result_json.put('message','Failed to retrieve subscribed regions: ' || SQLERRM); + RETURN l_result_json.to_clob(); + END list_subscribed_regions; + + ---------------------------------------------------------------------- + -- list_compartments: REST call to Identity compartments + ---------------------------------------------------------------------- + FUNCTION list_compartments RETURN CLOB + IS + l_result_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_compartments JSON_ARRAY_T := JSON_ARRAY_T(); + l_credential_name VARCHAR2(256); + tenancy_id VARCHAR2(128); + l_region VARCHAR2(128); + l_endpoint VARCHAR2(1000); + l_response CLOB; + l_data JSON_ARRAY_T; + l_obj JSON_OBJECT_T; + BEGIN + resolve_credential(NULL, l_credential_name); + IF l_credential_name IS NULL THEN + l_result_json.put('status','error'); + l_result_json.put('message','Missing credential_name (set in OCI_AGENT_CONFIG for OCI_NETWORK_LOAD_BALANCER).'); + RETURN l_result_json.to_clob(); + END IF; + + SELECT + JSON_VALUE(cloud_identity, '$.TENANT_OCID') AS tenant_ocid, + JSON_VALUE(cloud_identity, '$.REGION') AS region + INTO tenancy_id, l_region + FROM v$pdbs; + + l_endpoint := + 'https://identity.' || l_region || '.oci.oraclecloud.com/20160918/compartments?compartmentId=' || tenancy_id; + + l_response := DBMS_CLOUD.get_response_text( + DBMS_CLOUD.send_request( + credential_name => l_credential_name, + uri => l_endpoint, + method => DBMS_CLOUD.METHOD_GET + ) + ); + + l_data := JSON_ARRAY_T.parse(l_response); + FOR i IN 0 .. l_data.get_size() - 1 LOOP + l_obj := JSON_OBJECT_T(l_data.get(i)); + l_compartments.append( + JSON_OBJECT( + 'name' VALUE l_obj.get_string('name'), + 'id' VALUE l_obj.get_string('id'), + 'description' VALUE l_obj.get_string('description'), + 'lifecycle_state' VALUE l_obj.get_string('lifecycleState'), + 'time_created' VALUE l_obj.get_string('timeCreated') + ) + ); + END LOOP; + + l_result_json.put('status','success'); + l_result_json.put('message','Successfully retrieved compartments'); + l_result_json.put('total_compartments', l_compartments.get_size()); + l_result_json.put('compartments', l_compartments); + RETURN l_result_json.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result_json := JSON_OBJECT_T(); + l_result_json.put('status','error'); + l_result_json.put('message','Failed to retrieve compartments: ' || SQLERRM); + RETURN l_result_json.to_clob(); + END list_compartments; + + ---------------------------------------------------------------------- + -- get_compartment_ocid_by_name: utility used by create_nlb + ---------------------------------------------------------------------- + FUNCTION get_compartment_ocid_by_name( + p_compartment_name IN VARCHAR2, + p_credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN VARCHAR2 + IS + l_comp_json_clob CLOB; + l_root JSON_OBJECT_T; + l_arr JSON_ARRAY_T; + l_obj JSON_OBJECT_T; + l_id VARCHAR2(4000); + BEGIN + -- Currently list_compartments uses config credential only; honor override by temporarily resolving + IF p_credential_name IS NOT NULL THEN + -- Fall back: if caller provides credential override, list_compartments still uses config. + NULL; + END IF; + + l_comp_json_clob := list_compartments(); + l_root := JSON_OBJECT_T.parse(l_comp_json_clob); + IF l_root.get_string('status') <> 'success' THEN + RETURN NULL; + END IF; + l_arr := l_root.get_array('compartments'); + FOR i IN 0 .. l_arr.get_size() - 1 LOOP + l_obj := JSON_OBJECT_T(l_arr.get(i)); + IF l_obj.get_string('name') = p_compartment_name THEN + l_id := l_obj.get_string('id'); + EXIT; + END IF; + END LOOP; + RETURN l_id; + EXCEPTION + WHEN OTHERS THEN + RETURN NULL; + END get_compartment_ocid_by_name; + + ---------------------------------------------------------------------- + -- NLB wrappers (adapted from /Users/rposina/Downloads/network_load_balancer.sql) + ---------------------------------------------------------------------- + FUNCTION get_listener ( + p_network_load_balancer_id IN VARCHAR2, + p_listener_name IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_GET_LISTENER_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(p_credential_name, l_credential); + + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.GET_LISTENER( + network_load_balancer_id => p_network_load_balancer_id, + listener_name => p_listener_name, + opc_request_id => NULL, + if_none_match => NULL, + region => p_region, + endpoint => NULL, + credential_name => l_credential + ); + + l_result.put('status', 'success'); + l_result.put('message', 'Listener retrieved successfully'); + l_result.put('status_code', l_resp.status_code); + l_result.put('headers', l_resp.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to get listener: ' || SQLERRM); + l_result.put('nlb_id', p_network_load_balancer_id); + RETURN l_result.to_clob(); + END get_listener; + + FUNCTION list_listeners ( + p_network_load_balancer_id IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_LIST_LISTENERS_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_items DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_LISTENER_SUMMARY_TBL; + l_payload CLOB := ''; + l_credential VARCHAR2(256); + BEGIN + resolve_credential(p_credential_name, l_credential); + + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.LIST_LISTENERS( + network_load_balancer_id => p_network_load_balancer_id, + region => p_region, + credential_name => l_credential + ); + + l_items := l_resp.response_body.items; + l_payload := '['; + FOR i IN 1 .. l_items.COUNT LOOP + IF i > 1 THEN + l_payload := l_payload || ','; + END IF; + + l_payload := l_payload || '{"name":"' || l_items(i).name || + '","port":' || l_items(i).port || + ',"protocol":"' || l_items(i).protocol || + '","ipVersion":"' || l_items(i).ip_version || '"}'; + END LOOP; + l_payload := l_payload || ']'; + + l_result.put('status', 'success'); + l_result.put('message', 'Listeners listed successfully'); + l_result.put('status_code', l_resp.status_code); + l_result.put('listeners', JSON_ELEMENT_T.parse(l_payload)); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to list listeners: ' || SQLERRM); + l_result.put('nlb_id', p_network_load_balancer_id); + RETURN l_result.to_clob(); + END list_listeners; + + FUNCTION delete_listener ( + p_network_load_balancer_id IN VARCHAR2, + p_listener_name IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_DELETE_LISTENER_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(p_credential_name, l_credential); + + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.DELETE_LISTENER( + network_load_balancer_id => p_network_load_balancer_id, + listener_name => p_listener_name, + opc_request_id => NULL, + if_match => NULL, + region => p_region, + endpoint => NULL, + credential_name => l_credential + ); + + l_result.put('status', 'success'); + l_result.put('message', 'Listener deleted successfully'); + l_result.put('status_code', l_resp.status_code); + l_result.put('headers', l_resp.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to delete listener: ' || SQLERRM); + l_result.put('nlb_id', p_network_load_balancer_id); + l_result.put('listener', p_listener_name); + RETURN l_result.to_clob(); + END delete_listener; + + FUNCTION delete_network_load_balancer ( + p_network_load_balancer_id IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_DELETE_NETWORK_LOAD_BALANCER_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(p_credential_name, l_credential); + + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.DELETE_NETWORK_LOAD_BALANCER( + network_load_balancer_id => p_network_load_balancer_id, + if_match => NULL, + opc_request_id => NULL, + region => p_region, + endpoint => NULL, + credential_name => l_credential + ); + + l_result.put('status', 'success'); + l_result.put('message', 'Network Load Balancer deleted successfully'); + l_result.put('status_code', l_resp.status_code); + l_result.put('headers', l_resp.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to delete network load balancer: ' || SQLERRM); + l_result.put('nlb_id', p_network_load_balancer_id); + RETURN l_result.to_clob(); + END delete_network_load_balancer; + + FUNCTION create_network_load_balancer ( + p_compartment_name IN VARCHAR2, + p_display_name IN VARCHAR2, + p_is_preserve_source_destination IN NUMBER, + p_reserved_ips_json IN CLOB, + p_is_private IN NUMBER, + p_subnet_id IN VARCHAR2, + p_network_security_group_ids_json IN CLOB, + p_nlb_ip_version IN VARCHAR2, + p_listener_name IN VARCHAR2, + p_listener_backend_set_name IN VARCHAR2, + p_listener_port IN NUMBER, + p_listener_protocol IN VARCHAR2, + p_backend_set_name IN VARCHAR2, + p_backend_policy IN VARCHAR2, + p_health_protocol IN VARCHAR2, + p_health_port IN NUMBER, + p_freeform_tags IN CLOB, + p_defined_tags IN CLOB, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_listeners_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_listener_obj JSON_OBJECT_T := JSON_OBJECT_T(); + l_backend_sets_json JSON_OBJECT_T := JSON_OBJECT_T(); + l_backend_set_obj JSON_OBJECT_T := JSON_OBJECT_T(); + l_health_checker JSON_OBJECT_T := JSON_OBJECT_T(); + + l_listeners JSON_ELEMENT_T; + l_backend_sets JSON_ELEMENT_T; + l_freeform_tags JSON_ELEMENT_T := CASE WHEN p_freeform_tags IS NOT NULL THEN JSON_OBJECT_T.parse(p_freeform_tags) ELSE NULL END; + l_defined_tags JSON_ELEMENT_T := CASE WHEN p_defined_tags IS NOT NULL THEN JSON_OBJECT_T.parse(p_defined_tags) ELSE NULL END; + + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_CREATE_NETWORK_LOAD_BALANCER_RESPONSE_T; + l_details DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_CREATE_NETWORK_LOAD_BALANCER_DETAILS_T; + + l_reserved_ips DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_RESERVED_IP_TBL := DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_RESERVED_IP_TBL(); + l_nsg_ids DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_VARCHAR2_TBL := DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_VARCHAR2_TBL(); + l_compartment_id VARCHAR2(256); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(p_credential_name, l_credential); + + l_compartment_id := get_compartment_ocid_by_name(p_compartment_name => p_compartment_name); + IF l_compartment_id IS NULL THEN + l_result.put('status','error'); + l_result.put('message','Failed to resolve compartment OCID for compartment_name=' || p_compartment_name); + RETURN l_result.to_clob(); + END IF; + + IF p_reserved_ips_json IS NOT NULL THEN + DECLARE + l_json_arr JSON_ARRAY_T := JSON_ARRAY_T.parse(p_reserved_ips_json); + l_obj JSON_OBJECT_T; + BEGIN + FOR i IN 0 .. l_json_arr.get_size - 1 LOOP + l_obj := JSON_OBJECT_T(l_json_arr.get(i)); + l_reserved_ips.EXTEND; + l_reserved_ips(l_reserved_ips.COUNT) := DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_RESERVED_IP_T( + id => l_obj.get_string('id') + ); + END LOOP; + END; + END IF; + + IF p_network_security_group_ids_json IS NOT NULL THEN + DECLARE + l_json_arr JSON_ARRAY_T := JSON_ARRAY_T.parse(p_network_security_group_ids_json); + BEGIN + FOR i IN 0 .. l_json_arr.get_size - 1 LOOP + l_nsg_ids.EXTEND; + l_nsg_ids(l_nsg_ids.COUNT) := l_json_arr.get_string(i); + END LOOP; + END; + END IF; + + l_listener_obj.put('name', p_listener_name); + l_listener_obj.put('defaultBackendSetName', p_listener_backend_set_name); + l_listener_obj.put('port', p_listener_port); + l_listener_obj.put('protocol', p_listener_protocol); + l_listeners_json.put(p_listener_name, l_listener_obj); + l_listeners := l_listeners_json; + + l_health_checker.put('protocol', p_health_protocol); + l_health_checker.put('port', p_health_port); + l_backend_set_obj.put('policy', p_backend_policy); + l_backend_set_obj.put('backends', JSON_ARRAY_T()); + l_backend_set_obj.put('healthChecker', l_health_checker); + l_backend_sets_json.put(p_backend_set_name, l_backend_set_obj); + l_backend_sets := l_backend_sets_json; + + l_details := DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_CREATE_NETWORK_LOAD_BALANCER_DETAILS_T( + compartment_id => l_compartment_id, + display_name => p_display_name, + is_preserve_source_destination => p_is_preserve_source_destination, + reserved_ips => l_reserved_ips, + is_private => p_is_private, + subnet_id => p_subnet_id, + network_security_group_ids => l_nsg_ids, + nlb_ip_version => p_nlb_ip_version, + listeners => l_listeners, + backend_sets => l_backend_sets, + freeform_tags => l_freeform_tags, + defined_tags => l_defined_tags + ); + + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.CREATE_NETWORK_LOAD_BALANCER( + create_network_load_balancer_details => l_details, + opc_retry_token => NULL, + opc_request_id => NULL, + region => p_region, + endpoint => NULL, + credential_name => l_credential + ); + + l_result.put('status', 'success'); + l_result.put('message', 'Network Load Balancer created successfully'); + l_result.put('status_code', l_resp.status_code); + l_result.put('headers', l_resp.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to create NLB: ' || SQLERRM); + RETURN l_result.to_clob(); + END create_network_load_balancer; + + FUNCTION create_listener ( + p_network_load_balancer_id IN VARCHAR2, + p_name IN VARCHAR2, + p_default_backend_set_name IN VARCHAR2, + p_port IN NUMBER, + p_protocol IN VARCHAR2, + p_ip_version IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 DEFAULT NULL + ) RETURN CLOB + IS + l_details DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_CREATE_LISTENER_DETAILS_T; + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_CREATE_LISTENER_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_credential VARCHAR2(256); + BEGIN + resolve_credential(p_credential_name, l_credential); + + l_details := NEW DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_CREATE_LISTENER_DETAILS_T( + p_name, + p_default_backend_set_name, + p_port, + p_protocol, + p_ip_version + ); + + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.CREATE_LISTENER( + network_load_balancer_id => p_network_load_balancer_id, + create_listener_details => l_details, + opc_request_id => NULL, + opc_retry_token => NULL, + if_match => NULL, + region => p_region, + endpoint => NULL, + credential_name => l_credential + ); + + l_result.put('status', 'success'); + l_result.put('message', 'Listener created successfully'); + l_result.put('status_code', l_resp.status_code); + l_result.put('headers', l_resp.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to create listener: ' || SQLERRM); + RETURN l_result.to_clob(); + END create_listener; + + FUNCTION change_nlb_compartment ( + p_network_load_balancer_id IN VARCHAR2, + p_new_compartment_id IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB + IS + l_change_details DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_CHANGE_NETWORK_LOAD_BALANCER_COMPARTMENT_DETAILS_T; + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_CHANGE_NETWORK_LOAD_BALANCER_COMPARTMENT_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + BEGIN + l_change_details := DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_CHANGE_NETWORK_LOAD_BALANCER_COMPARTMENT_DETAILS_T( + compartment_id => p_new_compartment_id + ); + + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.CHANGE_NETWORK_LOAD_BALANCER_COMPARTMENT( + network_load_balancer_id => p_network_load_balancer_id, + change_network_load_balancer_compartment_details => l_change_details, + opc_request_id => NULL, + opc_retry_token => NULL, + if_match => NULL, + region => p_region, + endpoint => NULL, + credential_name => p_credential_name + ); + + l_result.put('status', 'success'); + l_result.put('message', 'Network Load Balancer moved successfully'); + l_result.put('status_code', l_resp.status_code); + l_result.put('headers', l_resp.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to change compartment: ' || SQLERRM); + l_result.put('nlb_id', p_network_load_balancer_id); + RETURN l_result.to_clob(); + END change_nlb_compartment; + + FUNCTION list_backend_sets ( + p_network_load_balancer_id IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB + IS + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_LIST_BACKEND_SETS_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_backend_sets JSON_ARRAY_T := JSON_ARRAY_T(); + l_entry JSON_OBJECT_T; + BEGIN + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.LIST_BACKEND_SETS( + network_load_balancer_id => p_network_load_balancer_id, + opc_request_id => NULL, + if_none_match => NULL, + limit => NULL, + page => NULL, + sort_order => NULL, + sort_by => NULL, + region => p_region, + endpoint => NULL, + credential_name => p_credential_name + ); + + FOR i IN 1 .. l_resp.response_body.items.COUNT LOOP + l_entry := JSON_OBJECT_T(); + l_entry.put('name', l_resp.response_body.items(i).name); + l_entry.put('policy', l_resp.response_body.items(i).policy); + l_backend_sets.append(l_entry); + END LOOP; + + l_result.put('status', 'success'); + l_result.put('message', 'Backend sets listed successfully'); + l_result.put('status_code', l_resp.status_code); + l_result.put('headers', l_resp.headers); + l_result.put('backend_sets', l_backend_sets); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to list backend sets: ' || SQLERRM); + l_result.put('nlb_id', p_network_load_balancer_id); + RETURN l_result.to_clob(); + END list_backend_sets; + + FUNCTION list_backends ( + p_network_load_balancer_id IN VARCHAR2, + p_backend_set_name IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB + IS + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_LIST_BACKENDS_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + BEGIN + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.LIST_BACKENDS( + network_load_balancer_id => p_network_load_balancer_id, + backend_set_name => p_backend_set_name, + opc_request_id => NULL, + if_none_match => NULL, + limit => NULL, + page => NULL, + sort_order => NULL, + sort_by => NULL, + region => p_region, + endpoint => NULL, + credential_name => p_credential_name + ); + + l_result.put('status', 'success'); + l_result.put('message', 'Backend list retrieved successfully'); + l_result.put('status_code', l_resp.status_code); + l_result.put('headers', l_resp.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to list backends: ' || SQLERRM); + l_result.put('nlb_id', p_network_load_balancer_id); + RETURN l_result.to_clob(); + END list_backends; + + FUNCTION list_nlb_healths ( + p_compartment_id IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB + IS + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_LIST_NETWORK_LOAD_BALANCER_HEALTHS_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_health_array JSON_ARRAY_T := JSON_ARRAY_T(); + l_item_obj JSON_OBJECT_T; + BEGIN + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.LIST_NETWORK_LOAD_BALANCER_HEALTHS( + compartment_id => p_compartment_id, + sort_order => NULL, + sort_by => NULL, + opc_request_id => NULL, + limit => NULL, + page => NULL, + region => p_region, + endpoint => NULL, + credential_name => p_credential_name + ); + + FOR i IN 1 .. l_resp.response_body.items.COUNT LOOP + l_item_obj := JSON_OBJECT_T(); + l_item_obj.put('network_load_balancer_id', l_resp.response_body.items(i).network_load_balancer_id); + l_item_obj.put('status', l_resp.response_body.items(i).status); + l_health_array.append(l_item_obj); + END LOOP; + + l_result.put('status', 'success'); + l_result.put('message', 'NLB health list retrieved successfully'); + l_result.put('status_code', l_resp.status_code); + l_result.put('headers', l_resp.headers); + l_result.put('health_summaries', l_health_array); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to list NLB health summaries: ' || SQLERRM); + l_result.put('compartment_id', p_compartment_id); + RETURN l_result.to_clob(); + END list_nlb_healths; + + FUNCTION list_nlb_policies ( + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB + IS + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_LIST_NETWORK_LOAD_BALANCERS_POLICIES_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + BEGIN + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.LIST_NETWORK_LOAD_BALANCERS_POLICIES( + opc_request_id => NULL, + limit => NULL, + page => NULL, + sort_order => NULL, + sort_by => NULL, + region => p_region, + endpoint => NULL, + credential_name => p_credential_name + ); + + l_result.put('status', 'success'); + l_result.put('message', 'Network Load Balancer policies listed successfully'); + l_result.put('status_code', l_resp.status_code); + l_result.put('headers', l_resp.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to list NLB policies: ' || SQLERRM); + RETURN l_result.to_clob(); + END list_nlb_policies; + + FUNCTION list_nlb_protocols ( + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB + IS + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_LIST_NETWORK_LOAD_BALANCERS_PROTOCOLS_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + BEGIN + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.LIST_NETWORK_LOAD_BALANCERS_PROTOCOLS( + opc_request_id => NULL, + limit => NULL, + page => NULL, + sort_order => NULL, + sort_by => NULL, + region => p_region, + endpoint => NULL, + credential_name => p_credential_name + ); + + l_result.put('status', 'success'); + l_result.put('message', 'Network Load Balancer protocols listed (deprecated endpoint)'); + l_result.put('status_code', l_resp.status_code); + l_result.put('headers', l_resp.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to list NLB protocols: ' || SQLERRM); + RETURN l_result.to_clob(); + END list_nlb_protocols; + + FUNCTION list_network_load_balancers ( + p_compartment_id IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB + IS + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_LIST_NETWORK_LOAD_BALANCERS_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_array JSON_ARRAY_T := JSON_ARRAY_T(); + l_item DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_NETWORK_LOAD_BALANCER_SUMMARY_T; + BEGIN + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.LIST_NETWORK_LOAD_BALANCERS( + compartment_id => p_compartment_id, + lifecycle_state => NULL, + display_name => NULL, + limit => NULL, + page => NULL, + sort_order => NULL, + sort_by => NULL, + opc_request_id => NULL, + region => p_region, + endpoint => NULL, + credential_name => p_credential_name + ); + + IF l_resp.response_body.items IS NOT NULL THEN + FOR i IN 1 .. l_resp.response_body.items.COUNT LOOP + l_item := l_resp.response_body.items(i); + l_array.append( + JSON_OBJECT( + 'name' VALUE l_item.display_name, + 'id' VALUE l_item.id, + 'lifecycle_state' VALUE l_item.lifecycle_state + ) + ); + END LOOP; + END IF; + + l_result.put('status', 'success'); + l_result.put('message', 'Network Load Balancers listed successfully'); + l_result.put('status_code', l_resp.status_code); + l_result.put('nlbs', l_array); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to list NLBs: ' || SQLERRM); + l_result.put('compartment_id', p_compartment_id); + RETURN l_result.to_clob(); + END list_network_load_balancers; + + FUNCTION update_network_load_balancer ( + p_network_load_balancer_id IN VARCHAR2, + p_display_name IN VARCHAR2, + p_is_preserve_source_destination IN NUMBER, + p_nlb_ip_version IN VARCHAR2, + p_freeform_tags IN CLOB, + p_defined_tags IN CLOB, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB + IS + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_UPDATE_NETWORK_LOAD_BALANCER_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_update_details DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_UPDATE_NETWORK_LOAD_BALANCER_DETAILS_T; + BEGIN + l_update_details := DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_UPDATE_NETWORK_LOAD_BALANCER_DETAILS_T( + display_name => p_display_name, + is_preserve_source_destination => p_is_preserve_source_destination, + nlb_ip_version => p_nlb_ip_version, + freeform_tags => CASE WHEN p_freeform_tags IS NOT NULL THEN JSON_ELEMENT_T.parse(p_freeform_tags) ELSE NULL END, + defined_tags => CASE WHEN p_defined_tags IS NOT NULL THEN JSON_ELEMENT_T.parse(p_defined_tags) ELSE NULL END + ); + + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.UPDATE_NETWORK_LOAD_BALANCER( + network_load_balancer_id => p_network_load_balancer_id, + update_network_load_balancer_details => l_update_details, + if_match => NULL, + opc_request_id => NULL, + region => p_region, + endpoint => NULL, + credential_name => p_credential_name + ); + + l_result.put('status', 'success'); + l_result.put('message', 'Network Load Balancer updated successfully'); + l_result.put('status_code', l_resp.status_code); + l_result.put('headers', l_resp.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to update network load balancer: ' || SQLERRM); + l_result.put('network_load_balancer_id', p_network_load_balancer_id); + RETURN l_result.to_clob(); + END update_network_load_balancer; + + FUNCTION update_listener ( + p_network_load_balancer_id IN VARCHAR2, + p_listener_name IN VARCHAR2, + p_default_backend_set_name IN VARCHAR2, + p_port IN NUMBER, + p_protocol IN VARCHAR2, + p_ip_version IN VARCHAR2, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB + IS + l_resp DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_UPDATE_LISTENER_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_update_listener DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_UPDATE_LISTENER_DETAILS_T; + BEGIN + l_update_listener := DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_UPDATE_LISTENER_DETAILS_T( + default_backend_set_name => p_default_backend_set_name, + port => p_port, + protocol => p_protocol, + ip_version => p_ip_version + ); + + l_resp := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.UPDATE_LISTENER( + network_load_balancer_id => p_network_load_balancer_id, + update_listener_details => l_update_listener, + listener_name => p_listener_name, + opc_request_id => NULL, + opc_retry_token => NULL, + if_match => NULL, + region => p_region, + endpoint => NULL, + credential_name => p_credential_name + ); + + l_result.put('status', 'success'); + l_result.put('message', 'Listener updated successfully'); + l_result.put('status_code', l_resp.status_code); + l_result.put('headers', l_resp.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to update listener: ' || SQLERRM); + l_result.put('network_load_balancer_id', p_network_load_balancer_id); + l_result.put('listener_name', p_listener_name); + RETURN l_result.to_clob(); + END update_listener; + + FUNCTION create_backend_set ( + p_network_load_balancer_id IN VARCHAR2, + p_name IN VARCHAR2, + p_policy IN VARCHAR2, + p_protocol IN VARCHAR2, + p_port IN NUMBER, + p_region IN VARCHAR2, + p_credential_name IN VARCHAR2 + ) RETURN CLOB + IS + l_health_checker DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_HEALTH_CHECKER_DETAILS_T; + l_backend_set DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_CREATE_BACKEND_SET_DETAILS_T; + l_response DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER_CREATE_BACKEND_SET_RESPONSE_T; + l_result JSON_OBJECT_T := JSON_OBJECT_T(); + l_backends DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_BACKEND_DETAILS_TBL := + DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_BACKEND_DETAILS_TBL(); + BEGIN + l_health_checker := DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_HEALTH_CHECKER_DETAILS_T( + protocol => p_protocol, + port => p_port, + retries => NULL, + timeout_in_millis => NULL, + interval_in_millis => NULL, + url_path => NULL, + response_body_regex => NULL, + return_code => NULL, + request_data => NULL, + response_data => NULL + ); + + l_backend_set := DBMS_CLOUD_OCI_NETWORK_LOAD_BALANCER_CREATE_BACKEND_SET_DETAILS_T( + name => p_name, + policy => p_policy, + is_preserve_source => NULL, + ip_version => NULL, + backends => l_backends, + health_checker => l_health_checker + ); + + l_response := DBMS_CLOUD_OCI_NLB_NETWORK_LOAD_BALANCER.CREATE_BACKEND_SET( + network_load_balancer_id => p_network_load_balancer_id, + create_backend_set_details => l_backend_set, + opc_request_id => NULL, + opc_retry_token => NULL, + if_match => NULL, + region => p_region, + endpoint => NULL, + credential_name => p_credential_name + ); + + l_result.put('status', 'success'); + l_result.put('message', 'Backend set created successfully'); + l_result.put('status_code', l_response.status_code); + l_result.put('headers', l_response.headers); + RETURN l_result.to_clob(); + EXCEPTION + WHEN OTHERS THEN + l_result := JSON_OBJECT_T(); + l_result.put('status', 'error'); + l_result.put('message', 'Failed to create backend set: ' || SQLERRM); + RETURN l_result.to_clob(); + END create_backend_set; + +END oci_network_load_balancer_agents; +/ + +------------------------------------------------------------------------------- +-- This procedure installs or refreshes the OCI NLB AI Agent tools in the +-- current schema. It drops any existing tool definitions and recreates them +-- pointing to the latest implementations in &&INSTALL_SCHEMA.oci_network_load_balancer_agents. +------------------------------------------------------------------------------- +CREATE OR REPLACE PROCEDURE initialize_network_load_balancer_tools +IS + PROCEDURE drop_tool_if_exists (tool_name IN VARCHAR2) IS + l_tool_count NUMBER; + l_sql CLOB; + BEGIN + l_sql := 'SELECT COUNT(*) FROM USER_AI_AGENT_TOOLS WHERE TOOL_NAME = :1'; + EXECUTE IMMEDIATE l_sql INTO l_tool_count USING tool_name; + IF l_tool_count > 0 THEN + DBMS_CLOUD_AI_AGENT.DROP_TOOL(tool_name); + END IF; + END drop_tool_if_exists; +BEGIN + -- Shared discovery tools (used by tasks in this repo) + drop_tool_if_exists(tool_name => 'LIST_SUBSCRIBED_REGIONS_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_SUBSCRIBED_REGIONS_TOOL', + attributes => '{ + "instruction": "Lists subscribed OCI regions for the tenancy. Use to help the user choose a region.", + "function": "oci_network_load_balancer_agents.list_subscribed_regions" + }', + description => 'Tool for listing subscribed OCI regions' + ); + + drop_tool_if_exists(tool_name => 'LIST_COMPARTMENTS_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_COMPARTMENTS_TOOL', + attributes => '{ + "instruction": "Lists compartments in the tenancy. Use to help the user choose a compartment for NLB operations.", + "function": "oci_network_load_balancer_agents.list_compartments" + }', + description => 'Tool for listing compartments in the tenancy' + ); + + -- NLB tools + drop_tool_if_exists(tool_name => 'GET_LISTENER_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'GET_LISTENER_TOOL', + attributes => '{ + "instruction": "Retrieve a specific listener from an OCI Network Load Balancer.", + "function": "oci_network_load_balancer_agents.get_listener" + }', + description => 'Tool for fetching an OCI NLB listener' + ); + + drop_tool_if_exists(tool_name => 'LIST_LISTENERS_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_LISTENERS_TOOL', + attributes => '{ + "instruction": "List all listeners associated with a specified OCI Network Load Balancer.", + "function": "oci_network_load_balancer_agents.list_listeners" + }', + description => 'Tool for listing OCI NLB listeners' + ); + + drop_tool_if_exists(tool_name => 'DELETE_LISTENER_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'DELETE_LISTENER_TOOL', + attributes => '{ + "instruction": "Delete a listener from a specified OCI Network Load Balancer (confirm before calling).", + "function": "oci_network_load_balancer_agents.delete_listener" + }', + description => 'Tool for deleting an OCI NLB listener' + ); + + drop_tool_if_exists(tool_name => 'DELETE_NETWORK_LOAD_BALANCER_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'DELETE_NETWORK_LOAD_BALANCER_TOOL', + attributes => '{ + "instruction": "Delete an OCI Network Load Balancer resource by its OCID (confirm before calling).", + "function": "oci_network_load_balancer_agents.delete_network_load_balancer" + }', + description => 'Tool for deleting an OCI Network Load Balancer' + ); + + drop_tool_if_exists(tool_name => 'CREATE_NETWORK_LOAD_BALANCER_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'CREATE_NETWORK_LOAD_BALANCER_TOOL', + attributes => '{ + "instruction": "Create a new OCI Network Load Balancer. Collect required inputs step-by-step and explain parameters with examples when asked.", + "function": "oci_network_load_balancer_agents.create_network_load_balancer" + }', + description => 'Tool for creating an OCI Network Load Balancer' + ); + + drop_tool_if_exists(tool_name => 'CREATE_LISTENER_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'CREATE_LISTENER_TOOL', + attributes => '{ + "instruction": "Create a listener for an existing OCI Network Load Balancer.", + "function": "oci_network_load_balancer_agents.create_listener" + }', + description => 'Tool for creating a listener on an OCI Network Load Balancer' + ); + + drop_tool_if_exists(tool_name => 'CHANGE_NLB_COMPARTMENT_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'CHANGE_NLB_COMPARTMENT_TOOL', + attributes => '{ + "instruction": "Move an OCI Network Load Balancer to a different compartment.", + "function": "oci_network_load_balancer_agents.change_nlb_compartment" + }', + description => 'Tool for changing the compartment of an OCI Network Load Balancer' + ); + + drop_tool_if_exists(tool_name => 'LIST_BACKEND_SETS_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_BACKEND_SETS_TOOL', + attributes => '{ + "instruction": "List backend sets configured on an OCI Network Load Balancer.", + "function": "oci_network_load_balancer_agents.list_backend_sets" + }', + description => 'Tool for listing backend sets of an OCI Network Load Balancer' + ); + + drop_tool_if_exists(tool_name => 'LIST_BACKENDS_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_BACKENDS_TOOL', + attributes => '{ + "instruction": "List backend servers within a specified backend set on an OCI Network Load Balancer.", + "function": "oci_network_load_balancer_agents.list_backends" + }', + description => 'Tool for listing backends in a backend set of an OCI Network Load Balancer' + ); + + drop_tool_if_exists(tool_name => 'LIST_NLB_HEALTHS_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_NLB_HEALTHS_TOOL', + attributes => '{ + "instruction": "List health summary status for all network load balancers in a compartment.", + "function": "oci_network_load_balancer_agents.list_nlb_healths" + }', + description => 'Tool for listing health summaries of network load balancers in a compartment' + ); + + drop_tool_if_exists(tool_name => 'LIST_NLB_POLICIES_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_NLB_POLICIES_TOOL', + attributes => '{ + "instruction": "List available load balancer policies for OCI Network Load Balancers.", + "function": "oci_network_load_balancer_agents.list_nlb_policies" + }', + description => 'Tool for listing NLB policies' + ); + + drop_tool_if_exists(tool_name => 'LIST_NLB_PROTOCOLS_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_NLB_PROTOCOLS_TOOL', + attributes => '{ + "instruction": "List supported protocols for OCI Network Load Balancers (deprecated endpoint).", + "function": "oci_network_load_balancer_agents.list_nlb_protocols" + }', + description => 'Tool for listing NLB protocols (deprecated)' + ); + + drop_tool_if_exists(tool_name => 'LIST_NETWORK_LOAD_BALANCERS_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'LIST_NETWORK_LOAD_BALANCERS_TOOL', + attributes => '{ + "instruction": "List all network load balancers in a compartment.", + "function": "oci_network_load_balancer_agents.list_network_load_balancers" + }', + description => 'Tool for listing network load balancers in a compartment' + ); + + drop_tool_if_exists(tool_name => 'UPDATE_NETWORK_LOAD_BALANCER_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'UPDATE_NETWORK_LOAD_BALANCER_TOOL', + attributes => '{ + "instruction": "Update a network load balancer (display name, tags, preserve flag, IP version).", + "function": "oci_network_load_balancer_agents.update_network_load_balancer" + }', + description => 'Tool for updating a network load balancer' + ); + + drop_tool_if_exists(tool_name => 'UPDATE_LISTENER_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'UPDATE_LISTENER_TOOL', + attributes => '{ + "instruction": "Update a listener on a network load balancer.", + "function": "oci_network_load_balancer_agents.update_listener" + }', + description => 'Tool for updating a listener' + ); + + drop_tool_if_exists(tool_name => 'CREATE_BACKEND_SET_TOOL'); + DBMS_CLOUD_AI_AGENT.CREATE_TOOL( + tool_name => 'CREATE_BACKEND_SET_TOOL', + attributes => '{ + "instruction": "Create a backend set on a network load balancer.", + "function": "oci_network_load_balancer_agents.create_backend_set" + }', + description => 'Tool for creating a backend set' + ); + + DBMS_OUTPUT.PUT_LINE('initialize_network_load_balancer_tools completed.'); +EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Error in initialize_network_load_balancer_tools: ' || SQLERRM); + RAISE; +END initialize_network_load_balancer_tools; +/ + +------------------------------------------------------------------------------- +-- Call the procedure to (re)create all OCI NLB AI Agent tools +------------------------------------------------------------------------------- +BEGIN + initialize_network_load_balancer_tools; +END; +/ + +alter session set current_schema = ADMIN; diff --git a/autonomous-ai-agents/oci_object_storage/oci_object_storage_agent.sql b/autonomous-ai-agents/oci_object_storage/oci_object_storage_agent.sql new file mode 100644 index 0000000..723d3cb --- /dev/null +++ b/autonomous-ai-agents/oci_object_storage/oci_object_storage_agent.sql @@ -0,0 +1,293 @@ +rem ============================================================================ +rem LICENSE +rem Copyright (c) 2025 Oracle and/or its affiliates. +rem Licensed under the Universal Permissive License (UPL), Version 1.0 +rem https://oss.oracle.com/licenses/upl/ +rem +rem NAME +rem oci_object_storage_agent.sql +rem +rem DESCRIPTION +rem Installer and configuration script for OCI Object Storage AI Agent +rem using DBMS_CLOUD_AI_AGENT (Select AI / Oracle AI Database). +rem +rem This script performs an interactive installation of an +rem OCI Object Storage AI Agent by: +rem - Prompting for target schema and AI Profile +rem - Granting required privileges to the target schema +rem - Creating an installer procedure in the target schema +rem - Registering an OCI Object Storage Task with supported tools +rem - Creating an OCI Object Storage AI Agent bound to the AI Profile +rem - Creating an OCI Object Storage Team linking the agent and task +rem - Executing the installer procedure to complete setup +rem +rem RELEASE VERSION +rem 1.0 +rem +rem RELEASE DATE +rem 26-Jan-2026 +rem +rem MAJOR CHANGES IN THIS RELEASE +rem - Initial release +rem - Added OCI Object Storage task, agent, and team registration +rem - Interactive installer with schema and AI profile prompts +rem +rem SCRIPT STRUCTURE +rem 1. Initialization: +rem - Enable SQL*Plus settings and error handling +rem - Prompt for target schema and AI profile +rem +rem 2. Grants: +rem - Grant DBMS_CLOUD_AI_AGENT and DBMS_CLOUD privileges +rem to the target schema +rem +rem 3. Installer Procedure Creation: +rem - Create INSTALL_OCI_OBJECTSTORE_AGENT procedure +rem in the target schema +rem +rem 4. AI Registration: +rem - Drop and create OCI_OBJECTSTORE_TASKS +rem - Drop and create OCI_OBJECT_STORAGE_ADVISOR agent +rem - Drop and create OCI_OBJECTSTORE_TEAM +rem +rem 5. Execution: +rem - Execute installer procedure with AI profile parameter +rem +rem INSTALL INSTRUCTIONS +rem 1. Connect as ADMIN or a user with required privileges +rem +rem 2. Run the script using SQL*Plus or SQLcl: +rem +rem sqlplus admin@db @oci_object_storage_agent.sql +rem +rem 3. Provide inputs when prompted: +rem - Target schema name +rem - AI Profile name +rem +rem 4. Verify installation by confirming: +rem - OCI_OBJECTSTORE_TASKS task exists +rem - OCI_OBJECT_STORAGE_ADVISOR agent is created +rem - OCI_OBJECTSTORE_TEAM team is registered +rem +rem PARAMETERS +rem INSTALL_SCHEMA (Prompted) +rem Target schema where the installer procedure, +rem task, agent, and team are created. +rem +rem PROFILE_NAME (Prompted) +rem AI Profile name used to bind the OCI Object Storage agent. +rem +rem NOTES +rem - Script is safe to re-run; existing tasks, agents, +rem and teams are dropped and recreated. +rem +rem - Destructive Object Storage operations require +rem explicit user confirmation as enforced by task instructions. +rem +rem - Tool names referenced in the task must exactly match +rem USER_CLOUD_AI_AGENT_TOOLS.TOOL_NAME values. +rem +rem - Script exits immediately on SQL errors. +rem +rem ============================================================================ + + +SET SERVEROUTPUT ON +SET VERIFY OFF +WHENEVER SQLERROR EXIT SQL.SQLCODE + +PROMPT ====================================================== +PROMPT OCI Object Storage AI Agent Installer +PROMPT ====================================================== + +-- Target schema +ACCEPT SCHEMA_NAME CHAR PROMPT 'Enter target schema name: ' +DEFINE INSTALL_SCHEMA = '&SCHEMA_NAME' + +-- AI Profile +ACCEPT PROFILE_NAME CHAR PROMPT 'Enter AI Profile name to be used with the Agent: ' +DEFINE PROFILE_NAME = '&PROFILE_NAME' + +PROMPT ------------------------------------------------------ +PROMPT Installing into schema: &&INSTALL_SCHEMA +PROMPT Using AI Profile : &&PROFILE_NAME +PROMPT ------------------------------------------------------ + +---------------------------------------------------------------- +-- 1. Grants (safe to re-run) +---------------------------------------------------------------- +BEGIN + DBMS_OUTPUT.PUT_LINE('Granting required privileges to &&INSTALL_SCHEMA ...'); + + EXECUTE IMMEDIATE 'GRANT EXECUTE ON DBMS_CLOUD_AI_AGENT TO &&INSTALL_SCHEMA'; + EXECUTE IMMEDIATE 'GRANT EXECUTE ON DBMS_CLOUD TO &&INSTALL_SCHEMA'; + + DBMS_OUTPUT.PUT_LINE('Grants completed.'); +END; +/ +---------------------------------------------------------------- +-- 2. Create installer procedure in target schema +---------------------------------------------------------------- +PROMPT Creating installer procedure in &&INSTALL_SCHEMA ... + +CREATE OR REPLACE PROCEDURE &&INSTALL_SCHEMA..install_oci_objectstore_agent ( + p_profile_name IN VARCHAR2 +) +AUTHID DEFINER +AS +BEGIN + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); + DBMS_OUTPUT.PUT_LINE('Starting OCI Object Storage AI installation'); + DBMS_OUTPUT.PUT_LINE('Schema : ' || USER); + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); + + ------------------------------------------------------------ + -- DROP TASK + ------------------------------------------------------------ + BEGIN + DBMS_CLOUD_AI_AGENT.DROP_TASK('OCI_OBJECTSTORE_TASKS'); + DBMS_OUTPUT.PUT_LINE('Dropped task OCI_OBJECTSTORE_TASKS'); + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Task OCI_OBJECTSTORE_TASKS does not exist, skipping'); + END; + + ------------------------------------------------------------ + -- CREATE TASK + ------------------------------------------------------------ + DBMS_CLOUD_AI_AGENT.CREATE_TASK( + task_name => 'OCI_OBJECTSTORE_TASKS', + description => 'Comprehensive task covering OCI Object Storage operations', + attributes => '{ + "instruction": "Identify the intent of the user request and determine the correct object storage operation. ' + || 'Prompt the user only for necessary missing details. ' + || 'Ask clarifying questions if intent is ambiguous. ' + || 'When presenting any list, object, or JSON structure to the user, format it in a human-readable way — such as: ' + || '- Bullet points for simple lists. ' + || '- Indented JSON for structured responses. ' + || 'Use LIST_COMPARTMENTS_TOOL to list compartments. ' + || 'Use LIST_SUBSCRIBED_REGIONS_TOOL to list regions and confirm with user. ' + || 'Automatically derive namespace using GET_NAMESPACE_TOOL. ' + || 'Confirm destructive actions before execution. ' + || 'User request: {query}", + "tools": [ + "LIST_COMPARTMENTS_TOOL", + "LIST_SUBSCRIBED_REGIONS_TOOL", + "GET_NAMESPACE_TOOL", + "CREATE_BUCKET_TOOL", + "DELETE_BUCKET_TOOL", + "UPDATE_BUCKET_TOOL", + "MAKE_BUCKET_WRITABLE_TOOL", + "REENCRYPT_BUCKET_TOOL", + "UPDATE_NAMESPACE_METADATA_TOOL", + "LIST_BUCKETS_TOOL", + "GET_BUCKET_TOOL", + "LIST_OBJECTS_TOOL", + "HEAD_OBJECT_TOOL", + "GET_OBJECT_TOOL", + "RENAME_OBJECT_TOOL", + "COPY_OBJECT_TOOL", + "DELETE_OBJECT_TOOL", + "PUT_OBJECT_TOOL", + "CREATE_PREAUTHENTICATED_REQUEST_TOOL", + "LIST_PREAUTHENTICATED_REQUESTS_TOOL", + "GET_PREAUTHENTICATED_REQUEST_TOOL", + "DELETE_PREAUTHENTICATED_REQUEST_TOOL", + "CREATE_RETENTION_RULE_TOOL", + "LIST_RETENTION_RULES_TOOL", + "GET_RETENTION_RULE_TOOL", + "UPDATE_RETENTION_RULE_TOOL", + "DELETE_RETENTION_RULE_TOOL", + "CREATE_REPLICATION_POLICY_TOOL", + "LIST_REPLICATION_POLICIES_TOOL", + "GET_REPLICATION_POLICY_TOOL", + "DELETE_REPLICATION_POLICY_TOOL", + "LIST_REPLICATION_SOURCES_TOOL", + "PUT_OBJECT_LIFECYCLE_POLICY_TOOL", + "DELETE_OBJECT_LIFECYCLE_POLICY_TOOL", + "CREATE_MULTIPART_UPLOAD_TOOL", + "LIST_MULTIPART_UPLOADS_TOOL", + "UPLOAD_PART_TOOL", + "LIST_MULTIPART_UPLOAD_PARTS_TOOL", + "COMMIT_MULTIPART_UPLOAD_TOOL", + "ABORT_MULTIPART_UPLOAD_TOOL", + "LIST_WORK_REQUESTS_TOOL", + "GET_WORK_REQUEST_TOOL", + "LIST_WORK_REQUEST_LOGS_TOOL", + "LIST_WORK_REQUEST_ERRORS_TOOL", + "CANCEL_WORK_REQUEST_TOOL" + ], + "enable_human_tool": "true" + }' + ); + DBMS_OUTPUT.PUT_LINE('Created task OCI_OBJECTSTORE_TASKS'); + + ------------------------------------------------------------ + -- DROP AGENT + ------------------------------------------------------------ + BEGIN + DBMS_CLOUD_AI_AGENT.DROP_AGENT('OCI_OBJECT_STORAGE_ADVISOR'); + DBMS_OUTPUT.PUT_LINE('Dropped agent OCI_OBJECT_STORAGE_ADVISOR'); + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Agent OCI_OBJECT_STORAGE_ADVISOR does not exist, skipping'); + END; + + ------------------------------------------------------------ + -- CREATE AGENT + ------------------------------------------------------------ + DBMS_CLOUD_AI_AGENT.CREATE_AGENT( + agent_name => 'OCI_OBJECT_STORAGE_ADVISOR', + attributes => + '{' || + '"profile_name":"' || p_profile_name || '",' || + '"role":"You are an OCI Object Storage Advisor and Automation Specialist. ' || + 'You assist users with bucket and object management, lifecycle policies, retention rules, replication, multipart uploads, and work request monitoring. ' || + 'You confirm destructive actions and present results clearly using human-readable formatting."' || + '}', + description => + 'AI agent for advising and automating OCI Object Storage operations' + ); + DBMS_OUTPUT.PUT_LINE('Created agent OCI_OBJECT_STORAGE_ADVISOR'); + + ------------------------------------------------------------ + -- DROP TEAM + ------------------------------------------------------------ + BEGIN + DBMS_CLOUD_AI_AGENT.DROP_TEAM('OCI_OBJECTSTORE_TEAM'); + DBMS_OUTPUT.PUT_LINE('Dropped team OCI_OBJECTSTORE_TEAM'); + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Team OCI_OBJECTSTORE_TEAM does not exist, skipping'); + END; + + ------------------------------------------------------------ + -- CREATE TEAM + ------------------------------------------------------------ + DBMS_CLOUD_AI_AGENT.CREATE_TEAM( + team_name => 'OCI_OBJECTSTORE_TEAM', + attributes => '{ + "agents":[{"name":"OCI_OBJECT_STORAGE_ADVISOR","task":"OCI_OBJECTSTORE_TASKS"}], + "process":"sequential" + }' + ); + DBMS_OUTPUT.PUT_LINE('Created team OCI_OBJECTSTORE_TEAM'); + + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); + DBMS_OUTPUT.PUT_LINE('OCI Object Storage AI installation COMPLETE'); + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); +END install_oci_objectstore_agent; +/ +---------------------------------------------------------------- +-- 3. Execute installer in target schema +---------------------------------------------------------------- +PROMPT Executing installer procedure ... + +BEGIN + &&INSTALL_SCHEMA..install_oci_objectstore_agent('&&PROFILE_NAME'); +END; +/ + +PROMPT ====================================================== +PROMPT Installation finished successfully +PROMPT ====================================================== diff --git a/autonomous-ai-agents/oci_object_storage_agent_install.sql b/autonomous-ai-agents/oci_object_storage/oci_object_storage_tools.sql similarity index 94% rename from autonomous-ai-agents/oci_object_storage_agent_install.sql rename to autonomous-ai-agents/oci_object_storage/oci_object_storage_tools.sql index d4234cd..1ef594e 100644 --- a/autonomous-ai-agents/oci_object_storage_agent_install.sql +++ b/autonomous-ai-agents/oci_object_storage/oci_object_storage_tools.sql @@ -1,33 +1,85 @@ --- Copyright (c) 2025 Oracle and/or its affiliates. --- Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ --- --- Installer script for OCI Object Storage AI tools (Select AI Agent / Oracle AI Database) --- --- Purpose: --- Install a consolidated PL/SQL package and AI Agent tool registrations --- to automate OCI Object Storage operations via Select AI Agent (Oracle AI Database). --- --- Script Structure --- 1) Initialization: grants, configuration setup. --- 2) Package deployment: &&INSTALL_SCHEMA.oci_object_storage_agents (spec and body). --- 3) AI tool setup: creation of all Object Storage agent tools. --- --- Usage: --- sqlplus admin@db @oci_object_storage_agent_install.sql [CONFIG_JSON] --- Minimal: --- sqlplus admin@db @oci_object_storage_agent_install.sql --- --- Notes: --- - Optional CONFIG_JSON keys: --- * credential_name (string) --- * compartment_ocid (string) --- - You may also update config in OCI_AGENT_CONFIG after install. --- +rem ============================================================================ +rem LICENSE +rem Copyright (c) 2025 Oracle and/or its affiliates. +rem Licensed under the Universal Permissive License (UPL), Version 1.0 +rem https://oss.oracle.com/licenses/upl/ +rem +rem NAME +rem oci_object_storage_tools.sql +rem +rem DESCRIPTION +rem Installer script for OCI Object Storage AI tools +rem (Select AI Agent / Oracle AI Database). +rem +rem This script installs a consolidated PL/SQL package and registers +rem AI Agent tools used to automate OCI Object Storage operations +rem via Select AI Agent (Oracle AI Database). +rem +rem RELEASE VERSION +rem 1.0 +rem +rem RELEASE DATE +rem 26-Jan-2026 +rem +rem MAJOR CHANGES IN THIS RELEASE +rem - Initial release +rem - Added Object Storage AI agent tool registrations +rem +rem SCRIPT STRUCTURE +rem 1. Initialization: +rem - Grants +rem - Configuration setup +rem +rem 2. Package Deployment: +rem - &&INSTALL_SCHEMA.oci_object_storage_agents +rem (package specification and body) +rem +rem 3. AI Tool Setup: +rem - Creation of all Object Storage agent tools +rem +rem INSTALL INSTRUCTIONS +rem 1. Connect as ADMIN or a user with required privileges +rem +rem 2. Run the script using SQL*Plus or SQLcl: +rem +rem sqlplus admin@db @oci_object_storage_tools.sql [CONFIG_JSON] +rem +rem 3. Minimal install (uses defaults): +rem +rem sqlplus admin@db @oci_object_storage_tools.sql +rem +rem 4. Verify installation by checking tool registration +rem and package compilation status. +rem +rem PARAMETERS +rem INSTALL_SCHEMA (Required) +rem Schema in which the package and tools will be created. +rem +rem CONFIG_JSON (Optional) +rem JSON string used to configure OCI access. +rem +rem NOTES +rem - Optional CONFIG_JSON keys: +rem * credential_name (string) +rem * compartment_ocid (string) +rem +rem - Configuration can also be updated post-install +rem in the OCI_AGENT_CONFIG table. +rem +rem - This script is idempotent only if DROP logic +rem is explicitly enabled. +rem +rem +rem ============================================================================ + + SET SERVEROUTPUT ON SET VERIFY OFF -- First argument: Schema Name (Required) -DEFINE INSTALL_SCHEMA = '' +ACCEPT SCHEMA_NAME CHAR PROMPT 'Enter schema name: ' + +DEFINE INSTALL_SCHEMA = '&SCHEMA_NAME' -- Second argument: JSON config (optional) -- DEFINE INSTALL_CONFIG_JSON = q'({"credential_name": "MY_CRED", "compartment_name": "MY_COMP"})' @@ -40,7 +92,7 @@ DEFINE INSTALL_CONFIG_JSON = NULL -- • Parses the JSON config and persists credential, compartment. -- Ensures the Object Storage agent is fully ready for tool execution. ------------------------------------------------------------------------------- -CREATE OR REPLACE PROCEDURE initilize_object_storage_agent( +CREATE OR REPLACE PROCEDURE initialize_object_storage_agent( p_install_schema_name IN VARCHAR2, p_config_json IN CLOB ) @@ -58,15 +110,19 @@ IS 'DBMS_CLOUD', 'DBMS_CLOUD_ADMIN', 'DBMS_CLOUD_AI_AGENT', + 'DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE', 'DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE_LIST_OBJECTS_RESPONSE_T', 'DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE_LIST_OBJECT_VERSIONS_RESPONSE_T', 'DBMS_CLOUD_OCI_OBJECT_STORAGE_LIST_OBJECTS_T', + 'DBMS_CLOUD_OCI_OBJECT_STORAGE_BUCKET_T', + 'DBMS_CLOUD_OCI_OBJECT_STORAGE_BUCKET_SUMMARY_TBL', 'DBMS_CLOUD_OCI_OBJECT_STORAGE_OBJECT_SUMMARY_TBL', -- Head/Get/Put object likely types (best-effort) 'DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE_GET_OBJECT_RESPONSE_T', 'DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE_PUT_OBJECT_RESPONSE_T', 'DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE_HEAD_OBJECT_RESPONSE_T', 'DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE_HEAD_BUCKET_RESPONSE_T', + 'DBMS_CLOUD_OCI_OBJECT_STORAGE_COMMIT_MULTIPART_UPLOAD_PART_DETAILS_T', -- Buckets 'DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE_GET_BUCKET_RESPONSE_T', 'DBMS_CLOUD_OCI_OBS_OBJECT_STORAGE_LIST_BUCKETS_RESPONSE_T', @@ -337,13 +393,13 @@ BEGIN p_compartment_ocid => l_compartment_ocid ); - DBMS_OUTPUT.PUT_LINE('initilize_object_storage_agent completed for schema ' || l_schema_name); + DBMS_OUTPUT.PUT_LINE('initialize_object_storage_agent completed for schema ' || l_schema_name); EXCEPTION WHEN OTHERS THEN - DBMS_OUTPUT.PUT_LINE('Fatal error in initilize_object_storage_agent: ' || SQLERRM); + DBMS_OUTPUT.PUT_LINE('Fatal error in initialize_object_storage_agent: ' || SQLERRM); RAISE; -END initilize_object_storage_agent; +END initialize_object_storage_agent; / ------------------------------------------------------------------------------- @@ -352,7 +408,7 @@ END initilize_object_storage_agent; -- and stores the runtime settings from the JSON config. ------------------------------------------------------------------------------- BEGIN - initilize_object_storage_agent( + initialize_object_storage_agent( p_install_schema_name => '&&INSTALL_SCHEMA', p_config_json => &&INSTALL_CONFIG_JSON ); @@ -360,6 +416,68 @@ END; / alter session set current_schema = &&INSTALL_SCHEMA; + +/* +================================================================================ +Package: OCI_OBJECT_STORAGE_AGENTS +================================================================================ +Purpose +------- +This package provides a comprehensive set of PL/SQL helper functions that +expose Oracle Cloud Infrastructure (OCI) Object Storage operations as +AI-agent–callable tools for Oracle Autonomous Database Select AI / AI Agents. + +The package abstracts low-level OCI REST and SDK calls and offers a clean, +JSON-based interface that can be safely consumed by: + - Select AI Agents + - Oracle APEX applications + - Automation scripts + - Conversational AI workflows + +Key Capabilities +---------------- +• Automatic resolution of: + - Object Storage namespace + - Compartment OCID + - Credentials + using centrally managed configuration (OCI_AGENT_CONFIG) + +• Read-only operations: + - List buckets, objects, versions, multipart uploads + - Retrieve metadata (HEAD / GET) + - Inspect lifecycle, retention, replication, and work requests + +• Write & management operations: + - Create, update, delete buckets and objects + - Upload objects (single & multipart) + - Manage lifecycle policies, retention rules, replication + - Create and manage Pre-Authenticated Requests (PAR) + - Restore, rename, copy, re-encrypt objects and buckets + +• All functions: + - Return JSON (CLOB) responses + - Are stateless and idempotent where possible + - Are safe for AI-agent execution + +Configuration Model +------------------- +This package relies on a configuration table (OCI_AGENT_CONFIG) to store: + - OCI credential name + - Default compartment name / OCID + - Other reusable parameters + +End users only need to configure once; all tools reuse it automatically. + +Who Is This For? +---------------- +• DBAs automating OCI Object Storage from SQL +• Developers building APEX + AI integrations +• Platform teams creating reusable AI agents +• End users interacting with Object Storage via natural language + +================================================================================ +*/ + ------------------------------------------------------------------------ -- Package specification ------------------------------------------------------------------------ @@ -4037,7 +4155,7 @@ END oci_object_storage_agents; -- tools using the latest package methods in &&INSTALL_SCHEMA, ------------------------------------------------------------------------------- -CREATE OR REPLACE PROCEDURE initilize_object_storage_tools +CREATE OR REPLACE PROCEDURE initialize_object_storage_tools IS PROCEDURE drop_tool_if_exists (tool_name IN VARCHAR2) IS l_tool_count NUMBER; @@ -4052,406 +4170,406 @@ IS BEGIN ------------------------------------------------------------------------ -- AI TOOL: LIST_OBJECTS_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.list_objects + -- maps to oci_object_storage_agents.list_objects ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'LIST_OBJECTS_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'LIST_OBJECTS_TOOL', attributes => '{ "instruction": "List all objects in a bucket using resolved namespace and configured credentials; surfaces per-object metadata for inventory, audit, and pre/post operation workflows.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.list_objects" + "function": "oci_object_storage_agents.list_objects" }', description => 'Tool for listing objects in OCI Object Storage' ); ------------------------------------------------------------------------ -- AI TOOL: LIST_BUCKETS_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.list_buckets + -- maps to oci_object_storage_agents.list_buckets ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'LIST_BUCKETS_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'LIST_BUCKETS_TOOL', attributes => '{ "instruction": "List all Object Storage buckets visible to the configured compartment scope in the given region; useful for navigation, selection, and governance views.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.list_buckets" + "function": "oci_object_storage_agents.list_buckets" }', description => 'Tool for listing Object Storage buckets' ); ------------------------------------------------------------------------ -- AI TOOL: GET_BUCKET_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.get_bucket + -- maps to oci_object_storage_agents.get_bucket ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'GET_BUCKET_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'GET_BUCKET_TOOL', attributes => '{ "instruction": "Fetches a bucket’s configuration and summary properties in the given region to support governance, diagnostics, and detail panes.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.get_bucket" + "function": "oci_object_storage_agents.get_bucket" }', description => 'Tool for retrieving Object Storage bucket metadata' ); ------------------------------------------------------------------------ -- AI TOOL: HEAD_BUCKET_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.head_bucket + -- maps to oci_object_storage_agents.head_bucket ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'HEAD_BUCKET_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'HEAD_BUCKET_TOOL', attributes => '{ "instruction": "Performs a lightweight metadata probe (HEAD) on a bucket to validate existence and inspect headers without retrieving content.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.head_bucket" + "function": "oci_object_storage_agents.head_bucket" }', description => 'Tool for retrieving Object Storage bucket metadata headers' ); ------------------------------------------------------------------------ -- AI TOOL: HEAD_OBJECT_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.head_object + -- maps to oci_object_storage_agents.head_object ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'HEAD_OBJECT_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'HEAD_OBJECT_TOOL', attributes => '{ "instruction": "Performs an object metadata probe (HEAD) to validate existence and inspect headers such as etag and content-type without downloading payload.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.head_object" + "function": "oci_object_storage_agents.head_object" }', description => 'Tool for retrieving Object Storage object metadata headers' ); ------------------------------------------------------------------------ -- AI TOOL: LIST_MULTIPART_UPLOADS_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.list_multipart_uploads + -- maps to oci_object_storage_agents.list_multipart_uploads ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'LIST_MULTIPART_UPLOADS_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'LIST_MULTIPART_UPLOADS_TOOL', attributes => '{ "instruction": "List all in-progress multipart uploads for a bucket to help resume, commit, or clean up unfinished large-object transfers.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.list_multipart_uploads" + "function": "oci_object_storage_agents.list_multipart_uploads" }', description => 'Tool for listing multipart uploads in Object Storage' ); ------------------------------------------------------------------------ -- AI TOOL: LIST_MULTIPART_UPLOAD_PARTS_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.list_multipart_upload_parts + -- maps to oci_object_storage_agents.list_multipart_upload_parts ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'LIST_MULTIPART_UPLOAD_PARTS_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'LIST_MULTIPART_UPLOAD_PARTS_TOOL', attributes => '{ "instruction": "Inspects the parts uploaded for a given multipart session, enabling validation and completion logic for large transfers.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.list_multipart_upload_parts" + "function": "oci_object_storage_agents.list_multipart_upload_parts" }', description => 'Tool for listing multipart upload parts in Object Storage' ); ------------------------------------------------------------------------ -- AI TOOL: MAKE_BUCKET_WRITABLE_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.make_bucket_writable + -- maps to oci_object_storage_agents.make_bucket_writable ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'MAKE_BUCKET_WRITABLE_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'MAKE_BUCKET_WRITABLE_TOOL', attributes => '{ "instruction": "Transitions a bucket to a writable state when it is read-only; use before performing write operations.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.make_bucket_writable" + "function": "oci_object_storage_agents.make_bucket_writable" }', description => 'Tool to set an OCI Object Storage bucket as writable' ); ------------------------------------------------------------------------ -- AI TOOL: PUT_OBJECT_LIFECYCLE_POLICY_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.put_object_lifecycle_policy + -- maps to oci_object_storage_agents.put_object_lifecycle_policy ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'PUT_OBJECT_LIFECYCLE_POLICY_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'PUT_OBJECT_LIFECYCLE_POLICY_TOOL', attributes => '{ "instruction": "Defines lifecycle management rules on a bucket to transition or delete objects based on age or criteria.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.put_object_lifecycle_policy" + "function": "oci_object_storage_agents.put_object_lifecycle_policy" }', description => 'Tool to set lifecycle policies for OCI Object Storage buckets' ); ------------------------------------------------------------------------ -- AI TOOL: LIST_RETENTION_RULES_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.list_retention_rules + -- maps to oci_object_storage_agents.list_retention_rules ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'LIST_RETENTION_RULES_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'LIST_RETENTION_RULES_TOOL', attributes => '{ "instruction": "List retention rules on a bucket to assess compliance posture and cleanup eligibility.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.list_retention_rules" + "function": "oci_object_storage_agents.list_retention_rules" }', description => 'Tool for listing OCI Object Storage retention rules' ); ------------------------------------------------------------------------ -- AI TOOL: GET_RETENTION_RULE_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.get_retention_rule + -- maps to oci_object_storage_agents.get_retention_rule ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'GET_RETENTION_RULE_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'GET_RETENTION_RULE_TOOL', attributes => '{ "instruction": "Retrieves the full definition of a specific retention rule for review or update workflows.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.get_retention_rule" + "function": "oci_object_storage_agents.get_retention_rule" }', description => 'Tool for retrieving Object Storage retention rule details' ); ------------------------------------------------------------------------ -- AI TOOL: GET_OBJECT_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.get_object + -- maps to oci_object_storage_agents.get_object ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'GET_OBJECT_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'GET_OBJECT_TOOL', attributes => '{ "instruction": "Retrieves object metadata (not payload) to inform downstream decisions such as conditional reads, cache validation, or UI displays.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.get_object" + "function": "oci_object_storage_agents.get_object" }', description => 'Tool for retrieving Object Storage object metadata (summary)' ); ------------------------------------------------------------------------ -- AI TOOL: PUT_OBJECT_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.put_object + -- maps to oci_object_storage_agents.put_object ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'PUT_OBJECT_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'PUT_OBJECT_TOOL', attributes => '{ "instruction": "Upload object content to a bucket with an explicit MIME type; use for uploads and content updates.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.put_object" + "function": "oci_object_storage_agents.put_object" }', description => 'Tool to upload objects to OCI Object Storage' ); ------------------------------------------------------------------------ -- AI TOOL: LIST_PREAUTHENTICATED_REQUESTS_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.list_preauthenticated_requests + -- maps to oci_object_storage_agents.list_preauthenticated_requests ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'LIST_PREAUTHENTICATED_REQUESTS_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'LIST_PREAUTHENTICATED_REQUESTS_TOOL', attributes => '{ "instruction": "Lists existing Preauthenticated Requests (PARs) for a bucket to audit access links and manage sharing.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.list_preauthenticated_requests" + "function": "oci_object_storage_agents.list_preauthenticated_requests" }', description => 'Tool for listing preauthenticated requests (PARs)' ); ------------------------------------------------------------------------ -- AI TOOL: LIST_REPLICATION_POLICIES_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.list_replication_policies + -- maps to oci_object_storage_agents.list_replication_policies ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'LIST_REPLICATION_POLICIES_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'LIST_REPLICATION_POLICIES_TOOL', attributes => '{ "instruction": "Lists replication policies configured on a bucket to understand cross-region replication posture.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.list_replication_policies" + "function": "oci_object_storage_agents.list_replication_policies" }', description => 'Tool for listing Object Storage replication policies' ); ------------------------------------------------------------------------ -- AI TOOL: GET_REPLICATION_POLICY_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.get_replication_policy + -- maps to oci_object_storage_agents.get_replication_policy ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'GET_REPLICATION_POLICY_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'GET_REPLICATION_POLICY_TOOL', attributes => '{ "instruction": "Retrieves details of a specific replication policy for status and configuration inspection.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.get_replication_policy" + "function": "oci_object_storage_agents.get_replication_policy" }', description => 'Tool for retrieving replication policy details' ); ------------------------------------------------------------------------ -- AI TOOL: LIST_REPLICATION_SOURCES_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.list_replication_sources + -- maps to oci_object_storage_agents.list_replication_sources ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'LIST_REPLICATION_SOURCES_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'LIST_REPLICATION_SOURCES_TOOL', attributes => '{ "instruction": "Lists upstream replication sources associated with a bucket to understand replication topology.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.list_replication_sources" + "function": "oci_object_storage_agents.list_replication_sources" }', description => 'Tool for listing replication sources' ); ------------------------------------------------------------------------ -- AI TOOL: REENCRYPT_BUCKET_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.reencrypt_bucket + -- maps to oci_object_storage_agents.reencrypt_bucket ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'REENCRYPT_BUCKET_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'REENCRYPT_BUCKET_TOOL', attributes => '{ "instruction": "Initiates a bucket-level re-encryption operation, typically after KMS rotation or encryption policy changes.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.reencrypt_bucket" + "function": "oci_object_storage_agents.reencrypt_bucket" }', description => 'Tool to re-encrypt buckets' ); ------------------------------------------------------------------------ -- AI TOOL: REENCRYPT_OBJECT_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.reencrypt_object + -- maps to oci_object_storage_agents.reencrypt_object ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'REENCRYPT_OBJECT_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'REENCRYPT_OBJECT_TOOL', attributes => '{ "instruction": "Initiates re-encryption for a specific object, typically after KMS or encryption policy changes.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.reencrypt_object" + "function": "oci_object_storage_agents.reencrypt_object" }', description => 'Tool to re-encrypt objects' ); ------------------------------------------------------------------------ -- AI TOOL: RENAME_OBJECT_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.rename_object + -- maps to oci_object_storage_agents.rename_object ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'RENAME_OBJECT_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'RENAME_OBJECT_TOOL', attributes => '{ "instruction": "Renames or moves an object within a bucket by changing its key name.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.rename_object" + "function": "oci_object_storage_agents.rename_object" }', description => 'Tool to rename objects' ); ------------------------------------------------------------------------ -- AI TOOL: RESTORE_OBJECTS_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.restore_objects + -- maps to oci_object_storage_agents.restore_objects ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'RESTORE_OBJECTS_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'RESTORE_OBJECTS_TOOL', attributes => '{ "instruction": "Restores archived or versioned content for a limited duration to enable reads or rehydration.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.restore_objects" + "function": "oci_object_storage_agents.restore_objects" }', description => 'Tool to restore objects from Object Storage' ); ------------------------------------------------------------------------ -- AI TOOL: UPLOAD_PART_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.upload_part + -- maps to oci_object_storage_agents.upload_part ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'UPLOAD_PART_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'UPLOAD_PART_TOOL', attributes => '{ "instruction": "Uploads a single part for an ongoing multipart transfer; repeat to assemble large objects.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.upload_part" + "function": "oci_object_storage_agents.upload_part" }', description => 'Tool for multipart upload parts' ); ------------------------------------------------------------------------ -- AI TOOL: UPDATE_NAMESPACE_METADATA_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.update_namespace_metadata + -- maps to oci_object_storage_agents.update_namespace_metadata ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'UPDATE_NAMESPACE_METADATA_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'UPDATE_NAMESPACE_METADATA_TOOL', attributes => '{ "instruction": "Sets default namespace metadata such as default compartments for S3/Swift interoperability.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.update_namespace_metadata" + "function": "oci_object_storage_agents.update_namespace_metadata" }', description => 'Tool to update namespace metadata' ); ------------------------------------------------------------------------ -- AI TOOL: UPDATE_RETENTION_RULE_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.update_retention_rule + -- maps to oci_object_storage_agents.update_retention_rule ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'UPDATE_RETENTION_RULE_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'UPDATE_RETENTION_RULE_TOOL', attributes => '{ "instruction": "Modifies an existing retention rule on a bucket to change display name or retention duration.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.update_retention_rule" + "function": "oci_object_storage_agents.update_retention_rule" }', description => 'Tool to update retention rules' ); ------------------------------------------------------------------------ -- AI TOOL: LIST_WORK_REQUESTS_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.list_work_requests + -- maps to oci_object_storage_agents.list_work_requests ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'LIST_WORK_REQUESTS_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'LIST_WORK_REQUESTS_TOOL', attributes => '{ "instruction": "Lists Object Storage work requests for the configured compartment to monitor asynchronous operations.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.list_work_requests" + "function": "oci_object_storage_agents.list_work_requests" }', description => 'Tool for listing work requests' ); ------------------------------------------------------------------------ -- AI TOOL: LIST_WORK_REQUEST_ERRORS_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.list_work_request_errors + -- maps to oci_object_storage_agents.list_work_request_errors ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'LIST_WORK_REQUEST_ERRORS_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'LIST_WORK_REQUEST_ERRORS_TOOL', attributes => '{ "instruction": "Retrieves error items associated with a work request to aid troubleshooting.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.list_work_request_errors" + "function": "oci_object_storage_agents.list_work_request_errors" }', description => 'Tool for listing work request errors' ); ------------------------------------------------------------------------ -- AI TOOL: LIST_WORK_REQUEST_LOGS_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.list_work_request_logs + -- maps to oci_object_storage_agents.list_work_request_logs ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'LIST_WORK_REQUEST_LOGS_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'LIST_WORK_REQUEST_LOGS_TOOL', attributes => '{ "instruction": "Retrieves log messages for a work request to track progress and diagnose issues.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.list_work_request_logs" + "function": "oci_object_storage_agents.list_work_request_logs" }', description => 'Tool for listing work request logs' ); ------------------------------------------------------------------------ -- AI TOOL: GET_WORK_REQUEST_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.get_work_request + -- maps to oci_object_storage_agents.get_work_request ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'GET_WORK_REQUEST_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'GET_WORK_REQUEST_TOOL', attributes => '{ "instruction": "Retrieves the current status and key attributes of a specific work request for monitoring.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.get_work_request" + "function": "oci_object_storage_agents.get_work_request" }', description => 'Tool for retrieving work request details' ); ------------------------------------------------------------------------ -- AI TOOL: UPDATE_BUCKET_TOOL - -- maps to &&INSTALL_SCHEMA.oci_object_storage_agents.update_bucket + -- maps to oci_object_storage_agents.update_bucket ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'UPDATE_BUCKET_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'UPDATE_BUCKET_TOOL', attributes => '{ "instruction": "Updates bucket configuration such as display name, versioning state, public access, and object event settings.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.update_bucket" + "function": "oci_object_storage_agents.update_bucket" }', description => 'Tool to update OCI Object Storage buckets' ); @@ -4462,7 +4580,7 @@ BEGIN tool_name => 'CREATE_BUCKET_TOOL', attributes => '{ "instruction": "Creates a new Object Storage bucket in the specified region under the configured compartment scope.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.create_bucket" + "function": "oci_object_storage_agents.create_bucket" }', description => 'Tool to create Object Storage buckets' ); @@ -4473,7 +4591,7 @@ BEGIN tool_name => 'DELETE_BUCKET_TOOL', attributes => '{ "instruction": "Removes an Object Storage bucket that is already empty; use for deprovisioning.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.delete_bucket" + "function": "oci_object_storage_agents.delete_bucket" }', description => 'Tool to delete Object Storage buckets' ); @@ -4484,7 +4602,7 @@ BEGIN tool_name => 'DELETE_OBJECT_TOOL', attributes => '{ "instruction": "Removes an object from a bucket; use for cleanup, archival workflows, or version management.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.delete_object" + "function": "oci_object_storage_agents.delete_object" }', description => 'Tool to delete objects from Object Storage' ); @@ -4495,7 +4613,7 @@ BEGIN tool_name => 'COPY_OBJECT_TOOL', attributes => '{ "instruction": "Copies an object to a destination bucket and region, enabling cross-bucket or cross-region duplication.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.copy_object" + "function": "oci_object_storage_agents.copy_object" }', description => 'Tool to copy objects between buckets/regions' ); @@ -4506,7 +4624,7 @@ BEGIN tool_name => 'CREATE_MULTIPART_UPLOAD_TOOL', attributes => '{ "instruction": "Initiates a multipart upload session for large object transfers.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.create_multipart_upload" + "function": "oci_object_storage_agents.create_multipart_upload" }', description => 'Tool to start multipart uploads' ); @@ -4517,7 +4635,7 @@ BEGIN tool_name => 'COMMIT_MULTIPART_UPLOAD_TOOL', attributes => '{ "instruction": "Finalizes a multipart upload by committing the selected parts.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.commit_multipart_upload" + "function": "oci_object_storage_agents.commit_multipart_upload" }', description => 'Tool to finalize multipart uploads' ); @@ -4528,7 +4646,7 @@ BEGIN tool_name => 'ABORT_MULTIPART_UPLOAD_TOOL', attributes => '{ "instruction": "Cancels an in-progress multipart upload and cleans up partial state.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.abort_multipart_upload" + "function": "oci_object_storage_agents.abort_multipart_upload" }', description => 'Tool to abort multipart uploads' ); @@ -4539,7 +4657,7 @@ BEGIN tool_name => 'CREATE_PREAUTHENTICATED_REQUEST_TOOL', attributes => '{ "instruction": "Creates a Preauthenticated Request (PAR) to grant time‑bound access to a bucket or object via a signed URL.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.create_preauthenticated_request" + "function": "oci_object_storage_agents.create_preauthenticated_request" }', description => 'Tool to create PARs for Object Storage' ); @@ -4550,7 +4668,7 @@ BEGIN tool_name => 'GET_PREAUTHENTICATED_REQUEST_TOOL', attributes => '{ "instruction": "Retrieves details of a Preauthenticated Request (PAR) for review, auditing, or client presentation.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.get_preauthenticated_request" + "function": "oci_object_storage_agents.get_preauthenticated_request" }', description => 'Tool to get PAR details' ); @@ -4561,7 +4679,7 @@ BEGIN tool_name => 'DELETE_PREAUTHENTICATED_REQUEST_TOOL', attributes => '{ "instruction": "Revokes a Preauthenticated Request (PAR) to immediately disable the shared link.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.delete_preauthenticated_request" + "function": "oci_object_storage_agents.delete_preauthenticated_request" }', description => 'Tool to delete PARs' ); @@ -4572,7 +4690,7 @@ BEGIN tool_name => 'CREATE_REPLICATION_POLICY_TOOL', attributes => '{ "instruction": "Creates a cross‑region replication policy from a source bucket to a destination bucket to enable continuous replication.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.create_replication_policy" + "function": "oci_object_storage_agents.create_replication_policy" }', description => 'Tool to create replication policies' ); @@ -4583,7 +4701,7 @@ BEGIN tool_name => 'DELETE_REPLICATION_POLICY_TOOL', attributes => '{ "instruction": "Removes a replication policy from a bucket to stop replication.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.delete_replication_policy" + "function": "oci_object_storage_agents.delete_replication_policy" }', description => 'Tool to delete replication policies' ); @@ -4594,7 +4712,7 @@ BEGIN tool_name => 'CREATE_RETENTION_RULE_TOOL', attributes => '{ "instruction": "Creates a retention rule on a bucket to enforce minimum retention periods for objects.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.create_retention_rule" + "function": "oci_object_storage_agents.create_retention_rule" }', description => 'Tool to create Object Storage retention rules' ); @@ -4605,7 +4723,7 @@ BEGIN tool_name => 'DELETE_RETENTION_RULE_TOOL', attributes => '{ "instruction": "Removes an existing retention rule from a bucket.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.delete_retention_rule" + "function": "oci_object_storage_agents.delete_retention_rule" }', description => 'Tool to delete Object Storage retention rules' ); @@ -4616,7 +4734,7 @@ BEGIN tool_name => 'DELETE_OBJECT_LIFECYCLE_POLICY_TOOL', attributes => '{ "instruction": "Removes the lifecycle policy from a bucket to stop automated transitions or deletions.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.delete_object_lifecycle_policy" + "function": "oci_object_storage_agents.delete_object_lifecycle_policy" }', description => 'Tool to delete lifecycle policy on a bucket' ); @@ -4627,7 +4745,7 @@ BEGIN tool_name => 'CANCEL_WORK_REQUEST_TOOL', attributes => '{ "instruction": "Requests cancellation of an asynchronous Object Storage work request.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.cancel_work_request" + "function": "oci_object_storage_agents.cancel_work_request" }', description => 'Tool to cancel Object Storage work requests' ); @@ -4638,20 +4756,20 @@ BEGIN tool_name => 'GET_NAMESPACE_TOOL', attributes => '{ "instruction": "Resolves the tenancy’s Object Storage namespace for the given region; foundational for bucket and object operations.", - "function": "&&INSTALL_SCHEMA.oci_object_storage_agents.get_namespace" + "function": "oci_object_storage_agents.get_namespace" }', description => 'Tool to retrieve Object Storage namespace' ); -END initilize_object_storage_tools; +END initialize_object_storage_tools; / ------------------------------------------------------------------------------- -- Call the procedure to (re)create all OCI Vault AI Agent tools ------------------------------------------------------------------------------- BEGIN - initilize_object_storage_tools; + initialize_object_storage_tools; END; / -alter session set current_schema = ADMIN; +alter session set current_schema = ADMIN; \ No newline at end of file diff --git a/autonomous-ai-agents/oci_vault/oci_vault_agent.sql b/autonomous-ai-agents/oci_vault/oci_vault_agent.sql new file mode 100644 index 0000000..575cf38 --- /dev/null +++ b/autonomous-ai-agents/oci_vault/oci_vault_agent.sql @@ -0,0 +1,246 @@ +rem ============================================================================ +rem LICENSE +rem Copyright (c) 2025 Oracle and/or its affiliates. +rem Licensed under the Universal Permissive License (UPL), Version 1.0 +rem https://oss.oracle.com/licenses/upl/ +rem +rem NAME +rem oci_vault_agent.sql +rem +rem DESCRIPTION +rem Installer and configuration script for OCI Vault AI Agent +rem using DBMS_CLOUD_AI_AGENT (Select AI / Oracle AI Database). +rem +rem This script performs an interactive installation of an +rem OCI Vault AI Agent by: +rem - Prompting for target schema and AI Profile +rem - Granting required privileges to the target schema +rem - Creating an installer procedure in the target schema +rem - Registering an OCI Vault Task with supported Vault tools +rem - Creating an OCI Vault AI Agent bound to the specified AI Profile +rem - Creating an OCI Vault Team linking the agent and task +rem - Executing the installer procedure to complete setup +rem +rem RELEASE VERSION +rem 1.0 +rem +rem RELEASE DATE +rem 26-Jan-2026 +rem +rem MAJOR CHANGES IN THIS RELEASE +rem - Initial release +rem - Added OCI Vault task, agent, and team registration +rem - Interactive installer with schema and AI profile prompts +rem +rem SCRIPT STRUCTURE +rem 1. Initialization: +rem - Enable output and error handling +rem - Prompt for target schema and AI profile +rem +rem 2. Grants: +rem - Grant DBMS_CLOUD_AI_AGENT and DBMS_CLOUD privileges +rem to the target schema +rem +rem 3. Installer Procedure Creation: +rem - Create INSTALL_OCI_VAULT_AGENT procedure +rem in the target schema +rem +rem 4. AI Registration: +rem - Drop and create OCI_VAULT_TASKS +rem - Drop and create OCI_VAULT_ADVISOR agent +rem - Drop and create OCI_VAULT_TEAM +rem +rem 5. Execution: +rem - Execute installer procedure with AI profile parameter +rem +rem INSTALL INSTRUCTIONS +rem 1. Connect as ADMIN or a privileged user +rem +rem 2. Run the script using SQL*Plus or SQLcl: +rem +rem sqlplus admin@db @oci_vault_agent.sql +rem +rem 3. Provide inputs when prompted: +rem - Target schema name +rem - AI Profile name +rem +rem 4. Verify installation by confirming: +rem - OCI_VAULT_TASKS task exists +rem - OCI_VAULT_ADVISOR agent is created +rem - OCI_VAULT_TEAM team is registered +rem +rem PARAMETERS +rem INSTALL_SCHEMA (Prompted) +rem Target schema where the installer procedure, +rem task, agent, and team are created. +rem +rem PROFILE_NAME (Prompted) +rem AI Profile name used to bind the OCI Vault agent. +rem +rem NOTES +rem - Script is safe to re-run; existing tasks, agents, +rem and teams are dropped and recreated. +rem +rem - Destructive Vault operations require user confirmation +rem as enforced by agent task instructions. +rem +rem - Script exits immediately on SQL errors. +rem +rem ============================================================================ + + +SET SERVEROUTPUT ON +SET VERIFY OFF +WHENEVER SQLERROR EXIT SQL.SQLCODE + +PROMPT ====================================================== +PROMPT OCI Vault AI Agent Installer +PROMPT ====================================================== + +-- Target schema +ACCEPT SCHEMA_NAME CHAR PROMPT 'Enter target schema name: ' +DEFINE INSTALL_SCHEMA = '&SCHEMA_NAME' + +-- AI Profile +ACCEPT PROFILE_NAME CHAR PROMPT 'Enter AI Profile name to be used with the Agent: ' +DEFINE PROFILE_NAME = '&PROFILE_NAME' + +PROMPT ------------------------------------------------------ +PROMPT Installing into schema: &&INSTALL_SCHEMA +PROMPT Using AI Profile : &&PROFILE_NAME +PROMPT ------------------------------------------------------ + +---------------------------------------------------------------- +-- 1. Grants (safe to re-run) +---------------------------------------------------------------- +BEGIN + DBMS_OUTPUT.PUT_LINE('Granting required privileges to &&INSTALL_SCHEMA ...'); + EXECUTE IMMEDIATE 'GRANT EXECUTE ON DBMS_CLOUD_AI_AGENT TO &&INSTALL_SCHEMA'; + EXECUTE IMMEDIATE 'GRANT EXECUTE ON DBMS_CLOUD TO &&INSTALL_SCHEMA'; + DBMS_OUTPUT.PUT_LINE('Grants completed.'); +END; +/ + +---------------------------------------------------------------- +-- 2. Create installer procedure in target schema +---------------------------------------------------------------- +PROMPT Creating installer procedure in &&INSTALL_SCHEMA ... + +CREATE OR REPLACE PROCEDURE &&INSTALL_SCHEMA..install_oci_vault_agent ( + p_profile_name IN VARCHAR2 +) +AUTHID DEFINER +AS +BEGIN + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); + DBMS_OUTPUT.PUT_LINE('Starting OCI Vault AI installation'); + DBMS_OUTPUT.PUT_LINE('Schema : ' || USER); + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); + + ------------------------------------------------------------ + -- DROP & CREATE TASK + ------------------------------------------------------------ + BEGIN + DBMS_CLOUD_AI_AGENT.DROP_TASK('OCI_VAULT_TASKS'); + EXCEPTION + WHEN OTHERS THEN NULL; + END; + + DBMS_CLOUD_AI_AGENT.CREATE_TASK( + task_name => 'OCI_VAULT_TASKS', + description => 'Task for managing OCI Vault secrets and versions.', + attributes => '{ + "instruction": "Identify the intent of the user request and determine the correct OCI Vault operation. ' + || 'Prompt the user only for necessary missing details. ' + || 'Ask clarifying questions if intent is ambiguous. ' + || 'When presenting any list, object, or JSON structure to the user, format it in a human-readable way. ' + || 'Use LIST_SUBSCRIBED_REGIONS_TOOL to list regions and confirm with the user. ' + || 'Use LIST_SECRETS_TOOL to list secrets. ' + || 'Use GET_SECRET_TOOL to retrieve secret metadata. ' + || 'Use CREATE_SECRET_TOOL to create a secret. ' + || 'Use UPDATE_SECRET_TOOL to update metadata or rotate content. ' + || 'Use LIST_SECRET_VERSIONS_TOOL / GET_SECRET_VERSION_TOOL to inspect versions. ' + || 'Use SCHEDULE_SECRET_DELETION_TOOL / SCHEDULE_SECRET_VERSION_DELETION_TOOL for deletions (confirm first). ' + || 'Use CANCEL_SECRET_DELETION_TOOL / CANCEL_SECRET_VERSION_DELETION_TOOL to cancel scheduled deletion. ' + || 'Use CHANGE_SECRET_COMPARTMENT_TOOL to move a secret. ' + || 'Confirm destructive actions with the user before proceeding. ' + || 'User request: {query}", + "tools": [ + "LIST_SUBSCRIBED_REGIONS_TOOL", + "LIST_SECRETS_TOOL", + "GET_SECRET_TOOL", + "CREATE_SECRET_TOOL", + "UPDATE_SECRET_TOOL", + "LIST_SECRET_VERSIONS_TOOL", + "GET_SECRET_VERSION_TOOL", + "SCHEDULE_SECRET_DELETION_TOOL", + "SCHEDULE_SECRET_VERSION_DELETION_TOOL", + "CANCEL_SECRET_DELETION_TOOL", + "CANCEL_SECRET_VERSION_DELETION_TOOL", + "CHANGE_SECRET_COMPARTMENT_TOOL" + ], + "enable_human_tool": "true" + }' + ); + DBMS_OUTPUT.PUT_LINE('Created task OCI_VAULT_TASKS'); + + ------------------------------------------------------------ + -- DROP & CREATE AGENT + ------------------------------------------------------------ + BEGIN + DBMS_CLOUD_AI_AGENT.DROP_AGENT('OCI_VAULT_ADVISOR'); + DBMS_OUTPUT.PUT_LINE('Dropped agent OCI_VAULT_ADVISOR'); + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Agent OCI_VAULT_ADVISOR does not exist, skipping'); + END; + + DBMS_CLOUD_AI_AGENT.CREATE_AGENT( + agent_name => 'OCI_VAULT_ADVISOR', + attributes => + '{' || + '"profile_name":"' || p_profile_name || '",' || + '"role":"You are an OCI Vault Advisor. You help users list, inspect, create, update, and manage secret versions safely. You confirm destructive actions before executing and present results clearly."' || + '}', + description => 'AI agent for advising and automating OCI Vault operations' + ); + DBMS_OUTPUT.PUT_LINE('Created agent OCI_VAULT_ADVISOR'); + + ------------------------------------------------------------ + -- DROP & CREATE TEAM + ------------------------------------------------------------ + BEGIN + DBMS_CLOUD_AI_AGENT.DROP_TEAM('OCI_VAULT_TEAM'); + DBMS_OUTPUT.PUT_LINE('Dropped team OCI_VAULT_TEAM'); + EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Team OCI_VAULT_TEAM does not exist, skipping'); + END; + + DBMS_CLOUD_AI_AGENT.CREATE_TEAM( + team_name => 'OCI_VAULT_TEAM', + attributes => '{ + "agents":[{"name":"OCI_VAULT_ADVISOR","task":"OCI_VAULT_TASKS"}], + "process":"sequential" + }' + ); + DBMS_OUTPUT.PUT_LINE('Created team OCI_VAULT_TEAM'); + + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); + DBMS_OUTPUT.PUT_LINE('OCI Vault AI installation COMPLETE'); + DBMS_OUTPUT.PUT_LINE('--------------------------------------------'); +END install_oci_vault_agent; +/ + +---------------------------------------------------------------- +-- 3. Execute installer in target schema +---------------------------------------------------------------- +PROMPT Executing installer procedure ... +BEGIN + &&INSTALL_SCHEMA..install_oci_vault_agent('&&PROFILE_NAME'); +END; +/ + +PROMPT ====================================================== +PROMPT Installation finished successfully +PROMPT ====================================================== diff --git a/autonomous-ai-agents/oci_vault_agent_install.sql b/autonomous-ai-agents/oci_vault/oci_vault_tools.sql similarity index 94% rename from autonomous-ai-agents/oci_vault_agent_install.sql rename to autonomous-ai-agents/oci_vault/oci_vault_tools.sql index b6f0fdb..897065b 100644 --- a/autonomous-ai-agents/oci_vault_agent_install.sql +++ b/autonomous-ai-agents/oci_vault/oci_vault_tools.sql @@ -1,34 +1,84 @@ --- Copyright (c) 2025 Oracle and/or its affiliates. --- Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ --- --- Installer script for OCI Vault AI tools (Select AI Agent / Oracle AI Database) --- --- Purpose: --- Install a consolidated PL/SQL package and AI Agent tool registrations --- to automate OCI Vault operations via Select AI Agent (Oracle AI Database). --- --- Script Structure --- 1) Initialization: grants, configuration setup. --- 2) Package deployment: &&INSTALL_SCHEMA.oci_object_storage_agents (spec and body). --- 3) AI tool setup: creation of all Object Storage agent tools. --- --- Usage: --- sqlplus admin@db @oci_vault_agent_install.sql [CONFIG_JSON] --- Minimal: --- sqlplus admin@db @oci_vault_agent_install.sql --- --- --- Notes: --- - Optional CONFIG_JSON keys: --- * credential_name (string) --- * compartment_name (string) --- - You may also update config in OCI_AGENT_CONFIG after install. --- +rem ============================================================================ +rem LICENSE +rem Copyright (c) 2025 Oracle and/or its affiliates. +rem Licensed under the Universal Permissive License (UPL), Version 1.0 +rem https://oss.oracle.com/licenses/upl/ +rem +rem NAME +rem oci_vault_tools.sql +rem +rem DESCRIPTION +rem Installer script for OCI Vault AI tools +rem (Select AI Agent / Oracle AI Database). +rem +rem This script installs a consolidated PL/SQL package and registers +rem AI Agent tools used to automate OCI Vault operations +rem via Select AI Agent (Oracle AI Database). +rem +rem RELEASE VERSION +rem 1.0 +rem +rem RELEASE DATE +rem 26-Jan-2026 +rem +rem MAJOR CHANGES IN THIS RELEASE +rem - Initial release +rem - Added OCI Vault AI agent tool registrations +rem +rem SCRIPT STRUCTURE +rem 1. Initialization: +rem - Grants +rem - Configuration setup +rem +rem 2. Package Deployment: +rem - &&INSTALL_SCHEMA.oci_vault_agents +rem (package specification and body) +rem +rem 3. AI Tool Setup: +rem - Creation of all OCI Vault agent tools +rem +rem INSTALL INSTRUCTIONS +rem 1. Connect as ADMIN or a user with required privileges +rem +rem 2. Run the script using SQL*Plus or SQLcl: +rem +rem sqlplus admin@db @oci_vault_agent_install.sql [CONFIG_JSON] +rem +rem 3. Minimal install (uses defaults): +rem +rem sqlplus admin@db @oci_vault_tools.sql +rem +rem 4. Verify installation by checking tool registration +rem and package compilation status. +rem +rem PARAMETERS +rem INSTALL_SCHEMA (Required) +rem Schema in which the package and tools will be created. +rem +rem CONFIG_JSON (Optional) +rem JSON string used to configure OCI access. +rem +rem NOTES +rem - Optional CONFIG_JSON keys: +rem * credential_name (string) +rem * compartment_name (string) +rem +rem - Configuration can also be updated post-install +rem in the OCI_AGENT_CONFIG table. +rem +rem - This script is idempotent only if DROP logic +rem is explicitly enabled. +rem +rem +rem ============================================================================ + + SET SERVEROUTPUT ON SET VERIFY OFF -- First argument: Schema Name (Required) -DEFINE INSTALL_SCHEMA = '' +ACCEPT SCHEMA_NAME CHAR PROMPT 'Enter schema name: ' +DEFINE INSTALL_SCHEMA = '&SCHEMA_NAME' -- Second argument: JSON config (optional) -- DEFINE INSTALL_CONFIG_JSON = q'({"credential_name": "MY_CRED", "compartment_name": "MY_COMP"})' @@ -41,7 +91,7 @@ DEFINE INSTALL_CONFIG_JSON = NULL -- • Parses the JSON config and persists credential, compartment. -- Ensures the Vault agent is fully ready for tool execution. ------------------------------------------------------------------------------- -CREATE OR REPLACE PROCEDURE initilize_vault_agent( +CREATE OR REPLACE PROCEDURE initialize_vault_agent( p_install_schema_name IN VARCHAR2, p_config_json IN CLOB ) @@ -285,18 +335,18 @@ BEGIN p_compartment_ocid => l_compartment_ocid ); - DBMS_OUTPUT.PUT_LINE('initilize_vault_agent completed for schema ' || l_schema_name); + DBMS_OUTPUT.PUT_LINE('initialize_vault_agent completed for schema ' || l_schema_name); EXCEPTION WHEN OTHERS THEN - DBMS_OUTPUT.PUT_LINE('Fatal error in initilize_vault_agent: ' || SQLERRM); + DBMS_OUTPUT.PUT_LINE('Fatal error in initialize_vault_agent: ' || SQLERRM); RAISE; -END initilize_vault_agent; +END initialize_vault_agent; / ------------------------------------------------------------------------------- --- Call initilize_vault_agent procedure +-- Call initialize_vault_agent procedure ------------------------------------------------------------------------------- BEGIN - initilize_vault_agent( + initialize_vault_agent( p_install_schema_name => '&&INSTALL_SCHEMA', p_config_json => &&INSTALL_CONFIG_JSON ); @@ -1558,7 +1608,7 @@ END oci_vault_agents; -- current schema. It drops any existing tool definitions and recreates them -- pointing to the latest implementations in &&INSTALL_SCHEMA.oci_vault_agents. ------------------------------------------------------------------------------- -CREATE OR REPLACE PROCEDURE initilize_vault_tools +CREATE OR REPLACE PROCEDURE initialize_vault_tools IS PROCEDURE drop_tool_if_exists (tool_name IN VARCHAR2) IS l_tool_count NUMBER; @@ -1573,154 +1623,154 @@ IS BEGIN ------------------------------------------------------------------------ -- AI TOOL: LIST_SECRETS_TOOL - -- maps to &&INSTALL_SCHEMA.oci_vault_agents.list_secrets + -- maps to oci_vault_agents.list_secrets ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'LIST_SECRETS_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'LIST_SECRETS_TOOL', attributes => '{ "instruction": "Enumerate all secrets visible to this agent within the configured compartment of the specified region. Use to inventory secrets, review basic metadata (name/OCID, vault, lifecycle state, timestamps), and support governance. This tool never returns secret payloads.", - "function": "&&INSTALL_SCHEMA.oci_vault_agents.list_secrets" + "function": "oci_vault_agents.list_secrets" }', description => 'Tool for listing all secrets in a given OCI Vault compartment' ); ------------------------------------------------------------------------ -- AI TOOL: LIST_SECRET_VERSIONS_TOOL - -- maps to &&INSTALL_SCHEMA.oci_vault_agents.list_secret_versions + -- maps to oci_vault_agents.list_secret_versions ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'LIST_SECRET_VERSIONS_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'LIST_SECRET_VERSIONS_TOOL', attributes => '{ "instruction": "List every version of a secret to understand its rotation history and stage assignments. Use for auditing and troubleshooting rotations. This tool returns version metadata only, not secret contents.", - "function": "&&INSTALL_SCHEMA.oci_vault_agents.list_secret_versions" + "function": "oci_vault_agents.list_secret_versions" }', description => 'Tool for listing all versions of an OCI Vault secret' ); ------------------------------------------------------------------------ -- AI TOOL: GET_SECRET_VERSION_TOOL - -- maps to &&INSTALL_SCHEMA.oci_vault_agents.get_secret_version + -- maps to oci_vault_agents.get_secret_version ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'GET_SECRET_VERSION_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'GET_SECRET_VERSION_TOOL', attributes => '{ "instruction": "Retrieve metadata for a specific version of a secret, including stage and timing information, to verify the state of that version. Does not return the secret value.", - "function": "&&INSTALL_SCHEMA.oci_vault_agents.get_secret_version" + "function": "oci_vault_agents.get_secret_version" }', description => 'Tool for fetching a specific version of an OCI Vault secret' ); ------------------------------------------------------------------------ -- AI TOOL: UPDATE_SECRET_TOOL - -- maps to &&INSTALL_SCHEMA.oci_vault_agents.update_secret + -- maps to oci_vault_agents.update_secret ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'UPDATE_SECRET_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'UPDATE_SECRET_TOOL', attributes => '{ "instruction": "Update secret metadata or roll a new version. Use to rotate the secret by supplying new content or to adjust description, tags, or rules. When content is provided, a new CURRENT version is created in OCI Vault.", - "function": "&&INSTALL_SCHEMA.oci_vault_agents.update_secret" + "function": "oci_vault_agents.update_secret" }', description => 'Tool for updating an OCI Vault secret' ); ------------------------------------------------------------------------ -- AI TOOL: SCHEDULE_SECRET_DELETION_TOOL - -- maps to &&INSTALL_SCHEMA.oci_vault_agents.schedule_secret_deletion + -- maps to oci_vault_agents.schedule_secret_deletion ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'SCHEDULE_SECRET_DELETION_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'SCHEDULE_SECRET_DELETION_TOOL', attributes => '{ "instruction": "Schedule a delayed deletion of a secret. Use when decommissioning; the secret remains recoverable until the scheduled time and can be canceled before it executes.", - "function": "&&INSTALL_SCHEMA.oci_vault_agents.schedule_secret_deletion" + "function": "oci_vault_agents.schedule_secret_deletion" }', description => 'Tool for scheduling deletion of an OCI Vault secret' ); ------------------------------------------------------------------------ -- AI TOOL: SCHEDULE_SECRET_VERSION_DELETION_TOOL - -- maps to &&INSTALL_SCHEMA.oci_vault_agents.schedule_secret_version_deletion + -- maps to oci_vault_agents.schedule_secret_version_deletion ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'SCHEDULE_SECRET_VERSION_DELETION_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'SCHEDULE_SECRET_VERSION_DELETION_TOOL', attributes => '{ "instruction": "Schedule deletion of a specific secret version without removing the secret itself. Useful for pruning superseded versions while retaining the active one.", - "function": "&&INSTALL_SCHEMA.oci_vault_agents.schedule_secret_version_deletion" + "function": "oci_vault_agents.schedule_secret_version_deletion" }', description => 'Tool for scheduling deletion of a specific OCI Vault secret version' ); ------------------------------------------------------------------------ -- AI TOOL: CANCEL_SECRET_DELETION_TOOL - -- maps to &&INSTALL_SCHEMA.oci_vault_agents.cancel_secret_deletion + -- maps to oci_vault_agents.cancel_secret_deletion ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'CANCEL_SECRET_DELETION_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'CANCEL_SECRET_DELETION_TOOL', attributes => '{ "instruction": "Cancel a previously scheduled deletion of a secret and keep it active.", - "function": "&&INSTALL_SCHEMA.oci_vault_agents.cancel_secret_deletion" + "function": "oci_vault_agents.cancel_secret_deletion" }', description => 'Tool for cancelling a scheduled deletion of an OCI Vault secret' ); ------------------------------------------------------------------------ -- AI TOOL: CANCEL_SECRET_VERSION_DELETION_TOOL - -- maps to &&INSTALL_SCHEMA.oci_vault_agents.cancel_secret_version_deletion + -- maps to oci_vault_agents.cancel_secret_version_deletion ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'CANCEL_SECRET_VERSION_DELETION_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'CANCEL_SECRET_VERSION_DELETION_TOOL', attributes => '{ "instruction": "Cancel a previously scheduled deletion for a specific secret version.", - "function": "&&INSTALL_SCHEMA.oci_vault_agents.cancel_secret_version_deletion" + "function": "oci_vault_agents.cancel_secret_version_deletion" }', description => 'Tool for cancelling scheduled deletion of a specific secret version' ); ------------------------------------------------------------------------ -- AI TOOL: CHANGE_SECRET_COMPARTMENT_TOOL - -- maps to &&INSTALL_SCHEMA.oci_vault_agents.change_secret_compartment + -- maps to oci_vault_agents.change_secret_compartment ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'CHANGE_SECRET_COMPARTMENT_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'CHANGE_SECRET_COMPARTMENT_TOOL', attributes => '{ "instruction": "Move a secret to a different compartment to align with tenancy structure, permissions, or cost ownership. The secret remains the same resource with updated compartment context.", - "function": "&&INSTALL_SCHEMA.oci_vault_agents.change_secret_compartment" + "function": "oci_vault_agents.change_secret_compartment" }', description => 'Tool for changing the compartment of an OCI Vault secret' ); ------------------------------------------------------------------------ -- AI TOOL: CREATE_SECRET_TOOL - -- maps to &&INSTALL_SCHEMA.oci_vault_agents.create_secret + -- maps to oci_vault_agents.create_secret ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'CREATE_SECRET_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'CREATE_SECRET_TOOL', attributes => '{ "instruction": "Create a new secret in OCI Vault using the specified vault and key, establishing its initial CURRENT version with the provided plaintext. Use for onboarding new credentials or initializing managed secrets.", - "function": "&&INSTALL_SCHEMA.oci_vault_agents.create_secret" + "function": "oci_vault_agents.create_secret" }', description => 'Tool for creating a secret in OCI Vault (Select AI Agent / Oracle AI Database)' ); ------------------------------------------------------------------------ -- AI TOOL: GET_SECRET_TOOL - -- maps to &&INSTALL_SCHEMA.oci_vault_agents.get_secret + -- maps to oci_vault_agents.get_secret ------------------------------------------------------------------------ drop_tool_if_exists(tool_name => 'GET_SECRET_TOOL'); DBMS_CLOUD_AI_AGENT.CREATE_TOOL( tool_name => 'GET_SECRET_TOOL', attributes => '{ "instruction": "Retrieve existing secret metadata to inspect its state, associations, and timing details. Use for monitoring and diagnostics; this tool does not expose secret material.", - "function": "&&INSTALL_SCHEMA.oci_vault_agents.get_secret" + "function": "oci_vault_agents.get_secret" }', description => 'Tool for fetching an OCI Vault secret (Select AI Agent / Oracle AI Database)' ); @@ -1730,13 +1780,13 @@ EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Error in create_vault_tools: ' || SQLERRM); RAISE; -END initilize_vault_tools; +END initialize_vault_tools; / ------------------------------------------------------------------------------- -- Call the procedure to (re)create all OCI Vault AI Agent tools ------------------------------------------------------------------------------- BEGIN - initilize_vault_tools; + initialize_vault_tools; END; /