From 9f3749fd4acf39289cc1ce39f81c788b164b71c5 Mon Sep 17 00:00:00 2001 From: dctouch Date: Sat, 11 Apr 2026 10:24:16 +0300 Subject: [PATCH] =?UTF-8?q?=D0=93=D0=9B=D0=9E=D0=91=D0=90=D0=9B=D0=AC?= =?UTF-8?q?=D0=9D=D0=AB=D0=99=20=D0=A0=D0=95=D0=A4=D0=90=D0=9A=D0=A2=D0=9E?= =?UTF-8?q?=D0=A0=D0=98=D0=9D=D0=93=20=D0=90=D0=A0=D0=A5=D0=98=D0=A2=D0=95?= =?UTF-8?q?=D0=9A=D0=A2=D0=A3=D0=A0=D0=AB=20-=20=D0=A0=D0=B5=D1=84=D0=B0?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D1=8D=D1=82=D0=B0?= =?UTF-8?q?=D0=BF=D0=BE=D0=B2=20=202.692.72=20=D0=B8=202.732.76=20-=20=20?= =?UTF-8?q?=D1=82=D0=B8=D0=BF=D0=BE=D0=B1=D0=B5=D0=B7=D0=BE=D0=BF=D0=B0?= =?UTF-8?q?=D1=81=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20turn-runtime=20=D0=B1?= =?UTF-8?q?=D0=B8=D0=BB=D0=B4=D0=B5=D1=80=D0=B0=20=D0=B8=20=D1=83=D0=B1?= =?UTF-8?q?=D1=80=D0=B0=D0=BB=20=D0=BE=D1=81=D1=82=D0=B0=D1=82=D0=BA=D0=B8?= =?UTF-8?q?=20=D1=81=D0=BB=D0=B0=D0=B1=D1=8B=D1=85=20=D0=BA=D0=B0=D1=81?= =?UTF-8?q?=D1=82=D0=BE=D0=B2=20=D0=B2=20=D0=BC=D0=B0=D0=BF=D0=BF=D0=B8?= =?UTF-8?q?=D0=BD=D0=B3=D0=B5=20=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8=D0=BC?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B5=D0=B9:=20=20assistantTurnRuntimeInputB?= =?UTF-8?q?uilder.ts=20/=20=D0=9F=D0=BE=D0=B4=D0=BD=D1=8F=D0=BB=20=D1=82?= =?UTF-8?q?=D0=B8=D0=BF=D1=8B=20=D0=B2=20deps-=D0=B0=D0=B4=D0=B0=D0=BF?= =?UTF-8?q?=D1=82=D0=B5=D1=80=D0=B5=20=D0=B4=D0=BE=20=D0=BA=D0=BE=D0=BD?= =?UTF-8?q?=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=BE=D0=B2=20AssistantTurnRunti?= =?UTF-8?q?meBuilderDeps=20(sessions/normalizer/data-layer/query/chat/log)?= =?UTF-8?q?,=20=D1=83=D0=B1=D1=80=D0=B0=D0=BB=20unknown/any-=D0=BE=D0=B1?= =?UTF-8?q?=D0=B5=D1=80=D1=82=D0=BA=D0=B8:=20=20assistantTurnRuntimeDepsAd?= =?UTF-8?q?apter.ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/TECH/1CLLMARCH-FACT.md | 42 ++- .../assistantAddressAttemptRuntimeAdapter.js | 104 +++--- .../assistantTurnRuntimeDepsAdapter.js | 12 +- .../assistantAddressAttemptRuntimeAdapter.ts | 24 +- .../assistantTurnRuntimeDepsAdapter.ts | 41 +-- .../assistantTurnRuntimeInputBuilder.ts | 306 ++++++++++-------- 6 files changed, 309 insertions(+), 220 deletions(-) diff --git a/docs/TECH/1CLLMARCH-FACT.md b/docs/TECH/1CLLMARCH-FACT.md index 35d0e57..cde9f0c 100644 --- a/docs/TECH/1CLLMARCH-FACT.md +++ b/docs/TECH/1CLLMARCH-FACT.md @@ -1850,7 +1850,47 @@ Validation: - `assistantWave10SettlementCorrectiveRegression.test.ts` - `assistantLivingChatMode.test.ts` -Status: **In progress (Phase 2.1 + 2.2 + 2.3 + 2.4 + 2.5 + 2.6 + 2.7 + 2.8 + 2.9 + 2.10 + 2.11 + 2.12 + 2.13 + 2.14 + 2.15 + 2.16 + 2.17 + 2.18 + 2.19 + 2.20 + 2.21 + 2.22 + 2.23 + 2.24 + 2.25 + 2.26 + 2.27 + 2.28 + 2.29 + 2.30 + 2.31 + 2.32 + 2.33 + 2.34 + 2.35 + 2.36 + 2.37 + 2.38 + 2.39 + 2.40 + 2.41 + 2.42 + 2.43 + 2.44 + 2.45 + 2.46 + 2.47 + 2.48 + 2.49 + 2.50 + 2.51 + 2.52 + 2.53 + 2.54 + 2.55 + 2.56 + 2.57 + 2.58 + 2.59 + 2.60 + 2.61 + 2.62 + 2.63 + 2.64 + 2.65 + 2.66 + 2.67 + 2.68 completed)** +Implemented in current pass (Phase 2.69 + 2.70 + 2.71 + 2.72): +1. Finalized strict deps typing in turn runtime input builder: + - `assistantTurnRuntimeInputBuilder.ts` + - completed generic `AssistantTurnRuntimeBuilderDeps` wiring through address/deep runtime input contracts; + - removed residual weak casts from builder field projection. +2. Hardened turn runtime deps adapter contracts: + - `assistantTurnRuntimeDepsAdapter.ts` + - typed sessions/normalizer/data-layer/address-query/chat/log inputs directly from `AssistantTurnRuntimeBuilderDeps` contract slices; + - removed `unknown`/`any` wrappers from adapter mapping while preserving compatible handler signatures for optional args. +3. Preserved behavior of turn orchestration chain under stricter typing: + - bootstrap -> address attempt -> deep attempt flow remains unchanged at runtime. + +Validation: +1. `npm run build` passed. +2. Targeted turn/deps regression pack passed: + - `assistantTurnRuntimeInputBuilder.test.ts` + - `assistantTurnRuntimeDepsAdapter.test.ts` + - `assistantTurnAttemptRuntimeAdapter.test.ts` + - `assistantAddressAttemptRuntimeAdapter.test.ts` + +Implemented in current pass (Phase 2.73 + 2.74 + 2.75 + 2.76): +1. Removed remaining unsafe casts in address->living-chat bridge: + - `assistantAddressAttemptRuntimeAdapter.ts` + - replaced `mergeKnownOrganizations` dependency type with living-chat compatible contract; + - removed `as any` cast for `mergeKnownOrganizations` and removed final object cast to `RunAssistantLivingChatAttemptRuntimeInput`. +2. Added explicit mode-decision normalization before living-chat runtime handoff: + - mapped untyped `modeDecision` to typed `{ mode: string | null; reason: string | null }` contract. +3. Preserved behavior of address lane + living-chat fallback under stricter typing: + - runtime flow unchanged, only contract hardening. + +Validation: +1. `npm run build` passed. +2. Targeted address/living/turn regression pack passed: + - `assistantAddressAttemptRuntimeAdapter.test.ts` + - `assistantLivingChatAttemptRuntimeAdapter.test.ts` + - `assistantLivingChatHandlerRuntimeAdapter.test.ts` + - `assistantTurnRuntimeInputBuilder.test.ts` + - `assistantTurnRuntimeDepsAdapter.test.ts` + - `assistantTurnAttemptRuntimeAdapter.test.ts` + +Status: **In progress (Phase 2.1 + 2.2 + 2.3 + 2.4 + 2.5 + 2.6 + 2.7 + 2.8 + 2.9 + 2.10 + 2.11 + 2.12 + 2.13 + 2.14 + 2.15 + 2.16 + 2.17 + 2.18 + 2.19 + 2.20 + 2.21 + 2.22 + 2.23 + 2.24 + 2.25 + 2.26 + 2.27 + 2.28 + 2.29 + 2.30 + 2.31 + 2.32 + 2.33 + 2.34 + 2.35 + 2.36 + 2.37 + 2.38 + 2.39 + 2.40 + 2.41 + 2.42 + 2.43 + 2.44 + 2.45 + 2.46 + 2.47 + 2.48 + 2.49 + 2.50 + 2.51 + 2.52 + 2.53 + 2.54 + 2.55 + 2.56 + 2.57 + 2.58 + 2.59 + 2.60 + 2.61 + 2.62 + 2.63 + 2.64 + 2.65 + 2.66 + 2.67 + 2.68 + 2.69 + 2.70 + 2.71 + 2.72 + 2.73 + 2.74 + 2.75 + 2.76 completed)** ## Stage 3 (P2): Hybrid Semantic Layer (LLM + Deterministic Guards) diff --git a/llm_normalizer/backend/dist/services/assistantAddressAttemptRuntimeAdapter.js b/llm_normalizer/backend/dist/services/assistantAddressAttemptRuntimeAdapter.js index 6b22f35..3fb0766 100644 --- a/llm_normalizer/backend/dist/services/assistantAddressAttemptRuntimeAdapter.js +++ b/llm_normalizer/backend/dist/services/assistantAddressAttemptRuntimeAdapter.js @@ -35,52 +35,64 @@ async function runAssistantAddressAttemptRuntime(input) { logEvent: input.logEvent, messageIdFactory: input.messageIdFactory })); - const tryHandleLivingChat = async (modeDecision, addressRuntimeMeta = null) => runLivingChatAttemptRuntimeSafe((0, assistantLivingChatAttemptInputBuilder_1.buildAssistantLivingChatAttemptRuntimeInput)({ - sessionId: input.sessionId, - userMessage: input.userMessage, - sessionItems: input.sessionItems, - modeDecision, - sessionScope: { - knownOrganizations: input.sessionScope.knownOrganizations, - selectedOrganization: input.sessionScope.selectedOrganization, - activeOrganization: input.sessionScope.activeOrganization - }, - addressRuntimeMeta, - toNonEmptyString: input.toNonEmptyString, - mergeKnownOrganizations: input.mergeKnownOrganizations, - hasAssistantDataScopeMetaQuestionSignal: input.hasAssistantDataScopeMetaQuestionSignal, - shouldHandleAsAssistantCapabilityMetaQuery: input.shouldHandleAsAssistantCapabilityMetaQuery, - hasDestructiveDataActionSignal: input.hasDestructiveDataActionSignal, - hasDangerOrCoercionSignal: input.hasDangerOrCoercionSignal, - hasOperationalAdminActionRequestSignal: input.hasOperationalAdminActionRequestSignal, - hasOrganizationFactLookupSignal: input.hasOrganizationFactLookupSignal, - hasOrganizationFactFollowupSignal: input.hasOrganizationFactFollowupSignal, - shouldEmitOrganizationSelectionReply: input.shouldEmitOrganizationSelectionReply, - hasAssistantCapabilityQuestionSignal: input.hasAssistantCapabilityQuestionSignal, - resolveDataScopeProbe: input.resolveDataScopeProbe, - applyScriptGuard: input.applyScriptGuard, - applyGroundingGuard: input.applyGroundingGuard, - buildAssistantSafetyRefusalReply: input.buildAssistantSafetyRefusalReply, - buildAssistantDataScopeContractReply: input.buildAssistantDataScopeContractReply, - buildAssistantOrganizationFactBoundaryReply: input.buildAssistantOrganizationFactBoundaryReply, - buildAssistantDataScopeSelectionReply: input.buildAssistantDataScopeSelectionReply, - buildAssistantOperationalBoundaryReply: input.buildAssistantOperationalBoundaryReply, - buildAssistantCapabilityContractReply: input.buildAssistantCapabilityContractReply, - appendItem: input.appendItem, - getSession: input.getSession, - persistSession: input.persistSession, - cloneConversation: input.cloneConversation, - logEvent: input.logEvent, - messageIdFactory: input.messageIdFactory, - nowIso: input.nowIso, - payload: input.payload, - chatClient: input.chatClient, - loadAssistantCanonExcerpt: input.loadAssistantCanonExcerpt, - sanitizeOutgoingAssistantText: input.sanitizeOutgoingAssistantText, - defaultModel: input.defaultModel, - defaultBaseUrl: input.defaultBaseUrl, - defaultApiKey: input.defaultApiKey - })); + const tryHandleLivingChat = async (modeDecision, addressRuntimeMeta = null) => { + const normalizedModeDecision = (() => { + if (!modeDecision || typeof modeDecision !== "object") { + return undefined; + } + const candidate = modeDecision; + return { + mode: typeof candidate.mode === "string" ? candidate.mode : null, + reason: typeof candidate.reason === "string" ? candidate.reason : null + }; + })(); + return runLivingChatAttemptRuntimeSafe((0, assistantLivingChatAttemptInputBuilder_1.buildAssistantLivingChatAttemptRuntimeInput)({ + sessionId: input.sessionId, + userMessage: input.userMessage, + sessionItems: input.sessionItems, + modeDecision: normalizedModeDecision, + sessionScope: { + knownOrganizations: input.sessionScope.knownOrganizations, + selectedOrganization: input.sessionScope.selectedOrganization, + activeOrganization: input.sessionScope.activeOrganization + }, + addressRuntimeMeta, + toNonEmptyString: input.toNonEmptyString, + mergeKnownOrganizations: input.mergeKnownOrganizations, + hasAssistantDataScopeMetaQuestionSignal: input.hasAssistantDataScopeMetaQuestionSignal, + shouldHandleAsAssistantCapabilityMetaQuery: input.shouldHandleAsAssistantCapabilityMetaQuery, + hasDestructiveDataActionSignal: input.hasDestructiveDataActionSignal, + hasDangerOrCoercionSignal: input.hasDangerOrCoercionSignal, + hasOperationalAdminActionRequestSignal: input.hasOperationalAdminActionRequestSignal, + hasOrganizationFactLookupSignal: input.hasOrganizationFactLookupSignal, + hasOrganizationFactFollowupSignal: input.hasOrganizationFactFollowupSignal, + shouldEmitOrganizationSelectionReply: input.shouldEmitOrganizationSelectionReply, + hasAssistantCapabilityQuestionSignal: input.hasAssistantCapabilityQuestionSignal, + resolveDataScopeProbe: input.resolveDataScopeProbe, + applyScriptGuard: input.applyScriptGuard, + applyGroundingGuard: input.applyGroundingGuard, + buildAssistantSafetyRefusalReply: input.buildAssistantSafetyRefusalReply, + buildAssistantDataScopeContractReply: input.buildAssistantDataScopeContractReply, + buildAssistantOrganizationFactBoundaryReply: input.buildAssistantOrganizationFactBoundaryReply, + buildAssistantDataScopeSelectionReply: input.buildAssistantDataScopeSelectionReply, + buildAssistantOperationalBoundaryReply: input.buildAssistantOperationalBoundaryReply, + buildAssistantCapabilityContractReply: input.buildAssistantCapabilityContractReply, + appendItem: input.appendItem, + getSession: input.getSession, + persistSession: input.persistSession, + cloneConversation: input.cloneConversation, + logEvent: input.logEvent, + messageIdFactory: input.messageIdFactory, + nowIso: input.nowIso, + payload: input.payload, + chatClient: input.chatClient, + loadAssistantCanonExcerpt: input.loadAssistantCanonExcerpt, + sanitizeOutgoingAssistantText: input.sanitizeOutgoingAssistantText, + defaultModel: input.defaultModel, + defaultBaseUrl: input.defaultBaseUrl, + defaultApiKey: input.defaultApiKey + })); + }; const runAddressLaneAttempt = async (messageUsed, carryMeta, analysisDateHint) => runAddressLaneAttemptRuntimeSafe((0, assistantAddressLaneAttemptInputBuilder_1.buildAssistantAddressLaneAttemptRuntimeInput)({ messageUsed, carryMeta, diff --git a/llm_normalizer/backend/dist/services/assistantTurnRuntimeDepsAdapter.js b/llm_normalizer/backend/dist/services/assistantTurnRuntimeDepsAdapter.js index 6565eff..23ecdb3 100644 --- a/llm_normalizer/backend/dist/services/assistantTurnRuntimeDepsAdapter.js +++ b/llm_normalizer/backend/dist/services/assistantTurnRuntimeDepsAdapter.js @@ -4,12 +4,12 @@ exports.buildAssistantTurnRuntimeDeps = buildAssistantTurnRuntimeDeps; function buildAssistantTurnRuntimeDeps(input) { return { ...input.helpers, - ensureSession: (sessionId) => input.sessions.ensureSession(sessionId), - appendItem: (sessionId, item) => input.sessions.appendItem(sessionId, item), - getSession: (sessionId) => input.sessions.getSession(sessionId), - persistSession: (sessionState) => input.sessionLogger.persistSession(sessionState), - setInvestigationState: (sessionId, snapshot) => input.sessions.setInvestigationState(sessionId, snapshot), - normalize: (payload) => input.normalizerService.normalize(payload), + ensureSession: input.sessions.ensureSession, + appendItem: input.sessions.appendItem, + getSession: input.sessions.getSession, + persistSession: input.sessionLogger.persistSession, + setInvestigationState: input.sessions.setInvestigationState, + normalize: input.normalizerService.normalize, executeRouteRuntime: (route, fragmentText, options) => input.dataLayer.executeRouteRuntime(route, fragmentText, options), tryAddressQueryHandle: (messageUsed, options) => input.addressQueryService.tryHandle(messageUsed, options), chatClient: input.chatClient, diff --git a/llm_normalizer/backend/src/services/assistantAddressAttemptRuntimeAdapter.ts b/llm_normalizer/backend/src/services/assistantAddressAttemptRuntimeAdapter.ts index 3822be5..4bef588 100644 --- a/llm_normalizer/backend/src/services/assistantAddressAttemptRuntimeAdapter.ts +++ b/llm_normalizer/backend/src/services/assistantAddressAttemptRuntimeAdapter.ts @@ -48,7 +48,7 @@ export interface RunAssistantAddressAttemptRuntimeInput sessionScope: AddressSessionScope; mergeFollowupContextWithOrganizationScope: RunAssistantAddressLaneAttemptRuntimeInput["mergeFollowupContextWithOrganizationScope"]; runAddressQueryTryHandle: RunAssistantAddressLaneAttemptRuntimeInput["runAddressQueryTryHandle"]; - mergeKnownOrganizations: RunAssistantAddressLaneResponseAttemptRuntimeInput["mergeKnownOrganizations"]; + mergeKnownOrganizations: RunAssistantLivingChatAttemptRuntimeInput["mergeKnownOrganizations"]; hasAssistantDataScopeMetaQuestionSignal: RunAssistantLivingChatAttemptRuntimeInput["hasAssistantDataScopeMetaQuestionSignal"]; shouldHandleAsAssistantCapabilityMetaQuery: RunAssistantLivingChatAttemptRuntimeInput["shouldHandleAsAssistantCapabilityMetaQuery"]; hasDestructiveDataActionSignal: RunAssistantLivingChatAttemptRuntimeInput["hasDestructiveDataActionSignal"]; @@ -140,13 +140,24 @@ export async function runAssistantAddressAttemptRuntime( const tryHandleLivingChat: RunAssistantAddressRuntimeInput["tryHandleLivingChat"] = async ( modeDecision, addressRuntimeMeta = null - ) => - runLivingChatAttemptRuntimeSafe( + ) => { + const normalizedModeDecision: RunAssistantLivingChatAttemptRuntimeInput["modeDecision"] = (() => { + if (!modeDecision || typeof modeDecision !== "object") { + return undefined; + } + const candidate = modeDecision as { mode?: unknown; reason?: unknown }; + return { + mode: typeof candidate.mode === "string" ? candidate.mode : null, + reason: typeof candidate.reason === "string" ? candidate.reason : null + }; + })(); + + return runLivingChatAttemptRuntimeSafe( buildAssistantLivingChatAttemptRuntimeInput({ sessionId: input.sessionId, userMessage: input.userMessage, sessionItems: input.sessionItems, - modeDecision, + modeDecision: normalizedModeDecision, sessionScope: { knownOrganizations: input.sessionScope.knownOrganizations, selectedOrganization: input.sessionScope.selectedOrganization, @@ -154,7 +165,7 @@ export async function runAssistantAddressAttemptRuntime( }, addressRuntimeMeta, toNonEmptyString: input.toNonEmptyString, - mergeKnownOrganizations: input.mergeKnownOrganizations as any, + mergeKnownOrganizations: input.mergeKnownOrganizations, hasAssistantDataScopeMetaQuestionSignal: input.hasAssistantDataScopeMetaQuestionSignal, shouldHandleAsAssistantCapabilityMetaQuery: input.shouldHandleAsAssistantCapabilityMetaQuery, hasDestructiveDataActionSignal: input.hasDestructiveDataActionSignal, @@ -187,8 +198,9 @@ export async function runAssistantAddressAttemptRuntime( defaultModel: input.defaultModel, defaultBaseUrl: input.defaultBaseUrl, defaultApiKey: input.defaultApiKey - } as any) as RunAssistantLivingChatAttemptRuntimeInput + }) ); + }; const runAddressLaneAttempt: RunAssistantAddressRuntimeInput["runAddressLaneAttempt"] = async ( messageUsed, diff --git a/llm_normalizer/backend/src/services/assistantTurnRuntimeDepsAdapter.ts b/llm_normalizer/backend/src/services/assistantTurnRuntimeDepsAdapter.ts index c59390f..2ded1f9 100644 --- a/llm_normalizer/backend/src/services/assistantTurnRuntimeDepsAdapter.ts +++ b/llm_normalizer/backend/src/services/assistantTurnRuntimeDepsAdapter.ts @@ -1,26 +1,26 @@ import type { AssistantTurnRuntimeBuilderDeps } from "./assistantTurnRuntimeInputBuilder"; export interface AssistantTurnRuntimeDepsSessionsLike { - ensureSession: (sessionId: string) => unknown; - appendItem: (sessionId: string, item: unknown) => void; - getSession: (sessionId: string) => unknown; - setInvestigationState: (sessionId: string, snapshot: unknown) => void; + ensureSession: AssistantTurnRuntimeBuilderDeps["ensureSession"]; + appendItem: AssistantTurnRuntimeBuilderDeps["appendItem"]; + getSession: AssistantTurnRuntimeBuilderDeps["getSession"]; + setInvestigationState: AssistantTurnRuntimeBuilderDeps["setInvestigationState"]; } export interface AssistantTurnRuntimeDepsSessionLoggerLike { - persistSession: (sessionState: unknown) => void; + persistSession: AssistantTurnRuntimeBuilderDeps["persistSession"]; } export interface AssistantTurnRuntimeDepsNormalizerLike { - normalize: (payload: unknown) => Promise; + normalize: AssistantTurnRuntimeBuilderDeps["normalize"]; } export interface AssistantTurnRuntimeDepsDataLayerLike { - executeRouteRuntime: (route: string, fragmentText: string, options?: unknown) => Promise; + executeRouteRuntime: AssistantTurnRuntimeBuilderDeps["executeRouteRuntime"]; } export interface AssistantTurnRuntimeDepsAddressQueryServiceLike { - tryHandle: (messageUsed: string, options?: unknown) => Promise; + tryHandle: AssistantTurnRuntimeBuilderDeps["tryAddressQueryHandle"]; } type BuilderDepsProvidedByAdapter = Pick< @@ -58,11 +58,11 @@ export interface BuildAssistantTurnRuntimeDepsInput { normalizerService: AssistantTurnRuntimeDepsNormalizerLike; dataLayer: AssistantTurnRuntimeDepsDataLayerLike; addressQueryService: AssistantTurnRuntimeDepsAddressQueryServiceLike; - chatClient: unknown; - messageIdFactory: () => string; - nowIso: () => string; - defaultApiKey: string; - logEvent: (payload: Record) => void; + chatClient: AssistantTurnRuntimeBuilderDeps["chatClient"]; + messageIdFactory: AssistantTurnRuntimeBuilderDeps["messageIdFactory"]; + nowIso: AssistantTurnRuntimeBuilderDeps["nowIso"]; + defaultApiKey: AssistantTurnRuntimeBuilderDeps["defaultApiKey"]; + logEvent: AssistantTurnRuntimeBuilderDeps["logEvent"]; flags: { featureAssistantAddressQueryV1: boolean; featureAddressLlmPredecomposeV1: boolean; @@ -85,13 +85,14 @@ export function buildAssistantTurnRuntimeDeps( ): AssistantTurnRuntimeBuilderDeps { return { ...input.helpers, - ensureSession: (sessionId) => input.sessions.ensureSession(sessionId) as any, - appendItem: (sessionId, item) => input.sessions.appendItem(sessionId, item as any), - getSession: (sessionId) => input.sessions.getSession(sessionId) as any, - persistSession: (sessionState) => input.sessionLogger.persistSession(sessionState as any), - setInvestigationState: (sessionId, snapshot) => input.sessions.setInvestigationState(sessionId, snapshot), - normalize: (payload) => input.normalizerService.normalize(payload), - executeRouteRuntime: (route, fragmentText, options) => input.dataLayer.executeRouteRuntime(route, fragmentText, options), + ensureSession: input.sessions.ensureSession, + appendItem: input.sessions.appendItem, + getSession: input.sessions.getSession, + persistSession: input.sessionLogger.persistSession, + setInvestigationState: input.sessions.setInvestigationState, + normalize: input.normalizerService.normalize, + executeRouteRuntime: (route, fragmentText, options) => + input.dataLayer.executeRouteRuntime(route, fragmentText, options), tryAddressQueryHandle: (messageUsed, options) => input.addressQueryService.tryHandle(messageUsed, options), chatClient: input.chatClient, messageIdFactory: input.messageIdFactory, diff --git a/llm_normalizer/backend/src/services/assistantTurnRuntimeInputBuilder.ts b/llm_normalizer/backend/src/services/assistantTurnRuntimeInputBuilder.ts index fef9732..5e91d18 100644 --- a/llm_normalizer/backend/src/services/assistantTurnRuntimeInputBuilder.ts +++ b/llm_normalizer/backend/src/services/assistantTurnRuntimeInputBuilder.ts @@ -9,83 +9,104 @@ import type { RunAssistantUserTurnBootstrapRuntimeInput } from "./assistantUserTurnBootstrapRuntimeAdapter"; -export interface AssistantTurnRuntimeBuilderDeps { +type AddressAttemptRuntimeInput = RunAssistantAddressAttemptRuntimeInput; +type DeepTurnAttemptRuntimeInput = RunAssistantDeepTurnAttemptRuntimeInput; + +export interface AssistantTurnRuntimeBuilderDeps { ensureSession: RunAssistantUserTurnBootstrapRuntimeInput["ensureSession"]; appendItem: RunAssistantUserTurnBootstrapRuntimeInput["appendItem"]; getSession: RunAssistantUserTurnBootstrapRuntimeInput["getSession"]; persistSession: RunAssistantUserTurnBootstrapRuntimeInput["persistSession"]; - setInvestigationState: (sessionId: string, snapshot: unknown) => void; - normalize: (payload: unknown) => Promise; - executeRouteRuntime: (route: string, fragmentText: string, options?: unknown) => Promise; - tryAddressQueryHandle: (messageUsed: string, options?: unknown) => Promise; - chatClient: unknown; - messageIdFactory: () => string; - nowIso: () => string; - defaultApiKey: string; - logEvent: (payload: Record) => void; - featureAssistantAddressQueryV1: boolean; - featureAddressLlmPredecomposeV1: boolean; - featureInvestigationStateV1: boolean; - featureStateFollowupBindingV1: boolean; - featureContractsV11: boolean; - featureAnswerPolicyV11: boolean; - featureProblemCentricAnswerV1: boolean; - featureLifecycleAnswerV1: boolean; - defaultModel: string; - defaultBaseUrl: string; compactWhitespace: RunAssistantUserTurnBootstrapRuntimeInput["compactWhitespace"]; repairAddressMojibake: RunAssistantUserTurnBootstrapRuntimeInput["repairAddressMojibake"]; resolveRuntimeAnalysisContext: RunAssistantUserTurnBootstrapRuntimeInput["resolveRuntimeAnalysisContext"]; - runAddressLlmPreDecompose: (payload: unknown, userMessage: string) => Promise>; - buildAddressLlmPredecomposeContractV1: (...args: any[]) => unknown; - sanitizeAddressMessageForFallback: (...args: any[]) => unknown; - toNonEmptyString: (...args: any[]) => unknown; - resolveAddressFollowupCarryoverContext: (...args: any[]) => unknown; - resolveAssistantOrchestrationDecision: (...args: any[]) => unknown; - buildAddressDialogContinuationContractV2: (...args: any[]) => unknown; - mergeFollowupContextWithOrganizationScope: (...args: any[]) => unknown; - isRetryableAddressLimitedResult: (...args: any[]) => unknown; - mergeKnownOrganizations: (...args: any[]) => unknown; - hasAssistantDataScopeMetaQuestionSignal: (...args: any[]) => unknown; - shouldHandleAsAssistantCapabilityMetaQuery: (...args: any[]) => unknown; - hasDestructiveDataActionSignal: (...args: any[]) => unknown; - hasDangerOrCoercionSignal: (...args: any[]) => unknown; - hasOperationalAdminActionRequestSignal: (...args: any[]) => unknown; - hasOrganizationFactLookupSignal: (...args: any[]) => unknown; - hasOrganizationFactFollowupSignal: (...args: any[]) => unknown; - shouldEmitOrganizationSelectionReply: (...args: any[]) => unknown; - hasAssistantCapabilityQuestionSignal: (...args: any[]) => unknown; - resolveDataScopeProbe: () => unknown; - applyScriptGuard: (...args: any[]) => unknown; - applyGroundingGuard: (...args: any[]) => unknown; - buildAssistantSafetyRefusalReply: (...args: any[]) => unknown; - buildAssistantDataScopeContractReply: (...args: any[]) => unknown; - buildAssistantOrganizationFactBoundaryReply: (...args: any[]) => unknown; - buildAssistantDataScopeSelectionReply: (...args: any[]) => unknown; - buildAssistantOperationalBoundaryReply: (...args: any[]) => unknown; - buildAssistantCapabilityContractReply: (...args: any[]) => unknown; - loadAssistantCanonExcerpt: (...args: any[]) => unknown; - sanitizeOutgoingAssistantText: (value: unknown, fallback?: string) => string; - buildAddressDebugPayload: (...args: any[]) => unknown; - buildAddressFollowupOffer: (...args: any[]) => unknown; - buildFollowupStateBinding: (...args: any[]) => unknown; - resolveBusinessScopeAlignment: (...args: any[]) => unknown; - inferP0DomainFromMessage: (...args: any[]) => unknown; - resolveBusinessScopeFromLiveContext: (...args: any[]) => unknown; - extractRequirements: (...args: any[]) => unknown; - toExecutionPlan: (...args: any[]) => unknown; - enforceRbpLiveRoutePlan: (...args: any[]) => unknown; - enforceFaLiveRoutePlan: (...args: any[]) => unknown; - mapNoRouteReason: (...args: any[]) => unknown; - buildSkippedResult: (...args: any[]) => unknown; - evaluateCoverage: (...args: any[]) => unknown; - checkGrounding: (...args: any[]) => unknown; - collectRbpLiveRouteAudit: (...args: any[]) => unknown; - collectFaLiveRouteAudit: (...args: any[]) => unknown; - hasExplicitPeriodAnchorFromNormalized: (...args: any[]) => unknown; - extractDroppedIntentSegments: (...args: any[]) => unknown; - toDebugRoutes: (...args: any[]) => unknown; - extractExecutionState: (...args: any[]) => unknown; + runAddressLlmPreDecompose: ( + payload: AddressAttemptRuntimeInput["payload"], + userMessage: string + ) => Promise>; + tryAddressQueryHandle: AddressAttemptRuntimeInput["runAddressQueryTryHandle"]; + setInvestigationState: DeepTurnAttemptRuntimeInput["persistInvestigationState"]; + normalize: DeepTurnAttemptRuntimeInput["normalize"]; + executeRouteRuntime: DeepTurnAttemptRuntimeInput["executeRouteRuntime"]; + chatClient: AddressAttemptRuntimeInput["chatClient"]; + messageIdFactory: AddressAttemptRuntimeInput["messageIdFactory"]; + nowIso: AddressAttemptRuntimeInput["nowIso"]; + defaultApiKey: NonNullable["defaultApiKey"]>; + logEvent: AddressAttemptRuntimeInput["logEvent"]; + featureAssistantAddressQueryV1: AddressAttemptRuntimeInput["featureAssistantAddressQueryV1"]; + featureAddressLlmPredecomposeV1: AddressAttemptRuntimeInput["featureAddressLlmPredecomposeV1"]; + featureInvestigationStateV1: DeepTurnAttemptRuntimeInput["featureInvestigationStateV1"]; + featureStateFollowupBindingV1: DeepTurnAttemptRuntimeInput["featureStateFollowupBindingV1"]; + featureContractsV11: DeepTurnAttemptRuntimeInput["featureContractsV11"]; + featureAnswerPolicyV11: DeepTurnAttemptRuntimeInput["featureAnswerPolicyV11"]; + featureProblemCentricAnswerV1: DeepTurnAttemptRuntimeInput["featureProblemCentricAnswerV1"]; + featureLifecycleAnswerV1: DeepTurnAttemptRuntimeInput["featureLifecycleAnswerV1"]; + defaultModel: AddressAttemptRuntimeInput["defaultModel"]; + defaultBaseUrl: AddressAttemptRuntimeInput["defaultBaseUrl"]; + buildAddressLlmPredecomposeContractV1: + AddressAttemptRuntimeInput["buildAddressLlmPredecomposeContractV1"]; + sanitizeAddressMessageForFallback: AddressAttemptRuntimeInput["sanitizeAddressMessageForFallback"]; + toNonEmptyString: AddressAttemptRuntimeInput["toNonEmptyString"]; + resolveAddressFollowupCarryoverContext: + AddressAttemptRuntimeInput["resolveAddressFollowupCarryoverContext"]; + resolveAssistantOrchestrationDecision: + AddressAttemptRuntimeInput["resolveAssistantOrchestrationDecision"]; + buildAddressDialogContinuationContractV2: + AddressAttemptRuntimeInput["buildAddressDialogContinuationContractV2"]; + mergeFollowupContextWithOrganizationScope: + AddressAttemptRuntimeInput["mergeFollowupContextWithOrganizationScope"]; + isRetryableAddressLimitedResult: AddressAttemptRuntimeInput["isRetryableAddressLimitedResult"]; + mergeKnownOrganizations: AddressAttemptRuntimeInput["mergeKnownOrganizations"]; + hasAssistantDataScopeMetaQuestionSignal: + AddressAttemptRuntimeInput["hasAssistantDataScopeMetaQuestionSignal"]; + shouldHandleAsAssistantCapabilityMetaQuery: + AddressAttemptRuntimeInput["shouldHandleAsAssistantCapabilityMetaQuery"]; + hasDestructiveDataActionSignal: AddressAttemptRuntimeInput["hasDestructiveDataActionSignal"]; + hasDangerOrCoercionSignal: AddressAttemptRuntimeInput["hasDangerOrCoercionSignal"]; + hasOperationalAdminActionRequestSignal: + AddressAttemptRuntimeInput["hasOperationalAdminActionRequestSignal"]; + hasOrganizationFactLookupSignal: AddressAttemptRuntimeInput["hasOrganizationFactLookupSignal"]; + hasOrganizationFactFollowupSignal: AddressAttemptRuntimeInput["hasOrganizationFactFollowupSignal"]; + shouldEmitOrganizationSelectionReply: + AddressAttemptRuntimeInput["shouldEmitOrganizationSelectionReply"]; + hasAssistantCapabilityQuestionSignal: + AddressAttemptRuntimeInput["hasAssistantCapabilityQuestionSignal"]; + resolveDataScopeProbe: AddressAttemptRuntimeInput["resolveDataScopeProbe"]; + applyScriptGuard: AddressAttemptRuntimeInput["applyScriptGuard"]; + applyGroundingGuard: AddressAttemptRuntimeInput["applyGroundingGuard"]; + buildAssistantSafetyRefusalReply: AddressAttemptRuntimeInput["buildAssistantSafetyRefusalReply"]; + buildAssistantDataScopeContractReply: + AddressAttemptRuntimeInput["buildAssistantDataScopeContractReply"]; + buildAssistantOrganizationFactBoundaryReply: + AddressAttemptRuntimeInput["buildAssistantOrganizationFactBoundaryReply"]; + buildAssistantDataScopeSelectionReply: + AddressAttemptRuntimeInput["buildAssistantDataScopeSelectionReply"]; + buildAssistantOperationalBoundaryReply: + AddressAttemptRuntimeInput["buildAssistantOperationalBoundaryReply"]; + buildAssistantCapabilityContractReply: + AddressAttemptRuntimeInput["buildAssistantCapabilityContractReply"]; + loadAssistantCanonExcerpt: AddressAttemptRuntimeInput["loadAssistantCanonExcerpt"]; + sanitizeOutgoingAssistantText: AddressAttemptRuntimeInput["sanitizeOutgoingAssistantText"]; + buildAddressDebugPayload: AddressAttemptRuntimeInput["buildAddressDebugPayload"]; + buildAddressFollowupOffer: AddressAttemptRuntimeInput["buildAddressFollowupOffer"]; + buildFollowupStateBinding: DeepTurnAttemptRuntimeInput["buildFollowupStateBinding"]; + resolveBusinessScopeAlignment: DeepTurnAttemptRuntimeInput["resolveBusinessScopeAlignment"]; + inferP0DomainFromMessage: DeepTurnAttemptRuntimeInput["inferP0DomainFromMessage"]; + resolveBusinessScopeFromLiveContext: DeepTurnAttemptRuntimeInput["resolveBusinessScopeFromLiveContext"]; + extractRequirements: DeepTurnAttemptRuntimeInput["extractRequirements"]; + toExecutionPlan: DeepTurnAttemptRuntimeInput["toExecutionPlan"]; + enforceRbpLiveRoutePlan: DeepTurnAttemptRuntimeInput["enforceRbpLiveRoutePlan"]; + enforceFaLiveRoutePlan: DeepTurnAttemptRuntimeInput["enforceFaLiveRoutePlan"]; + mapNoRouteReason: DeepTurnAttemptRuntimeInput["mapNoRouteReason"]; + buildSkippedResult: DeepTurnAttemptRuntimeInput["buildSkippedResult"]; + evaluateCoverage: DeepTurnAttemptRuntimeInput["evaluateCoverage"]; + checkGrounding: DeepTurnAttemptRuntimeInput["checkGrounding"]; + collectRbpLiveRouteAudit: DeepTurnAttemptRuntimeInput["collectRbpLiveRouteAudit"]; + collectFaLiveRouteAudit: DeepTurnAttemptRuntimeInput["collectFaLiveRouteAudit"]; + hasExplicitPeriodAnchorFromNormalized: DeepTurnAttemptRuntimeInput["hasExplicitPeriodAnchor"]; + extractDroppedIntentSegments: DeepTurnAttemptRuntimeInput["extractDroppedIntentSegments"]; + toDebugRoutes: DeepTurnAttemptRuntimeInput["buildDebugRoutes"]; + extractExecutionState: DeepTurnAttemptRuntimeInput["extractExecutionState"]; } export function buildAssistantUserTurnBootstrapRuntimeInput( @@ -107,15 +128,15 @@ export function buildAssistantUserTurnBootstrapRuntimeInput( } export function buildAssistantAddressAttemptRuntimeInput( - runtimeInput: RunAssistantTurnAttemptRuntimeAddressInput, - deps: AssistantTurnRuntimeBuilderDeps + runtimeInput: RunAssistantTurnAttemptRuntimeAddressInput["payload"]>, + deps: AssistantTurnRuntimeBuilderDeps ): RunAssistantAddressAttemptRuntimeInput { return { featureAssistantAddressQueryV1: deps.featureAssistantAddressQueryV1, sessionId: runtimeInput.sessionId, userMessage: runtimeInput.userMessage, sessionItems: runtimeInput.sessionItems, - payload: runtimeInput.payload as any, + payload: runtimeInput.payload, sessionScope: { knownOrganizations: runtimeInput.sessionOrganizationScope.knownOrganizations, selectedOrganization: runtimeInput.sessionOrganizationScope.selectedOrganization, @@ -123,65 +144,68 @@ export function buildAssistantAddressAttemptRuntimeInput }, featureAddressLlmPredecomposeV1: deps.featureAddressLlmPredecomposeV1, runAddressLlmPreDecompose: async () => deps.runAddressLlmPreDecompose(runtimeInput.payload, runtimeInput.userMessage), - buildAddressLlmPredecomposeContractV1: deps.buildAddressLlmPredecomposeContractV1 as any, - sanitizeAddressMessageForFallback: deps.sanitizeAddressMessageForFallback as any, - toNonEmptyString: deps.toNonEmptyString as any, - resolveAddressFollowupCarryoverContext: deps.resolveAddressFollowupCarryoverContext as any, - resolveAssistantOrchestrationDecision: deps.resolveAssistantOrchestrationDecision as any, - buildAddressDialogContinuationContractV2: deps.buildAddressDialogContinuationContractV2 as any, + buildAddressLlmPredecomposeContractV1: deps.buildAddressLlmPredecomposeContractV1, + sanitizeAddressMessageForFallback: deps.sanitizeAddressMessageForFallback, + toNonEmptyString: deps.toNonEmptyString, + resolveAddressFollowupCarryoverContext: deps.resolveAddressFollowupCarryoverContext, + resolveAssistantOrchestrationDecision: deps.resolveAssistantOrchestrationDecision, + buildAddressDialogContinuationContractV2: deps.buildAddressDialogContinuationContractV2, runtimeAnalysisContextAsOfDate: runtimeInput.runtimeAnalysisContext.as_of_date, compactWhitespace: deps.compactWhitespace, - mergeFollowupContextWithOrganizationScope: deps.mergeFollowupContextWithOrganizationScope as any, - runAddressQueryTryHandle: deps.tryAddressQueryHandle as any, - isRetryableAddressLimitedResult: deps.isRetryableAddressLimitedResult as any, - mergeKnownOrganizations: deps.mergeKnownOrganizations as any, - hasAssistantDataScopeMetaQuestionSignal: deps.hasAssistantDataScopeMetaQuestionSignal as any, - shouldHandleAsAssistantCapabilityMetaQuery: deps.shouldHandleAsAssistantCapabilityMetaQuery as any, - hasDestructiveDataActionSignal: deps.hasDestructiveDataActionSignal as any, - hasDangerOrCoercionSignal: deps.hasDangerOrCoercionSignal as any, - hasOperationalAdminActionRequestSignal: deps.hasOperationalAdminActionRequestSignal as any, - hasOrganizationFactLookupSignal: deps.hasOrganizationFactLookupSignal as any, - hasOrganizationFactFollowupSignal: deps.hasOrganizationFactFollowupSignal as any, - shouldEmitOrganizationSelectionReply: deps.shouldEmitOrganizationSelectionReply as any, - hasAssistantCapabilityQuestionSignal: deps.hasAssistantCapabilityQuestionSignal as any, - resolveDataScopeProbe: deps.resolveDataScopeProbe as any, - applyScriptGuard: deps.applyScriptGuard as any, - applyGroundingGuard: deps.applyGroundingGuard as any, - buildAssistantSafetyRefusalReply: deps.buildAssistantSafetyRefusalReply as any, - buildAssistantDataScopeContractReply: deps.buildAssistantDataScopeContractReply as any, - buildAssistantOrganizationFactBoundaryReply: deps.buildAssistantOrganizationFactBoundaryReply as any, - buildAssistantDataScopeSelectionReply: deps.buildAssistantDataScopeSelectionReply as any, - buildAssistantOperationalBoundaryReply: deps.buildAssistantOperationalBoundaryReply as any, - buildAssistantCapabilityContractReply: deps.buildAssistantCapabilityContractReply as any, - chatClient: deps.chatClient as any, - loadAssistantCanonExcerpt: deps.loadAssistantCanonExcerpt as any, + mergeFollowupContextWithOrganizationScope: deps.mergeFollowupContextWithOrganizationScope, + runAddressQueryTryHandle: deps.tryAddressQueryHandle, + isRetryableAddressLimitedResult: deps.isRetryableAddressLimitedResult, + mergeKnownOrganizations: deps.mergeKnownOrganizations, + hasAssistantDataScopeMetaQuestionSignal: deps.hasAssistantDataScopeMetaQuestionSignal, + shouldHandleAsAssistantCapabilityMetaQuery: deps.shouldHandleAsAssistantCapabilityMetaQuery, + hasDestructiveDataActionSignal: deps.hasDestructiveDataActionSignal, + hasDangerOrCoercionSignal: deps.hasDangerOrCoercionSignal, + hasOperationalAdminActionRequestSignal: deps.hasOperationalAdminActionRequestSignal, + hasOrganizationFactLookupSignal: deps.hasOrganizationFactLookupSignal, + hasOrganizationFactFollowupSignal: deps.hasOrganizationFactFollowupSignal, + shouldEmitOrganizationSelectionReply: deps.shouldEmitOrganizationSelectionReply, + hasAssistantCapabilityQuestionSignal: deps.hasAssistantCapabilityQuestionSignal, + resolveDataScopeProbe: deps.resolveDataScopeProbe, + applyScriptGuard: deps.applyScriptGuard, + applyGroundingGuard: deps.applyGroundingGuard, + buildAssistantSafetyRefusalReply: deps.buildAssistantSafetyRefusalReply, + buildAssistantDataScopeContractReply: deps.buildAssistantDataScopeContractReply, + buildAssistantOrganizationFactBoundaryReply: deps.buildAssistantOrganizationFactBoundaryReply, + buildAssistantDataScopeSelectionReply: deps.buildAssistantDataScopeSelectionReply, + buildAssistantOperationalBoundaryReply: deps.buildAssistantOperationalBoundaryReply, + buildAssistantCapabilityContractReply: deps.buildAssistantCapabilityContractReply, + chatClient: deps.chatClient, + loadAssistantCanonExcerpt: deps.loadAssistantCanonExcerpt, sanitizeOutgoingAssistantText: deps.sanitizeOutgoingAssistantText, defaultModel: deps.defaultModel, defaultBaseUrl: deps.defaultBaseUrl, defaultApiKey: deps.defaultApiKey, - buildAddressDebugPayload: deps.buildAddressDebugPayload as any, - buildAddressFollowupOffer: deps.buildAddressFollowupOffer as any, - appendItem: deps.appendItem as any, - getSession: deps.getSession as any, - persistSession: deps.persistSession as any, + buildAddressDebugPayload: deps.buildAddressDebugPayload, + buildAddressFollowupOffer: deps.buildAddressFollowupOffer, + appendItem: deps.appendItem, + getSession: deps.getSession, + persistSession: deps.persistSession, cloneConversation: (items) => items.map((item) => ({ ...item })), - logEvent: deps.logEvent as any, + logEvent: deps.logEvent, messageIdFactory: deps.messageIdFactory, nowIso: deps.nowIso }; } export function buildAssistantDeepTurnAttemptRuntimeInput( - runtimeInput: RunAssistantTurnAttemptRuntimeDeepInput, - deps: AssistantTurnRuntimeBuilderDeps + runtimeInput: RunAssistantTurnAttemptRuntimeDeepInput["payload"]> & { + runtimeAnalysisContext: DeepTurnAttemptRuntimeInput["runtimeAnalysisContext"]; + sessionInvestigationState: DeepTurnAttemptRuntimeInput["sessionInvestigationState"]; + }, + deps: AssistantTurnRuntimeBuilderDeps ): RunAssistantDeepTurnAttemptRuntimeInput { return { sessionId: runtimeInput.sessionId, questionId: runtimeInput.questionId, userMessage: runtimeInput.userMessage, - payload: runtimeInput.payload as any, - runtimeAnalysisContext: runtimeInput.runtimeAnalysisContext as any, - sessionInvestigationState: runtimeInput.sessionInvestigationState as any, + payload: runtimeInput.payload, + runtimeAnalysisContext: runtimeInput.runtimeAnalysisContext, + sessionInvestigationState: runtimeInput.sessionInvestigationState, addressRuntimeMetaForDeep: runtimeInput.addressRuntimeMetaForDeep, featureInvestigationStateV1: deps.featureInvestigationStateV1, featureStateFollowupBindingV1: deps.featureStateFollowupBindingV1, @@ -189,33 +213,33 @@ export function buildAssistantDeepTurnAttemptRuntimeInput items.map((item) => ({ ...item })), - logEvent: deps.logEvent as any + logEvent: deps.logEvent }; }