133 lines
4.6 KiB
TypeScript
133 lines
4.6 KiB
TypeScript
export interface AssistantAddressToolGateRuntimeInput<ResponseType = unknown> {
|
|
sessionId: string;
|
|
userMessage: string;
|
|
addressInputMessage: string;
|
|
orchestrationDecision: {
|
|
runAddressLane?: boolean;
|
|
[key: string]: unknown;
|
|
};
|
|
livingModeDecision: {
|
|
mode?: unknown;
|
|
[key: string]: unknown;
|
|
};
|
|
addressRuntimeMeta: {
|
|
attempted?: unknown;
|
|
applied?: unknown;
|
|
reason?: unknown;
|
|
fallbackRuleHit?: unknown;
|
|
sanitizedUserMessage?: unknown;
|
|
orchestrationContract?: unknown;
|
|
toolGateDecision?: unknown;
|
|
toolGateReason?: unknown;
|
|
predecomposeContract?: {
|
|
intent?: unknown;
|
|
aggregation_profile?: unknown;
|
|
period?: {
|
|
scope?: unknown;
|
|
} | null;
|
|
} | null;
|
|
semanticExtractionContract?: {
|
|
valid?: unknown;
|
|
quality?: unknown;
|
|
apply_canonical_recommended?: unknown;
|
|
reason_codes?: unknown;
|
|
} | null;
|
|
[key: string]: unknown;
|
|
} | null;
|
|
logEvent: (payload: Record<string, unknown>) => void;
|
|
tryHandleLivingChat: (
|
|
modeDecision: { mode?: unknown; reason?: unknown },
|
|
addressRuntimeMeta: Record<string, unknown> | null
|
|
) => Promise<ResponseType | null>;
|
|
nowIso: () => string;
|
|
}
|
|
|
|
export interface AssistantAddressToolGateRuntimeOutput<ResponseType = unknown> {
|
|
handled: boolean;
|
|
response: ResponseType | null;
|
|
}
|
|
|
|
export async function runAssistantAddressToolGateRuntime<ResponseType = unknown>(
|
|
input: AssistantAddressToolGateRuntimeInput<ResponseType>
|
|
): Promise<AssistantAddressToolGateRuntimeOutput<ResponseType>> {
|
|
if (Boolean(input.orchestrationDecision?.runAddressLane)) {
|
|
return {
|
|
handled: false,
|
|
response: null
|
|
};
|
|
}
|
|
|
|
const runtimeMeta =
|
|
input.addressRuntimeMeta && typeof input.addressRuntimeMeta === "object"
|
|
? input.addressRuntimeMeta
|
|
: ({} as Record<string, unknown>);
|
|
const predecomposeContract =
|
|
runtimeMeta.predecomposeContract && typeof runtimeMeta.predecomposeContract === "object"
|
|
? (runtimeMeta.predecomposeContract as {
|
|
intent?: unknown;
|
|
aggregation_profile?: unknown;
|
|
period?: { scope?: unknown } | null;
|
|
})
|
|
: null;
|
|
const predecomposePeriod =
|
|
predecomposeContract?.period && typeof predecomposeContract.period === "object"
|
|
? predecomposeContract.period
|
|
: null;
|
|
const semanticExtractionContract =
|
|
runtimeMeta.semanticExtractionContract && typeof runtimeMeta.semanticExtractionContract === "object"
|
|
? (runtimeMeta.semanticExtractionContract as {
|
|
valid?: unknown;
|
|
quality?: unknown;
|
|
apply_canonical_recommended?: unknown;
|
|
reason_codes?: unknown;
|
|
})
|
|
: null;
|
|
const semanticReasonCodes = Array.isArray(semanticExtractionContract?.reason_codes)
|
|
? semanticExtractionContract?.reason_codes
|
|
: [];
|
|
|
|
input.logEvent({
|
|
timestamp: input.nowIso(),
|
|
level: "info",
|
|
service: "assistant_loop",
|
|
message: "assistant_address_tool_gate_skip",
|
|
sessionId: input.sessionId,
|
|
details: {
|
|
session_id: input.sessionId,
|
|
user_message: input.userMessage,
|
|
effective_address_user_message: input.addressInputMessage,
|
|
address_llm_predecompose_attempted: Boolean(runtimeMeta.attempted),
|
|
address_llm_predecompose_applied: Boolean(runtimeMeta.applied),
|
|
address_llm_predecompose_reason: runtimeMeta.reason ?? null,
|
|
address_fallback_rule_hit: runtimeMeta.fallbackRuleHit ?? null,
|
|
address_sanitized_user_message: runtimeMeta.sanitizedUserMessage ?? null,
|
|
assistant_orchestration_contract_v1: runtimeMeta.orchestrationContract ?? null,
|
|
address_tool_gate_decision: runtimeMeta.toolGateDecision ?? null,
|
|
address_tool_gate_reason: runtimeMeta.toolGateReason ?? null,
|
|
address_llm_predecompose_contract_intent: predecomposeContract?.intent ?? null,
|
|
address_llm_predecompose_contract_aggregation_profile: predecomposeContract?.aggregation_profile ?? null,
|
|
address_llm_predecompose_contract_period_scope: predecomposePeriod?.scope ?? null,
|
|
address_semantic_contract_valid: semanticExtractionContract?.valid ?? null,
|
|
address_semantic_contract_quality: semanticExtractionContract?.quality ?? null,
|
|
address_semantic_apply_canonical_recommended:
|
|
semanticExtractionContract?.apply_canonical_recommended ?? null,
|
|
address_semantic_reason_codes: semanticReasonCodes
|
|
}
|
|
});
|
|
|
|
if (input.livingModeDecision?.mode === "chat") {
|
|
const chatHandled = await input.tryHandleLivingChat(input.livingModeDecision, runtimeMeta);
|
|
if (chatHandled) {
|
|
return {
|
|
handled: true,
|
|
response: chatHandled
|
|
};
|
|
}
|
|
}
|
|
|
|
return {
|
|
handled: false,
|
|
response: null
|
|
};
|
|
}
|