NODEDC_1C/llm_normalizer/backend/src/services/assistantMcpDiscoveryRuntim...

122 lines
4.2 KiB
TypeScript

import {
runAssistantMcpDiscoveryRuntimeBridge,
type AssistantMcpDiscoveryRuntimeBridgeContract
} from "./assistantMcpDiscoveryRuntimeBridge";
import {
buildAssistantMcpDiscoveryTurnInput,
type AssistantMcpDiscoveryTurnInputContract,
type BuildAssistantMcpDiscoveryTurnInputAdapterInput
} from "./assistantMcpDiscoveryTurnInputAdapter";
import type { AssistantMcpDiscoveryPilotExecutorDeps } from "./assistantMcpDiscoveryPilotExecutor";
export const ASSISTANT_MCP_DISCOVERY_RUNTIME_ENTRY_POINT_SCHEMA_VERSION =
"assistant_mcp_discovery_runtime_entry_point_v1" as const;
export type AssistantMcpDiscoveryRuntimeEntryPointStatus =
| "bridge_executed"
| "skipped_not_applicable"
| "skipped_needs_more_context";
export interface RunAssistantMcpDiscoveryRuntimeEntryPointInput
extends BuildAssistantMcpDiscoveryTurnInputAdapterInput {
deps?: AssistantMcpDiscoveryPilotExecutorDeps;
}
export interface AssistantMcpDiscoveryRuntimeEntryPointContract {
schema_version: typeof ASSISTANT_MCP_DISCOVERY_RUNTIME_ENTRY_POINT_SCHEMA_VERSION;
policy_owner: "assistantMcpDiscoveryRuntimeEntryPoint";
entry_status: AssistantMcpDiscoveryRuntimeEntryPointStatus;
hot_runtime_wired: false;
discovery_attempted: boolean;
turn_input: AssistantMcpDiscoveryTurnInputContract;
bridge: AssistantMcpDiscoveryRuntimeBridgeContract | null;
reason_codes: string[];
}
function normalizeReasonCode(value: string): string | null {
const normalized = value
.trim()
.replace(/[^\p{L}\p{N}_.:-]+/gu, "_")
.replace(/^_+|_+$/g, "")
.toLowerCase();
return normalized.length > 0 ? normalized.slice(0, 120) : null;
}
function pushReason(target: string[], value: string): void {
const normalized = normalizeReasonCode(value);
if (normalized && !target.includes(normalized)) {
target.push(normalized);
}
}
function uniqueStrings(values: string[]): string[] {
const result: string[] = [];
for (const value of values) {
const text = String(value ?? "").trim();
if (text && !result.includes(text)) {
result.push(text);
}
}
return result;
}
function skippedContract(input: {
status: Exclude<AssistantMcpDiscoveryRuntimeEntryPointStatus, "bridge_executed">;
turnInput: AssistantMcpDiscoveryTurnInputContract;
reason: string;
}): AssistantMcpDiscoveryRuntimeEntryPointContract {
const reasonCodes = uniqueStrings(input.turnInput.reason_codes);
pushReason(reasonCodes, input.reason);
pushReason(reasonCodes, "runtime_entry_point_not_wired_to_hot_assistant_answer");
return {
schema_version: ASSISTANT_MCP_DISCOVERY_RUNTIME_ENTRY_POINT_SCHEMA_VERSION,
policy_owner: "assistantMcpDiscoveryRuntimeEntryPoint",
entry_status: input.status,
hot_runtime_wired: false,
discovery_attempted: false,
turn_input: input.turnInput,
bridge: null,
reason_codes: reasonCodes
};
}
export async function runAssistantMcpDiscoveryRuntimeEntryPoint(
input: RunAssistantMcpDiscoveryRuntimeEntryPointInput
): Promise<AssistantMcpDiscoveryRuntimeEntryPointContract> {
const turnInput = buildAssistantMcpDiscoveryTurnInput(input);
if (!turnInput.should_run_discovery) {
return skippedContract({
status: "skipped_not_applicable",
turnInput,
reason: "runtime_entry_point_skipped_supported_exact_turn"
});
}
if (!turnInput.turn_meaning_ref) {
return skippedContract({
status: "skipped_needs_more_context",
turnInput,
reason: "runtime_entry_point_skipped_missing_discovery_turn_meaning"
});
}
const bridge = await runAssistantMcpDiscoveryRuntimeBridge({
semanticDataNeed: turnInput.semantic_data_need,
turnMeaning: turnInput.turn_meaning_ref,
deps: input.deps
});
const reasonCodes = uniqueStrings([...turnInput.reason_codes, ...bridge.reason_codes]);
pushReason(reasonCodes, "runtime_entry_point_bridge_executed");
pushReason(reasonCodes, "runtime_entry_point_not_wired_to_hot_assistant_answer");
return {
schema_version: ASSISTANT_MCP_DISCOVERY_RUNTIME_ENTRY_POINT_SCHEMA_VERSION,
policy_owner: "assistantMcpDiscoveryRuntimeEntryPoint",
entry_status: "bridge_executed",
hot_runtime_wired: false,
discovery_attempted: true,
turn_input: turnInput,
bridge,
reason_codes: reasonCodes
};
}