export interface AssistantAddressToolGateRuntimeInput { 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) => void; tryHandleLivingChat: ( modeDecision: { mode?: unknown; reason?: unknown }, addressRuntimeMeta: Record | null ) => Promise; nowIso: () => string; } export interface AssistantAddressToolGateRuntimeOutput { handled: boolean; response: ResponseType | null; } export async function runAssistantAddressToolGateRuntime( input: AssistantAddressToolGateRuntimeInput ): Promise> { if (Boolean(input.orchestrationDecision?.runAddressLane)) { return { handled: false, response: null }; } const runtimeMeta = input.addressRuntimeMeta && typeof input.addressRuntimeMeta === "object" ? input.addressRuntimeMeta : ({} as Record); 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 }; }