NODEDC_1C/llm_normalizer/backend/src/services/assistantAddressAttemptRunt...

266 lines
14 KiB
TypeScript

import {
runAssistantAddressRuntime,
type RunAssistantAddressRuntimeInput,
type RunAssistantAddressRuntimeOutput
} from "./assistantAddressRuntimeAdapter";
import {
runAssistantAddressLaneAttemptRuntime,
type RunAssistantAddressLaneAttemptRuntimeInput
} from "./assistantAddressLaneAttemptRuntimeAdapter";
import {
runAssistantAddressLaneResponseAttemptRuntime,
type RunAssistantAddressLaneResponseAttemptRuntimeInput
} from "./assistantAddressLaneResponseAttemptRuntimeAdapter";
import { buildAssistantAddressLaneResponseAttemptRuntimeInput } from "./assistantAddressLaneResponseAttemptInputBuilder";
import {
runAssistantLivingChatAttemptRuntime,
type RunAssistantLivingChatAttemptRuntimeInput
} from "./assistantLivingChatAttemptRuntimeAdapter";
import { buildAssistantLivingChatAttemptRuntimeInput } from "./assistantLivingChatAttemptInputBuilder";
import { buildAssistantAddressLaneAttemptRuntimeInput } from "./assistantAddressLaneAttemptInputBuilder";
import { buildAssistantAddressRuntimeInput } from "./assistantAddressRuntimeInputBuilder";
interface AddressAttemptPayload {
llmProvider?: unknown;
useMock?: unknown;
context?: {
period_hint?: unknown;
} | null;
apiKey?: unknown;
model?: unknown;
baseUrl?: unknown;
temperature?: number;
maxOutputTokens?: number;
}
interface AddressSessionScope {
knownOrganizations: string[];
selectedOrganization: string | null;
activeOrganization: string | null;
}
export interface RunAssistantAddressAttemptRuntimeInput<ResponseType = unknown>
extends Omit<
RunAssistantAddressRuntimeInput<ResponseType>,
| "llmProvider"
| "useMock"
| "payloadContextPeriodHint"
| "runAddressLaneAttempt"
| "finalizeAddressLaneResponse"
| "tryHandleLivingChat"
> {
payload: AddressAttemptPayload;
sessionScope: AddressSessionScope;
sessionAddressNavigationState?: unknown;
mergeFollowupContextWithOrganizationScope: RunAssistantAddressLaneAttemptRuntimeInput["mergeFollowupContextWithOrganizationScope"];
runAddressQueryTryHandle: RunAssistantAddressLaneAttemptRuntimeInput["runAddressQueryTryHandle"];
mergeKnownOrganizations: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["mergeKnownOrganizations"];
hasAssistantDataScopeMetaQuestionSignal: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["hasAssistantDataScopeMetaQuestionSignal"];
shouldHandleAsAssistantCapabilityMetaQuery: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["shouldHandleAsAssistantCapabilityMetaQuery"];
hasDestructiveDataActionSignal: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["hasDestructiveDataActionSignal"];
hasDangerOrCoercionSignal: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["hasDangerOrCoercionSignal"];
hasOperationalAdminActionRequestSignal: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["hasOperationalAdminActionRequestSignal"];
hasOrganizationFactLookupSignal: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["hasOrganizationFactLookupSignal"];
hasOrganizationFactFollowupSignal: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["hasOrganizationFactFollowupSignal"];
hasLivingChatSignal: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["hasLivingChatSignal"];
shouldEmitOrganizationSelectionReply: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["shouldEmitOrganizationSelectionReply"];
hasAssistantCapabilityQuestionSignal: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["hasAssistantCapabilityQuestionSignal"];
resolveDataScopeProbe: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["resolveDataScopeProbe"];
applyScriptGuard: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["applyScriptGuard"];
applyGroundingGuard: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["applyGroundingGuard"];
buildAssistantSafetyRefusalReply: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["buildAssistantSafetyRefusalReply"];
buildAssistantDataScopeContractReply: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["buildAssistantDataScopeContractReply"];
buildAssistantProactiveOrganizationOfferReply:
RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["buildAssistantProactiveOrganizationOfferReply"];
buildAssistantOrganizationFactBoundaryReply: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["buildAssistantOrganizationFactBoundaryReply"];
buildAssistantDataScopeSelectionReply: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["buildAssistantDataScopeSelectionReply"];
buildAssistantOperationalBoundaryReply: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["buildAssistantOperationalBoundaryReply"];
buildAssistantCapabilityContractReply: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["buildAssistantCapabilityContractReply"];
chatClient: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["chatClient"];
loadAssistantCanonExcerpt: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["loadAssistantCanonExcerpt"];
sanitizeOutgoingAssistantText: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["sanitizeOutgoingAssistantText"];
defaultModel: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["defaultModel"];
defaultBaseUrl: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["defaultBaseUrl"];
defaultApiKey?: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["defaultApiKey"];
buildAddressDebugPayload: RunAssistantAddressLaneResponseAttemptRuntimeInput<ResponseType>["buildAddressDebugPayload"];
buildAddressFollowupOffer: RunAssistantAddressLaneResponseAttemptRuntimeInput<ResponseType>["buildAddressFollowupOffer"];
appendItem: RunAssistantAddressLaneResponseAttemptRuntimeInput<ResponseType>["appendItem"];
getSession: RunAssistantAddressLaneResponseAttemptRuntimeInput<ResponseType>["getSession"];
persistSession: RunAssistantAddressLaneResponseAttemptRuntimeInput<ResponseType>["persistSession"];
cloneConversation: RunAssistantAddressLaneResponseAttemptRuntimeInput<ResponseType>["cloneConversation"];
logEvent: RunAssistantAddressRuntimeInput<ResponseType>["logEvent"];
messageIdFactory: NonNullable<
RunAssistantAddressLaneResponseAttemptRuntimeInput<ResponseType>["messageIdFactory"]
>;
runAddressRuntime?: (
input: RunAssistantAddressRuntimeInput<ResponseType>
) => Promise<RunAssistantAddressRuntimeOutput<ResponseType>>;
runAddressLaneAttemptRuntime?: (
input: RunAssistantAddressLaneAttemptRuntimeInput
) => Promise<Awaited<ReturnType<RunAssistantAddressLaneAttemptRuntimeInput["runAddressQueryTryHandle"]>>>;
runAddressLaneResponseAttemptRuntime?: (
input: RunAssistantAddressLaneResponseAttemptRuntimeInput<ResponseType>
) => ResponseType;
runLivingChatAttemptRuntime?: (
input: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>
) => Promise<ResponseType | null>;
}
export async function runAssistantAddressAttemptRuntime<ResponseType = unknown>(
input: RunAssistantAddressAttemptRuntimeInput<ResponseType>
): Promise<RunAssistantAddressRuntimeOutput<ResponseType>> {
const runAddressRuntimeSafe = input.runAddressRuntime ?? runAssistantAddressRuntime;
const runAddressLaneAttemptRuntimeSafe = input.runAddressLaneAttemptRuntime ?? runAssistantAddressLaneAttemptRuntime;
const runAddressLaneResponseAttemptRuntimeSafe =
input.runAddressLaneResponseAttemptRuntime ?? runAssistantAddressLaneResponseAttemptRuntime;
const runLivingChatAttemptRuntimeSafe =
input.runLivingChatAttemptRuntime ?? runAssistantLivingChatAttemptRuntime;
const finalizeAddressLaneResponse: RunAssistantAddressRuntimeInput<ResponseType>["finalizeAddressLaneResponse"] = (
addressLane,
effectiveAddressUserMessage,
carryoverMeta = null,
llmPreDecomposeMeta = null
) =>
runAddressLaneResponseAttemptRuntimeSafe(
buildAssistantAddressLaneResponseAttemptRuntimeInput({
sessionId: input.sessionId,
userMessage: input.userMessage,
effectiveAddressUserMessage,
addressLane,
carryoverMeta,
llmPreDecomposeMeta,
knownOrganizations: input.sessionScope.knownOrganizations,
activeOrganization: input.sessionScope.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 tryHandleLivingChat: RunAssistantAddressRuntimeInput<ResponseType>["tryHandleLivingChat"] = async (
modeDecision,
addressRuntimeMeta = null
) => {
const normalizedModeDecision: RunAssistantLivingChatAttemptRuntimeInput<ResponseType>["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: 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,
hasLivingChatSignal: input.hasLivingChatSignal,
shouldEmitOrganizationSelectionReply: input.shouldEmitOrganizationSelectionReply,
hasAssistantCapabilityQuestionSignal: input.hasAssistantCapabilityQuestionSignal,
resolveDataScopeProbe: input.resolveDataScopeProbe,
applyScriptGuard: input.applyScriptGuard,
applyGroundingGuard: input.applyGroundingGuard,
buildAssistantSafetyRefusalReply: input.buildAssistantSafetyRefusalReply,
buildAssistantDataScopeContractReply: input.buildAssistantDataScopeContractReply,
buildAssistantProactiveOrganizationOfferReply: input.buildAssistantProactiveOrganizationOfferReply,
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: RunAssistantAddressRuntimeInput<ResponseType>["runAddressLaneAttempt"] = async (
messageUsed,
carryMeta,
analysisDateHint,
llmSemanticHints = null
) =>
runAddressLaneAttemptRuntimeSafe(
buildAssistantAddressLaneAttemptRuntimeInput({
messageUsed,
carryMeta,
analysisDateHint,
llmSemanticHints,
activeOrganization: input.sessionScope.activeOrganization,
knownOrganizations: input.sessionScope.knownOrganizations,
mergeFollowupContextWithOrganizationScope: input.mergeFollowupContextWithOrganizationScope,
runAddressQueryTryHandle: input.runAddressQueryTryHandle
})
);
return runAddressRuntimeSafe(
buildAssistantAddressRuntimeInput({
featureAssistantAddressQueryV1: input.featureAssistantAddressQueryV1,
sessionId: input.sessionId,
userMessage: input.userMessage,
sessionItems: input.sessionItems,
sessionAddressNavigationState: input.sessionAddressNavigationState,
sessionScope: input.sessionScope,
payload: input.payload,
featureAddressLlmPredecomposeV1: input.featureAddressLlmPredecomposeV1,
runAddressLlmPreDecompose: input.runAddressLlmPreDecompose,
buildAddressLlmPredecomposeContractV1: input.buildAddressLlmPredecomposeContractV1,
sanitizeAddressMessageForFallback: input.sanitizeAddressMessageForFallback,
toNonEmptyString: input.toNonEmptyString,
resolveAddressFollowupCarryoverContext: input.resolveAddressFollowupCarryoverContext,
resolveAssistantOrchestrationDecision: input.resolveAssistantOrchestrationDecision,
buildAddressDialogContinuationContractV2: input.buildAddressDialogContinuationContractV2,
runtimeAnalysisContextAsOfDate: input.runtimeAnalysisContextAsOfDate,
compactWhitespace: input.compactWhitespace,
runAddressLaneAttempt,
isRetryableAddressLimitedResult: input.isRetryableAddressLimitedResult,
finalizeAddressLaneResponse,
tryHandleLivingChat,
logEvent: input.logEvent,
nowIso: input.nowIso,
runAddressOrchestrationRuntime: input.runAddressOrchestrationRuntime,
runAddressToolGateRuntime: input.runAddressToolGateRuntime,
runAddressLaneRuntime: input.runAddressLaneRuntime
})
);
}