refs #739: preserve Smilegate changes before repository layout migration

This commit is contained in:
devmrko
2026-08-03 11:12:19 +09:00
parent 022ae7f9d2
commit 4d2964b5c6
58 changed files with 3002 additions and 291 deletions

View File

@@ -93,8 +93,12 @@ IS
v_unresolved JSON_ARRAY_T := JSON_ARRAY_T();
v_unmatched JSON_ARRAY_T := JSON_ARRAY_T();
v_mention_results JSON_ARRAY_T := JSON_ARRAY_T();
v_execution_tasks JSON_ARRAY_T := JSON_ARRAY_T();
v_seen_game_keys t_seen_game_keys;
v_result JSON_OBJECT_T := JSON_OBJECT_T();
v_reference_summary JSON_OBJECT_T := JSON_OBJECT_T();
v_select_ai_reference CLOB;
v_plan_status VARCHAR2(30);
v_matched_count PLS_INTEGER := 0;
v_data_eligible_count PLS_INTEGER := 0;
v_unmatched_count PLS_INTEGER := 0;
@@ -111,6 +115,14 @@ IS
v_mention_result JSON_OBJECT_T;
v_target JSON_OBJECT_T;
v_unmatched_item JSON_OBJECT_T;
v_execution_task JSON_OBJECT_T;
v_worker_arguments JSON_OBJECT_T;
v_fewshot_arguments JSON_OBJECT_T;
v_task_plan JSON_OBJECT_T;
v_task_reference JSON_OBJECT_T;
v_task_targets JSON_ARRAY_T;
v_excluded_mentions JSON_ARRAY_T;
v_task_question CLOB;
v_cursor SYS_REFCURSOR;
v_game_key VARCHAR2(128);
@@ -345,21 +357,52 @@ BEGIN
END LOOP;
END IF;
v_result.put('contractVersion', '1.0');
IF v_target_type = 'NONE' THEN
v_plan_status := 'NO_TARGET';
ELSIF v_matched_count = 0 THEN
v_plan_status := 'UNMATCHED';
ELSIF v_data_eligible_count = 0 THEN
v_plan_status := 'UNAVAILABLE';
ELSIF v_unmatched_count > 0 THEN
v_plan_status := 'PARTIAL';
ELSE
v_plan_status := 'SUPPORTED';
END IF;
-- This is the sole Select AI handoff contract. It is deliberately generic:
-- game values and physical objects come only from the database lookup above.
v_reference_summary.put('targetType', v_target_type);
v_reference_summary.put('status', v_plan_status);
v_reference_summary.put('gameTargets', v_supported);
v_select_ai_reference := '[GAME QUERY REFERENCE]' || CHR(10) || CHR(10)
|| v_reference_summary.to_clob()
|| CHR(10) || CHR(10)
|| 'Field meanings:' || CHR(10) || CHR(10)
|| '* targetType:' || CHR(10)
|| ' * NONE: No game was resolved.' || CHR(10)
|| ' * SINGLE: Exactly one game was resolved.' || CHR(10)
|| ' * MULTI: Multiple specific games were resolved.' || CHR(10)
|| ' * ALL: The query applies to all supported games.' || CHR(10)
|| '* status: The result of game-target resolution.' || CHR(10)
|| '* gameTargets: The exact games resolved by the DB lookup. Each item may include:' || CHR(10)
|| ' * gameKey: Canonical game identifier.' || CHR(10)
|| ' * gamePrefix: Prefix used for game-scoped objects.' || CHR(10)
|| ' * userMasterObjectName: Resolved user-master object for that game.' || CHR(10) || CHR(10)
|| 'Object-selection guidance:' || CHR(10) || CHR(10)
|| '* Use only the targets listed in gameTargets.' || CHR(10)
|| '* For NONE, use a game-neutral common object when it directly answers the question.' || CHR(10)
|| '* If no suitable common object exists, state that a game name is required.' || CHR(10)
|| '* Do not infer an unlisted game or game-scoped object.';
v_result.put('contractVersion', '2.0');
v_result.put('targetType', v_target_type);
v_result.put('scopeType', v_target_type);
v_result.put('selectAiReference', v_select_ai_reference);
v_result.put('extractScopeHint', v_scope_type);
IF v_target_type = 'NONE' THEN
v_result.put('status', 'NO_TARGET');
ELSIF v_matched_count = 0 THEN
v_result.put('status', 'UNMATCHED');
ELSIF v_data_eligible_count = 0 THEN
v_result.put('status', 'UNAVAILABLE');
ELSIF v_unmatched_count > 0 THEN
v_result.put('status', 'PARTIAL');
ELSE
v_result.put('status', 'SUPPORTED');
END IF;
v_result.put('status', v_plan_status);
-- `gameTargets` is the public downstream contract. The detailed `targets`
-- collection remains diagnostic evidence only for the MCP response.
v_result.put('gameTargets', v_supported);
v_result.put('targets', v_targets);
v_result.put('matchedGames', v_supported);
v_result.put('mentionResults', v_mention_results);
@@ -368,6 +411,66 @@ BEGIN
v_result.put('unresolvedTargets', v_unresolved);
v_result.put('dataIneligibleTargets', v_data_ineligible);
v_result.put('unmatchedGames', v_unmatched);
-- Dynamic ReAct work items. Every game identity and availability state comes
-- from the catalog lookup above; clients must not infer their own targets.
FOR i IN 0 .. v_targets.get_size - 1 LOOP
v_target := TREAT(v_targets.get(i) AS JSON_OBJECT_T);
IF v_target.get_string('gameKey') IS NOT NULL THEN
v_execution_task := JSON_OBJECT_T();
v_execution_task.put(
'action',
CASE
WHEN v_target.get_string('dataStatus') = 'AVAILABLE'
AND v_target.get_string('userMasterObjectName') IS NOT NULL
THEN 'QUERY'
ELSE 'REPORT_UNAVAILABLE'
END
);
v_execution_task.put('scopeGameKey', v_target.get_string('gameKey'));
v_execution_task.put('target', v_target);
IF v_execution_task.get_string('action') = 'QUERY' THEN
v_excluded_mentions := JSON_ARRAY_T();
FOR j IN 0 .. v_targets.get_size - 1 LOOP
v_candidate := TREAT(v_targets.get(j) AS JSON_OBJECT_T);
IF v_candidate.get_string('gameKey') <> v_target.get_string('gameKey')
AND v_candidate.get_string('mention') IS NOT NULL THEN
v_excluded_mentions.append(v_candidate.get_string('mention'));
END IF;
END LOOP;
-- Preserve the original question verbatim. The target-specific
-- queryPlan below is the separate, authoritative scope contract.
v_task_question := p_question;
v_task_reference := JSON_OBJECT_T();
v_task_targets := JSON_ARRAY_T();
v_task_targets.append(v_target);
v_task_reference.put('targetType', 'SINGLE');
v_task_reference.put('status', 'SUPPORTED');
v_task_reference.put('gameTargets', v_task_targets);
v_task_plan := JSON_OBJECT_T();
v_task_plan.put('contractVersion', '2.0');
v_task_plan.put('targetType', 'SINGLE');
v_task_plan.put('status', 'SUPPORTED');
v_task_plan.put('gameTargets', v_task_targets);
v_task_plan.put('selectAiReference',
'[GAME QUERY REFERENCE]' || CHR(10) || CHR(10) || v_task_reference.to_clob());
v_worker_arguments := JSON_OBJECT_T();
v_worker_arguments.put('prompt', v_task_question);
v_worker_arguments.put('scopeGameKey', v_target.get_string('gameKey'));
v_worker_arguments.put('queryPlan', v_task_plan);
v_fewshot_arguments := JSON_OBJECT_T();
v_fewshot_arguments.put('question', v_task_question);
v_fewshot_arguments.put('topK', 3);
v_execution_task.put('workerTool', 'oracle.select_ai.smilegate_fewshot_nl2sql');
v_execution_task.put('workerArguments', v_worker_arguments);
v_execution_task.put('fewShotArguments', v_fewshot_arguments);
END IF;
v_execution_tasks.append(v_execution_task);
END IF;
END LOOP;
v_result.put('executionTasks', v_execution_tasks);
v_result.put('nextAction', 'CALL_FEWSHOT');
CASE v_target_type