ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Рефакторинг этапов 2.612.64 - вынос mapper для assistantAddressLaneResponseAttemptRuntimeAdapter и для assistantLivingChatAttemptRuntimeAdapter / сборка входов для living chat attempt в отдельный builder (LLM + handler)

This commit is contained in:
2026-04-11 09:52:59 +03:00
parent 6c9b94ef34
commit 79b636bfe6
11 changed files with 489 additions and 78 deletions
@@ -2,9 +2,10 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.runAssistantAddressLaneResponseAttemptRuntime = runAssistantAddressLaneResponseAttemptRuntime;
const assistantAddressLaneResponseRuntimeAdapter_1 = require("./assistantAddressLaneResponseRuntimeAdapter");
const assistantAddressLaneResponseRuntimeInputBuilder_1 = require("./assistantAddressLaneResponseRuntimeInputBuilder");
function runAssistantAddressLaneResponseAttemptRuntime(input) {
const runAddressLaneResponseRuntimeSafe = input.runAddressLaneResponseRuntime ?? assistantAddressLaneResponseRuntimeAdapter_1.runAssistantAddressLaneResponseRuntime;
const runtime = runAddressLaneResponseRuntimeSafe({
const runtime = runAddressLaneResponseRuntimeSafe((0, assistantAddressLaneResponseRuntimeInputBuilder_1.buildAssistantAddressLaneResponseRuntimeInput)({
sessionId: input.sessionId,
userMessage: input.userMessage,
effectiveAddressUserMessage: input.effectiveAddressUserMessage,
@@ -24,6 +25,6 @@ function runAssistantAddressLaneResponseAttemptRuntime(input) {
cloneConversation: input.cloneConversation,
logEvent: input.logEvent,
messageIdFactory: input.messageIdFactory
});
}));
return runtime.response;
}
@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildAssistantAddressLaneResponseRuntimeInput = buildAssistantAddressLaneResponseRuntimeInput;
function buildAssistantAddressLaneResponseRuntimeInput(input) {
return {
sessionId: input.sessionId,
userMessage: input.userMessage,
effectiveAddressUserMessage: input.effectiveAddressUserMessage,
addressLane: input.addressLane,
carryoverMeta: input.carryoverMeta,
llmPreDecomposeMeta: input.llmPreDecomposeMeta,
knownOrganizations: input.knownOrganizations,
activeOrganization: input.activeOrganization,
sanitizeOutgoingAssistantText: input.sanitizeOutgoingAssistantText,
buildAddressDebugPayload: input.buildAddressDebugPayload,
buildAddressFollowupOffer: input.buildAddressFollowupOffer,
mergeKnownOrganizations: input.mergeKnownOrganizations,
toNonEmptyString: input.toNonEmptyString,
appendItem: input.appendItem,
getSession: input.getSession,
persistSession: input.persistSession,
cloneConversation: input.cloneConversation,
logEvent: input.logEvent,
messageIdFactory: input.messageIdFactory
};
}
@@ -3,8 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.runAssistantLivingChatAttemptRuntime = runAssistantLivingChatAttemptRuntime;
const assistantLivingChatHandlerRuntimeAdapter_1 = require("./assistantLivingChatHandlerRuntimeAdapter");
const assistantLivingChatLlmRuntimeAdapter_1 = require("./assistantLivingChatLlmRuntimeAdapter");
const assistantLivingChatAttemptRuntimeInputBuilder_1 = require("./assistantLivingChatAttemptRuntimeInputBuilder");
function buildExecuteLlmChat(input, runLivingChatLlmSafe) {
return async () => runLivingChatLlmSafe({
return async () => runLivingChatLlmSafe((0, assistantLivingChatAttemptRuntimeInputBuilder_1.buildAssistantLivingChatLlmRuntimeInput)({
userMessage: input.userMessage,
sessionItems: input.sessionItems,
payload: input.payload,
@@ -14,13 +15,13 @@ function buildExecuteLlmChat(input, runLivingChatLlmSafe) {
defaultModel: input.defaultModel,
defaultBaseUrl: input.defaultBaseUrl,
defaultApiKey: input.defaultApiKey
});
}));
}
async function runAssistantLivingChatAttemptRuntime(input) {
const runLivingChatHandlerSafe = input.runLivingChatHandler ?? assistantLivingChatHandlerRuntimeAdapter_1.tryHandleAssistantLivingChatRuntime;
const runLivingChatLlmSafe = input.runLivingChatLlm ?? assistantLivingChatLlmRuntimeAdapter_1.runAssistantLivingChatLlmRuntime;
const executeLlmChat = buildExecuteLlmChat(input, runLivingChatLlmSafe);
return runLivingChatHandlerSafe({
return runLivingChatHandlerSafe((0, assistantLivingChatAttemptRuntimeInputBuilder_1.buildAssistantLivingChatHandlerRuntimeInput)({
sessionId: input.sessionId,
userMessage: input.userMessage,
sessionItems: input.sessionItems,
@@ -58,5 +59,5 @@ async function runAssistantLivingChatAttemptRuntime(input) {
nowIso: input.nowIso,
runLivingChatRuntime: input.runLivingChatRuntime,
finalizeLivingChatTurn: input.finalizeLivingChatTurn
});
}));
}
@@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildAssistantLivingChatLlmRuntimeInput = buildAssistantLivingChatLlmRuntimeInput;
exports.buildAssistantLivingChatHandlerRuntimeInput = buildAssistantLivingChatHandlerRuntimeInput;
function buildAssistantLivingChatLlmRuntimeInput(input) {
return {
userMessage: input.userMessage,
sessionItems: input.sessionItems,
payload: input.payload,
chatClient: input.chatClient,
loadAssistantCanonExcerpt: input.loadAssistantCanonExcerpt,
sanitizeOutgoingAssistantText: input.sanitizeOutgoingAssistantText,
defaultModel: input.defaultModel,
defaultBaseUrl: input.defaultBaseUrl,
defaultApiKey: input.defaultApiKey
};
}
function buildAssistantLivingChatHandlerRuntimeInput(input) {
return {
sessionId: input.sessionId,
userMessage: input.userMessage,
sessionItems: input.sessionItems,
modeDecision: input.modeDecision,
sessionScope: input.sessionScope,
addressRuntimeMeta: input.addressRuntimeMeta,
traceIdFactory: input.traceIdFactory,
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,
executeLlmChat: input.executeLlmChat,
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,
runLivingChatRuntime: input.runLivingChatRuntime,
finalizeLivingChatTurn: input.finalizeLivingChatTurn
};
}
@@ -4,6 +4,7 @@ import {
type RunAssistantAddressLaneResponseRuntimeInput,
type RunAssistantAddressLaneResponseRuntimeOutput
} from "./assistantAddressLaneResponseRuntimeAdapter";
import { buildAssistantAddressLaneResponseRuntimeInput } from "./assistantAddressLaneResponseRuntimeInputBuilder";
export interface RunAssistantAddressLaneResponseAttemptRuntimeInput<
ResponseType = AssistantMessageResponsePayload
@@ -20,26 +21,28 @@ export function runAssistantAddressLaneResponseAttemptRuntime<
): ResponseType {
const runAddressLaneResponseRuntimeSafe =
input.runAddressLaneResponseRuntime ?? runAssistantAddressLaneResponseRuntime;
const runtime = runAddressLaneResponseRuntimeSafe({
sessionId: input.sessionId,
userMessage: input.userMessage,
effectiveAddressUserMessage: input.effectiveAddressUserMessage,
addressLane: input.addressLane,
carryoverMeta: input.carryoverMeta,
llmPreDecomposeMeta: input.llmPreDecomposeMeta,
knownOrganizations: input.knownOrganizations,
activeOrganization: input.activeOrganization,
sanitizeOutgoingAssistantText: input.sanitizeOutgoingAssistantText,
buildAddressDebugPayload: input.buildAddressDebugPayload,
buildAddressFollowupOffer: input.buildAddressFollowupOffer,
mergeKnownOrganizations: input.mergeKnownOrganizations,
toNonEmptyString: input.toNonEmptyString,
appendItem: input.appendItem,
getSession: input.getSession,
persistSession: input.persistSession,
cloneConversation: input.cloneConversation,
logEvent: input.logEvent,
messageIdFactory: input.messageIdFactory
});
const runtime = runAddressLaneResponseRuntimeSafe(
buildAssistantAddressLaneResponseRuntimeInput({
sessionId: input.sessionId,
userMessage: input.userMessage,
effectiveAddressUserMessage: input.effectiveAddressUserMessage,
addressLane: input.addressLane,
carryoverMeta: input.carryoverMeta,
llmPreDecomposeMeta: input.llmPreDecomposeMeta,
knownOrganizations: input.knownOrganizations,
activeOrganization: input.activeOrganization,
sanitizeOutgoingAssistantText: input.sanitizeOutgoingAssistantText,
buildAddressDebugPayload: input.buildAddressDebugPayload,
buildAddressFollowupOffer: input.buildAddressFollowupOffer,
mergeKnownOrganizations: input.mergeKnownOrganizations,
toNonEmptyString: input.toNonEmptyString,
appendItem: input.appendItem,
getSession: input.getSession,
persistSession: input.persistSession,
cloneConversation: input.cloneConversation,
logEvent: input.logEvent,
messageIdFactory: input.messageIdFactory
})
);
return runtime.response;
}
@@ -0,0 +1,54 @@
import type { RunAssistantAddressLaneResponseRuntimeInput } from "./assistantAddressLaneResponseRuntimeAdapter";
export interface BuildAssistantAddressLaneResponseRuntimeInputInput<ResponseType = unknown> {
sessionId: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["sessionId"];
userMessage: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["userMessage"];
effectiveAddressUserMessage:
RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["effectiveAddressUserMessage"];
addressLane: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["addressLane"];
carryoverMeta?: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["carryoverMeta"];
llmPreDecomposeMeta?: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["llmPreDecomposeMeta"];
knownOrganizations: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["knownOrganizations"];
activeOrganization: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["activeOrganization"];
sanitizeOutgoingAssistantText:
RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["sanitizeOutgoingAssistantText"];
buildAddressDebugPayload:
RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["buildAddressDebugPayload"];
buildAddressFollowupOffer:
RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["buildAddressFollowupOffer"];
mergeKnownOrganizations:
RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["mergeKnownOrganizations"];
toNonEmptyString: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["toNonEmptyString"];
appendItem: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["appendItem"];
getSession: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["getSession"];
persistSession: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["persistSession"];
cloneConversation: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["cloneConversation"];
logEvent: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["logEvent"];
messageIdFactory: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>["messageIdFactory"];
}
export function buildAssistantAddressLaneResponseRuntimeInput<ResponseType = unknown>(
input: BuildAssistantAddressLaneResponseRuntimeInputInput<ResponseType>
): RunAssistantAddressLaneResponseRuntimeInput<ResponseType> {
return {
sessionId: input.sessionId,
userMessage: input.userMessage,
effectiveAddressUserMessage: input.effectiveAddressUserMessage,
addressLane: input.addressLane,
carryoverMeta: input.carryoverMeta,
llmPreDecomposeMeta: input.llmPreDecomposeMeta,
knownOrganizations: input.knownOrganizations,
activeOrganization: input.activeOrganization,
sanitizeOutgoingAssistantText: input.sanitizeOutgoingAssistantText,
buildAddressDebugPayload: input.buildAddressDebugPayload,
buildAddressFollowupOffer: input.buildAddressFollowupOffer,
mergeKnownOrganizations: input.mergeKnownOrganizations,
toNonEmptyString: input.toNonEmptyString,
appendItem: input.appendItem,
getSession: input.getSession,
persistSession: input.persistSession,
cloneConversation: input.cloneConversation,
logEvent: input.logEvent,
messageIdFactory: input.messageIdFactory
};
}
@@ -6,6 +6,10 @@ import {
runAssistantLivingChatLlmRuntime,
type RunAssistantLivingChatLlmRuntimeInput
} from "./assistantLivingChatLlmRuntimeAdapter";
import {
buildAssistantLivingChatHandlerRuntimeInput,
buildAssistantLivingChatLlmRuntimeInput
} from "./assistantLivingChatAttemptRuntimeInputBuilder";
type AssistantLivingChatHandlerInput<ResponseType> = TryHandleAssistantLivingChatRuntimeInput<ResponseType>;
type AssistantLivingChatLlmInput = RunAssistantLivingChatLlmRuntimeInput;
@@ -32,17 +36,19 @@ function buildExecuteLlmChat<ResponseType>(
runLivingChatLlmSafe: (input: AssistantLivingChatLlmInput) => Promise<string>
): AssistantLivingChatHandlerInput<ResponseType>["executeLlmChat"] {
return async () =>
runLivingChatLlmSafe({
userMessage: input.userMessage,
sessionItems: input.sessionItems,
payload: input.payload,
chatClient: input.chatClient,
loadAssistantCanonExcerpt: input.loadAssistantCanonExcerpt,
sanitizeOutgoingAssistantText: input.sanitizeOutgoingAssistantText,
defaultModel: input.defaultModel,
defaultBaseUrl: input.defaultBaseUrl,
defaultApiKey: input.defaultApiKey
});
runLivingChatLlmSafe(
buildAssistantLivingChatLlmRuntimeInput({
userMessage: input.userMessage,
sessionItems: input.sessionItems,
payload: input.payload,
chatClient: input.chatClient,
loadAssistantCanonExcerpt: input.loadAssistantCanonExcerpt,
sanitizeOutgoingAssistantText: input.sanitizeOutgoingAssistantText,
defaultModel: input.defaultModel,
defaultBaseUrl: input.defaultBaseUrl,
defaultApiKey: input.defaultApiKey
})
);
}
export async function runAssistantLivingChatAttemptRuntime<ResponseType = unknown>(
@@ -51,43 +57,45 @@ export async function runAssistantLivingChatAttemptRuntime<ResponseType = unknow
const runLivingChatHandlerSafe = input.runLivingChatHandler ?? tryHandleAssistantLivingChatRuntime;
const runLivingChatLlmSafe = input.runLivingChatLlm ?? runAssistantLivingChatLlmRuntime;
const executeLlmChat = buildExecuteLlmChat(input, runLivingChatLlmSafe);
return runLivingChatHandlerSafe({
sessionId: input.sessionId,
userMessage: input.userMessage,
sessionItems: input.sessionItems,
modeDecision: input.modeDecision,
sessionScope: input.sessionScope,
addressRuntimeMeta: input.addressRuntimeMeta,
traceIdFactory: input.traceIdFactory,
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,
executeLlmChat,
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,
runLivingChatRuntime: input.runLivingChatRuntime,
finalizeLivingChatTurn: input.finalizeLivingChatTurn
});
return runLivingChatHandlerSafe(
buildAssistantLivingChatHandlerRuntimeInput({
sessionId: input.sessionId,
userMessage: input.userMessage,
sessionItems: input.sessionItems,
modeDecision: input.modeDecision,
sessionScope: input.sessionScope,
addressRuntimeMeta: input.addressRuntimeMeta,
traceIdFactory: input.traceIdFactory,
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,
executeLlmChat,
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,
runLivingChatRuntime: input.runLivingChatRuntime,
finalizeLivingChatTurn: input.finalizeLivingChatTurn
})
);
}
@@ -0,0 +1,81 @@
import type {
TryHandleAssistantLivingChatRuntimeInput
} from "./assistantLivingChatHandlerRuntimeAdapter";
import type { RunAssistantLivingChatLlmRuntimeInput } from "./assistantLivingChatLlmRuntimeAdapter";
export interface BuildAssistantLivingChatLlmRuntimeInputInput {
userMessage: RunAssistantLivingChatLlmRuntimeInput["userMessage"];
sessionItems: RunAssistantLivingChatLlmRuntimeInput["sessionItems"];
payload: RunAssistantLivingChatLlmRuntimeInput["payload"];
chatClient: RunAssistantLivingChatLlmRuntimeInput["chatClient"];
loadAssistantCanonExcerpt: RunAssistantLivingChatLlmRuntimeInput["loadAssistantCanonExcerpt"];
sanitizeOutgoingAssistantText: RunAssistantLivingChatLlmRuntimeInput["sanitizeOutgoingAssistantText"];
defaultModel: RunAssistantLivingChatLlmRuntimeInput["defaultModel"];
defaultBaseUrl: RunAssistantLivingChatLlmRuntimeInput["defaultBaseUrl"];
defaultApiKey?: RunAssistantLivingChatLlmRuntimeInput["defaultApiKey"];
}
export function buildAssistantLivingChatLlmRuntimeInput(
input: BuildAssistantLivingChatLlmRuntimeInputInput
): RunAssistantLivingChatLlmRuntimeInput {
return {
userMessage: input.userMessage,
sessionItems: input.sessionItems,
payload: input.payload,
chatClient: input.chatClient,
loadAssistantCanonExcerpt: input.loadAssistantCanonExcerpt,
sanitizeOutgoingAssistantText: input.sanitizeOutgoingAssistantText,
defaultModel: input.defaultModel,
defaultBaseUrl: input.defaultBaseUrl,
defaultApiKey: input.defaultApiKey
};
}
export interface BuildAssistantLivingChatHandlerRuntimeInputInput<ResponseType = unknown>
extends Omit<TryHandleAssistantLivingChatRuntimeInput<ResponseType>, "executeLlmChat"> {
executeLlmChat: TryHandleAssistantLivingChatRuntimeInput<ResponseType>["executeLlmChat"];
}
export function buildAssistantLivingChatHandlerRuntimeInput<ResponseType = unknown>(
input: BuildAssistantLivingChatHandlerRuntimeInputInput<ResponseType>
): TryHandleAssistantLivingChatRuntimeInput<ResponseType> {
return {
sessionId: input.sessionId,
userMessage: input.userMessage,
sessionItems: input.sessionItems,
modeDecision: input.modeDecision,
sessionScope: input.sessionScope,
addressRuntimeMeta: input.addressRuntimeMeta,
traceIdFactory: input.traceIdFactory,
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,
executeLlmChat: input.executeLlmChat,
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,
runLivingChatRuntime: input.runLivingChatRuntime,
finalizeLivingChatTurn: input.finalizeLivingChatTurn
};
}
@@ -0,0 +1,48 @@
import { describe, expect, it, vi } from "vitest";
import { buildAssistantAddressLaneResponseRuntimeInput } from "../src/services/assistantAddressLaneResponseRuntimeInputBuilder";
function buildInput(overrides: Record<string, unknown> = {}) {
return {
sessionId: "asst-1",
userMessage: "where is settlement tail",
effectiveAddressUserMessage: "where is settlement tail for Org A",
addressLane: {
reply_text: "address reply",
reply_type: "factual_with_explanation",
debug: {}
},
carryoverMeta: { previousReplyType: "partial_coverage" },
llmPreDecomposeMeta: { mode: "supported", confidence: "high" },
knownOrganizations: ["Org A"],
activeOrganization: "Org A",
sanitizeOutgoingAssistantText: vi.fn((value: unknown, fallback = "") => {
const text = String(value ?? "").trim();
return text || fallback;
}),
buildAddressDebugPayload: vi.fn(() => ({})),
buildAddressFollowupOffer: vi.fn(() => null),
mergeKnownOrganizations: vi.fn((values: string[]) => values),
toNonEmptyString: vi.fn((value: unknown) =>
typeof value === "string" && value.trim().length > 0 ? value.trim() : null
),
appendItem: vi.fn(),
getSession: vi.fn(),
persistSession: vi.fn(),
cloneConversation: vi.fn((items: unknown[]) => items),
logEvent: vi.fn(),
messageIdFactory: vi.fn(() => "msg-1"),
...overrides
} as any;
}
describe("assistant address lane response runtime input builder", () => {
it("maps lane-response fields into runtime input", () => {
const runtimeInput = buildAssistantAddressLaneResponseRuntimeInput(buildInput());
expect(runtimeInput.sessionId).toBe("asst-1");
expect(runtimeInput.effectiveAddressUserMessage).toBe("where is settlement tail for Org A");
expect(runtimeInput.knownOrganizations).toEqual(["Org A"]);
expect(runtimeInput.carryoverMeta).toEqual({ previousReplyType: "partial_coverage" });
expect(runtimeInput.llmPreDecomposeMeta).toEqual({ mode: "supported", confidence: "high" });
});
});
@@ -0,0 +1,83 @@
import { describe, expect, it, vi } from "vitest";
import {
buildAssistantLivingChatHandlerRuntimeInput,
buildAssistantLivingChatLlmRuntimeInput
} from "../src/services/assistantLivingChatAttemptRuntimeInputBuilder";
describe("assistant living chat attempt runtime input builder", () => {
it("builds living-chat llm runtime input", () => {
const runtimeInput = buildAssistantLivingChatLlmRuntimeInput({
userMessage: "hello",
sessionItems: [{ role: "user", text: "ctx" }],
payload: { llmProvider: "openai" } as any,
chatClient: {} as any,
loadAssistantCanonExcerpt: vi.fn(() => "canon"),
sanitizeOutgoingAssistantText: vi.fn((value: unknown) => String(value ?? "")),
defaultModel: "gpt-5",
defaultBaseUrl: "http://localhost",
defaultApiKey: "key"
});
expect(runtimeInput.userMessage).toBe("hello");
expect(runtimeInput.sessionItems).toEqual([{ role: "user", text: "ctx" }]);
expect(runtimeInput.defaultModel).toBe("gpt-5");
expect(runtimeInput.defaultBaseUrl).toBe("http://localhost");
expect(runtimeInput.defaultApiKey).toBe("key");
});
it("builds living-chat handler runtime input with execute callback", async () => {
const executeLlmChat = vi.fn(async () => "llm-answer");
const runtimeInput = buildAssistantLivingChatHandlerRuntimeInput({
sessionId: "asst-1",
userMessage: "hello",
sessionItems: [],
modeDecision: { mode: "chat", reason: "living_chat_signal_detected" },
sessionScope: { knownOrganizations: [], selectedOrganization: null, activeOrganization: null },
addressRuntimeMeta: null,
traceIdFactory: vi.fn(() => "chat-1"),
toNonEmptyString: vi.fn((value: unknown) =>
typeof value === "string" && value.trim().length > 0 ? value.trim() : null
),
mergeKnownOrganizations: vi.fn((values: string[]) => values),
hasAssistantDataScopeMetaQuestionSignal: vi.fn(() => false),
shouldHandleAsAssistantCapabilityMetaQuery: vi.fn(() => false),
hasDestructiveDataActionSignal: vi.fn(() => false),
hasDangerOrCoercionSignal: vi.fn(() => false),
hasOperationalAdminActionRequestSignal: vi.fn(() => false),
hasOrganizationFactLookupSignal: vi.fn(() => false),
hasOrganizationFactFollowupSignal: vi.fn(() => false),
shouldEmitOrganizationSelectionReply: vi.fn(() => false),
hasAssistantCapabilityQuestionSignal: vi.fn(() => false),
resolveDataScopeProbe: vi.fn(async () => null),
executeLlmChat,
applyScriptGuard: vi.fn((text: string) => ({ text, applied: false, reason: null })),
applyGroundingGuard: vi.fn((payload: { chatText: string }) => ({
text: payload.chatText,
applied: false,
reason: null
})),
buildAssistantSafetyRefusalReply: vi.fn(() => "safety"),
buildAssistantDataScopeContractReply: vi.fn(() => "scope"),
buildAssistantOrganizationFactBoundaryReply: vi.fn(() => "boundary"),
buildAssistantDataScopeSelectionReply: vi.fn(() => "selection"),
buildAssistantOperationalBoundaryReply: vi.fn(() => "operational"),
buildAssistantCapabilityContractReply: vi.fn(() => "capability"),
appendItem: vi.fn(),
getSession: vi.fn(),
persistSession: vi.fn(),
cloneConversation: vi.fn((items: unknown[]) => items),
logEvent: vi.fn(),
messageIdFactory: vi.fn(() => "msg-1"),
nowIso: vi.fn(() => "2026-04-11T00:00:00.000Z"),
runLivingChatRuntime: vi.fn(async () => null),
finalizeLivingChatTurn: vi.fn()
});
await runtimeInput.executeLlmChat();
expect(executeLlmChat).toHaveBeenCalledTimes(1);
expect(runtimeInput.modeDecision).toEqual({
mode: "chat",
reason: "living_chat_signal_detected"
});
});
});