Skip to content

Commit 462b651

Browse files
Merge pull request #45 from konradszymanski/feat/tools-api-upsert
feat(tools_api): add upsert support to create_tool_from_schema
2 parents f65168a + 5149d29 commit 462b651

4 files changed

Lines changed: 408 additions & 12 deletions

File tree

src/packages/uc_ai_tools_api.pkb

Lines changed: 162 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
11031256
end uc_ai_tools_api;
11041257
/

src/packages/uc_ai_tools_api.pks

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ as
4747

4848
/*
4949
* Creates a new tool definition from a JSON schema
50-
*
50+
*
5151
* Takes a JSON schema input and creates the corresponding records in
5252
* uc_ai_tools and uc_ai_tool_parameters tables.
53-
*
53+
*
5454
* @param p_tool_code Unique code for the tool
5555
* @param p_description Description of what the tool does
5656
* @param p_function_call PL/SQL function that executes the tool
@@ -60,7 +60,7 @@ as
6060
* @param p_authorization_schema Authorization schema if needed
6161
* @param p_created_by User creating the tool
6262
* @param p_tags Array of tags to associate with the tool
63-
*
63+
*
6464
* @return tool_id The ID of the created tool
6565
*/
6666
function create_tool_from_schema(
@@ -75,5 +75,37 @@ as
7575
p_tags in apex_t_varchar2 default apex_t_varchar2()
7676
) return uc_ai_tools.id%type;
7777

78+
/*
79+
* Creates or updates a tool definition from a JSON schema
80+
*
81+
* Takes a JSON schema input and creates or updates the corresponding records in
82+
* uc_ai_tools, uc_ai_tool_parameters, and uc_ai_tool_tags tables.
83+
* If a tool with the same code already exists, it will be updated and its
84+
* parameters and tags will be replaced.
85+
*
86+
* @param p_tool_code Unique code for the tool
87+
* @param p_description Description of what the tool does
88+
* @param p_function_call PL/SQL function that executes the tool
89+
* @param p_json_schema JSON schema defining the tool parameters
90+
* @param p_active Whether the tool is active (default 1)
91+
* @param p_version Tool version (default '1.0')
92+
* @param p_authorization_schema Authorization schema if needed
93+
* @param p_created_by User creating the tool
94+
* @param p_tags Array of tags to associate with the tool
95+
*
96+
* @return tool_id The ID of the created or updated tool
97+
*/
98+
function merge_tool_from_schema(
99+
p_tool_code in uc_ai_tools.code%type,
100+
p_description in uc_ai_tools.description%type,
101+
p_function_call in uc_ai_tools.function_call%type,
102+
p_json_schema in json_object_t,
103+
p_active in uc_ai_tools.active%type default 1,
104+
p_version in uc_ai_tools.version%type default '1.0',
105+
p_authorization_schema in uc_ai_tools.authorization_schema%type default null,
106+
p_created_by in uc_ai_tools.created_by%type default coalesce(sys_context('APEX$SESSION','app_user'), sys_context('userenv', 'session_user')),
107+
p_tags in apex_t_varchar2 default apex_t_varchar2()
108+
) return uc_ai_tools.id%type;
109+
78110
end uc_ai_tools_api;
79111
/

0 commit comments

Comments
 (0)