@@ -1004,7 +1004,7 @@ create or replace package body uc_ai_tools_api as
10041004 ) return uc_ai_tools.id%type
10051005 as
10061006 l_scope uc_ai_logger.scope := gc_scope_prefix || 'create_tool_from_schema';
1007-
1007+
10081008 l_tool_id uc_ai_tools.id%type;
10091009 l_properties json_object_t;
10101010 l_required_arr json_array_t;
@@ -1041,17 +1041,17 @@ create or replace package body uc_ai_tools_api as
10411041 p_created_by,
10421042 systimestamp
10431043 ) returning id into l_tool_id;
1044-
1044+
10451045 uc_ai_logger.log('Created tool with ID: ' || l_tool_id, l_scope);
10461046
10471047 if l_schema_clob is null then
10481048 return l_tool_id;
10491049 end if;
1050-
1050+
10511051 -- Extract properties and required array from schema
10521052 l_properties := treat(p_json_schema.get('properties') as json_object_t);
10531053 l_required_arr := treat(p_json_schema.get('required') as json_array_t);
1054-
1054+
10551055 -- Convert required array to key list for easier processing
10561056 if l_required_arr is not null then
10571057 <<required_loop>>
@@ -1060,7 +1060,7 @@ create or replace package body uc_ai_tools_api as
10601060 l_required_keys_arr(l_required_keys_arr.count) := l_required_arr.get_string(i);
10611061 end loop required_loop;
10621062 end if;
1063-
1063+
10641064 -- Create parameters from schema properties
10651065 create_parameters_recursive(
10661066 p_properties => l_properties
@@ -1069,7 +1069,7 @@ create or replace package body uc_ai_tools_api as
10691069 , p_created_by => p_created_by
10701070 , p_tool_id => l_tool_id
10711071 );
1072-
1072+
10731073 -- Create tags if provided
10741074 if p_tags is not null and p_tags.count > 0 then
10751075 forall i in 1 .. p_tags.count
@@ -1089,16 +1089,169 @@ create or replace package body uc_ai_tools_api as
10891089 systimestamp
10901090 );
10911091 end if;
1092-
1092+
10931093 uc_ai_logger.log('Successfully created tool with schema', l_scope, 'Tool ID: ' || l_tool_id);
1094-
1094+
10951095 return l_tool_id;
1096-
1096+
10971097 exception
10981098 when others then
10991099 uc_ai_logger.log_error('Error in create_tool_from_schema', l_scope, sqlerrm || ' ' || sys.dbms_utility.format_error_backtrace);
11001100 raise;
11011101 end create_tool_from_schema;
11021102
1103+ /*
1104+ * Creates or updates a tool definition from a JSON schema
1105+ *
1106+ * If a tool with the same code already exists, it will be updated.
1107+ * Parameters and tags are replaced (deleted and recreated) on update.
1108+ */
1109+ function merge_tool_from_schema(
1110+ p_tool_code in uc_ai_tools.code%type,
1111+ p_description in uc_ai_tools.description%type,
1112+ p_function_call in uc_ai_tools.function_call%type,
1113+ p_json_schema in json_object_t,
1114+ p_active in uc_ai_tools.active%type default 1,
1115+ p_version in uc_ai_tools.version%type default '1.0',
1116+ p_authorization_schema in uc_ai_tools.authorization_schema%type default null,
1117+ p_created_by in uc_ai_tools.created_by%type default coalesce(sys_context('APEX$SESSION','app_user'), sys_context('userenv', 'session_user')),
1118+ p_tags in apex_t_varchar2 default apex_t_varchar2()
1119+ ) return uc_ai_tools.id%type
1120+ as
1121+ l_scope uc_ai_logger.scope := gc_scope_prefix || 'merge_tool_from_schema';
1122+
1123+ l_tool_id uc_ai_tools.id%type;
1124+ l_existing_tool_id uc_ai_tools.id%type;
1125+ l_properties json_object_t;
1126+ l_required_arr json_array_t;
1127+ l_required_keys_arr json_key_list := json_key_list();
1128+ l_schema_clob clob;
1129+ begin
1130+ uc_ai_logger.log('Merging tool from schema', l_scope, 'Tool: ' || p_tool_code);
1131+
1132+ l_schema_clob := case when p_json_schema is not null then p_json_schema.to_clob else null end;
1133+
1134+ -- Check if tool already exists
1135+ begin
1136+ select id
1137+ into l_existing_tool_id
1138+ from uc_ai_tools
1139+ where code = p_tool_code;
1140+ exception
1141+ when no_data_found then
1142+ l_existing_tool_id := null;
1143+ end;
1144+
1145+ if l_existing_tool_id is not null then
1146+ -- Update existing tool
1147+ update uc_ai_tools
1148+ set description = p_description,
1149+ active = p_active,
1150+ response_schema = l_schema_clob,
1151+ version = p_version,
1152+ function_call = p_function_call,
1153+ authorization_schema = p_authorization_schema,
1154+ updated_by = p_created_by,
1155+ updated_at = systimestamp
1156+ where id = l_existing_tool_id;
1157+
1158+ l_tool_id := l_existing_tool_id;
1159+
1160+ uc_ai_logger.log('Updated existing tool with ID: ' || l_tool_id, l_scope);
1161+
1162+ -- Delete existing parameters (cascade will handle nested params)
1163+ delete from uc_ai_tool_parameters
1164+ where tool_id = l_tool_id;
1165+
1166+ -- Delete existing tags
1167+ delete from uc_ai_tool_tags
1168+ where tool_id = l_tool_id;
1169+ else
1170+ -- Create new tool record
1171+ insert into uc_ai_tools (
1172+ code,
1173+ description,
1174+ active,
1175+ response_schema,
1176+ version,
1177+ function_call,
1178+ authorization_schema,
1179+ created_by,
1180+ created_at,
1181+ updated_by,
1182+ updated_at
1183+ ) values (
1184+ p_tool_code,
1185+ p_description,
1186+ p_active,
1187+ l_schema_clob,
1188+ p_version,
1189+ p_function_call,
1190+ p_authorization_schema,
1191+ p_created_by,
1192+ systimestamp,
1193+ p_created_by,
1194+ systimestamp
1195+ ) returning id into l_tool_id;
1196+
1197+ uc_ai_logger.log('Created new tool with ID: ' || l_tool_id, l_scope);
1198+ end if;
1199+
1200+ if l_schema_clob is null then
1201+ return l_tool_id;
1202+ end if;
1203+
1204+ -- Extract properties and required array from schema
1205+ l_properties := treat(p_json_schema.get('properties') as json_object_t);
1206+ l_required_arr := treat(p_json_schema.get('required') as json_array_t);
1207+
1208+ -- Convert required array to key list for easier processing
1209+ if l_required_arr is not null then
1210+ <<required_loop>>
1211+ for i in 0 .. l_required_arr.get_size - 1 loop
1212+ l_required_keys_arr.extend;
1213+ l_required_keys_arr(l_required_keys_arr.count) := l_required_arr.get_string(i);
1214+ end loop required_loop;
1215+ end if;
1216+
1217+ -- Create parameters from schema properties
1218+ create_parameters_recursive(
1219+ p_properties => l_properties
1220+ , p_required_keys => l_required_keys_arr
1221+ , p_parent_param_id => null
1222+ , p_created_by => p_created_by
1223+ , p_tool_id => l_tool_id
1224+ );
1225+
1226+ -- Create tags if provided
1227+ if p_tags is not null and p_tags.count > 0 then
1228+ forall i in 1 .. p_tags.count
1229+ insert into uc_ai_tool_tags (
1230+ tool_id,
1231+ tag_name,
1232+ created_by,
1233+ created_at,
1234+ updated_by,
1235+ updated_at
1236+ ) values (
1237+ l_tool_id,
1238+ lower(p_tags(i)),
1239+ p_created_by,
1240+ systimestamp,
1241+ p_created_by,
1242+ systimestamp
1243+ );
1244+ end if;
1245+
1246+ uc_ai_logger.log('Successfully merged tool with schema', l_scope, 'Tool ID: ' || l_tool_id);
1247+
1248+ return l_tool_id;
1249+
1250+ exception
1251+ when others then
1252+ uc_ai_logger.log_error('Error in merge_tool_from_schema', l_scope, sqlerrm || ' ' || sys.dbms_utility.format_error_backtrace);
1253+ raise;
1254+ end merge_tool_from_schema;
1255+
11031256end uc_ai_tools_api;
11041257/
0 commit comments