ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Рефакторинг этапов 2.47: вынесен верхний orchestration-скелет handleMessage (bootstrap -> address attempt -> deep attempt) в единый turn runtime adapter без изменения поведения.
This commit is contained in:
@@ -19,6 +19,7 @@ import * as assistantCanon_1 from "./assistantCanon";
|
||||
import * as assistantAddressAttemptRuntimeAdapter_1 from "./assistantAddressAttemptRuntimeAdapter";
|
||||
import * as assistantCoverageGrounding_1 from "./assistantCoverageGrounding";
|
||||
import * as assistantDeepTurnAttemptRuntimeAdapter_1 from "./assistantDeepTurnAttemptRuntimeAdapter";
|
||||
import * as assistantTurnAttemptRuntimeAdapter_1 from "./assistantTurnAttemptRuntimeAdapter";
|
||||
import * as assistantUserTurnBootstrapRuntimeAdapter_1 from "./assistantUserTurnBootstrapRuntimeAdapter";
|
||||
import * as assistantQueryPlanning_1 from "./assistantQueryPlanning";
|
||||
import iconv from "iconv-lite";
|
||||
@@ -4324,125 +4325,124 @@ export class AssistantService {
|
||||
return this.sessions.getSession(sessionId);
|
||||
}
|
||||
async handleMessage(payload) {
|
||||
const { session, sessionId, userMessage, runtimeAnalysisContext, userItem } = (0, assistantUserTurnBootstrapRuntimeAdapter_1.runAssistantUserTurnBootstrapRuntime)({
|
||||
const turnRuntime = await (0, assistantTurnAttemptRuntimeAdapter_1.runAssistantTurnAttemptRuntime)({
|
||||
payload,
|
||||
ensureSession: (targetSessionId) => this.sessions.ensureSession(targetSessionId),
|
||||
appendItem: (targetSessionId, item) => this.sessions.appendItem(targetSessionId, item),
|
||||
getSession: (targetSessionId) => this.sessions.getSession(targetSessionId),
|
||||
persistSession: (sessionState) => this.sessionLogger.persistSession(sessionState),
|
||||
compactWhitespace,
|
||||
repairAddressMojibake,
|
||||
resolveRuntimeAnalysisContext,
|
||||
messageIdFactory: () => `msg-${(0, nanoid_1.nanoid)(10)}`,
|
||||
nowIso: () => new Date().toISOString()
|
||||
runUserTurnBootstrapRuntime: (runtimePayload) => (0, assistantUserTurnBootstrapRuntimeAdapter_1.runAssistantUserTurnBootstrapRuntime)({
|
||||
payload: runtimePayload,
|
||||
ensureSession: (targetSessionId) => this.sessions.ensureSession(targetSessionId),
|
||||
appendItem: (targetSessionId, item) => this.sessions.appendItem(targetSessionId, item),
|
||||
getSession: (targetSessionId) => this.sessions.getSession(targetSessionId),
|
||||
persistSession: (sessionState) => this.sessionLogger.persistSession(sessionState),
|
||||
compactWhitespace,
|
||||
repairAddressMojibake,
|
||||
resolveRuntimeAnalysisContext,
|
||||
messageIdFactory: () => `msg-${(0, nanoid_1.nanoid)(10)}`,
|
||||
nowIso: () => new Date().toISOString()
|
||||
}),
|
||||
resolveSessionOrganizationScopeContext: (runtimeUserMessage, sessionItems) => resolveSessionOrganizationScopeContext(runtimeUserMessage, sessionItems),
|
||||
runAddressAttemptRuntime: async (runtimeInput) => (0, assistantAddressAttemptRuntimeAdapter_1.runAssistantAddressAttemptRuntime)({
|
||||
featureAssistantAddressQueryV1: config_1.FEATURE_ASSISTANT_ADDRESS_QUERY_V1,
|
||||
sessionId: runtimeInput.sessionId,
|
||||
userMessage: runtimeInput.userMessage,
|
||||
sessionItems: runtimeInput.sessionItems,
|
||||
payload: runtimeInput.payload,
|
||||
sessionScope: {
|
||||
knownOrganizations: runtimeInput.sessionOrganizationScope.knownOrganizations,
|
||||
selectedOrganization: runtimeInput.sessionOrganizationScope.selectedOrganization,
|
||||
activeOrganization: runtimeInput.sessionOrganizationScope.activeOrganization
|
||||
},
|
||||
featureAddressLlmPredecomposeV1: config_1.FEATURE_ASSISTANT_ADDRESS_QUERY_LLM_PREDECOMPOSE_V1,
|
||||
runAddressLlmPreDecompose: async () => runAddressLlmPreDecompose(this.normalizerService, runtimeInput.payload, runtimeInput.userMessage),
|
||||
buildAddressLlmPredecomposeContractV1: predecomposeContract_1.buildAddressLlmPredecomposeContractV1,
|
||||
sanitizeAddressMessageForFallback,
|
||||
toNonEmptyString,
|
||||
resolveAddressFollowupCarryoverContext,
|
||||
resolveAssistantOrchestrationDecision,
|
||||
buildAddressDialogContinuationContractV2,
|
||||
runtimeAnalysisContextAsOfDate: runtimeInput.runtimeAnalysisContext.as_of_date,
|
||||
compactWhitespace,
|
||||
mergeFollowupContextWithOrganizationScope,
|
||||
runAddressQueryTryHandle: (laneMessageUsed, options) => this.addressQueryService.tryHandle(laneMessageUsed, options),
|
||||
isRetryableAddressLimitedResult,
|
||||
mergeKnownOrganizations,
|
||||
hasAssistantDataScopeMetaQuestionSignal,
|
||||
shouldHandleAsAssistantCapabilityMetaQuery,
|
||||
hasDestructiveDataActionSignal,
|
||||
hasDangerOrCoercionSignal,
|
||||
hasOperationalAdminActionRequestSignal,
|
||||
hasOrganizationFactLookupSignal,
|
||||
hasOrganizationFactFollowupSignal,
|
||||
shouldEmitOrganizationSelectionReply,
|
||||
hasAssistantCapabilityQuestionSignal,
|
||||
resolveDataScopeProbe: () => resolveAssistantDataScopeProbe(),
|
||||
applyScriptGuard: (chatText, runtimeUserMessage) => applyLivingChatScriptGuard(chatText, runtimeUserMessage),
|
||||
applyGroundingGuard: (guardInput) => applyLivingChatGroundingGuard(guardInput),
|
||||
buildAssistantSafetyRefusalReply,
|
||||
buildAssistantDataScopeContractReply,
|
||||
buildAssistantOrganizationFactBoundaryReply,
|
||||
buildAssistantDataScopeSelectionReply,
|
||||
buildAssistantOperationalBoundaryReply,
|
||||
buildAssistantCapabilityContractReply,
|
||||
chatClient: this.chatClient,
|
||||
loadAssistantCanonExcerpt: assistantCanon_1.loadAssistantCanonExcerpt,
|
||||
sanitizeOutgoingAssistantText,
|
||||
defaultModel: config_1.DEFAULT_MODEL,
|
||||
defaultBaseUrl: config_1.DEFAULT_OPENAI_BASE_URL,
|
||||
defaultApiKey: process.env.OPENAI_API_KEY ?? "",
|
||||
buildAddressDebugPayload,
|
||||
buildAddressFollowupOffer,
|
||||
appendItem: (targetSessionId, item) => this.sessions.appendItem(targetSessionId, item),
|
||||
getSession: (targetSessionId) => this.sessions.getSession(targetSessionId),
|
||||
persistSession: (sessionState) => this.sessionLogger.persistSession(sessionState),
|
||||
cloneConversation: (items) => cloneItems(items),
|
||||
logEvent: (runtimePayload) => (0, log_1.logJson)(runtimePayload),
|
||||
messageIdFactory: () => `msg-${(0, nanoid_1.nanoid)(10)}`,
|
||||
nowIso: () => new Date().toISOString()
|
||||
}),
|
||||
runDeepTurnAttemptRuntime: async (runtimeInput) => (0, assistantDeepTurnAttemptRuntimeAdapter_1.runAssistantDeepTurnAttemptRuntime)({
|
||||
sessionId: runtimeInput.sessionId,
|
||||
questionId: runtimeInput.questionId,
|
||||
userMessage: runtimeInput.userMessage,
|
||||
payload: runtimeInput.payload,
|
||||
runtimeAnalysisContext: runtimeInput.runtimeAnalysisContext,
|
||||
sessionInvestigationState: runtimeInput.sessionInvestigationState,
|
||||
addressRuntimeMetaForDeep: runtimeInput.addressRuntimeMetaForDeep,
|
||||
featureInvestigationStateV1: config_1.FEATURE_ASSISTANT_INVESTIGATION_STATE_V1,
|
||||
featureStateFollowupBindingV1: config_1.FEATURE_ASSISTANT_STATE_FOLLOWUP_BINDING_V1,
|
||||
featureContractsV11: config_1.FEATURE_ASSISTANT_CONTRACTS_V11,
|
||||
featureAnswerPolicyV11: config_1.FEATURE_ASSISTANT_ANSWER_POLICY_V11,
|
||||
featureProblemCentricAnswerV1: config_1.FEATURE_ASSISTANT_PROBLEM_CENTRIC_ANSWER_V1,
|
||||
featureLifecycleAnswerV1: config_1.FEATURE_ASSISTANT_LIFECYCLE_ANSWER_V1,
|
||||
buildFollowupStateBinding,
|
||||
normalize: (normalizePayload) => this.normalizerService.normalize(normalizePayload),
|
||||
resolveBusinessScopeAlignment,
|
||||
inferP0DomainFromMessage,
|
||||
resolveBusinessScopeFromLiveContext,
|
||||
extractRequirements,
|
||||
toExecutionPlan,
|
||||
enforceRbpLiveRoutePlan,
|
||||
enforceFaLiveRoutePlan,
|
||||
executeRouteRuntime: (route, fragmentText, options) => this.dataLayer.executeRouteRuntime(route, fragmentText, options),
|
||||
mapNoRouteReason,
|
||||
buildSkippedResult,
|
||||
evaluateCoverage,
|
||||
checkGrounding,
|
||||
collectRbpLiveRouteAudit,
|
||||
collectFaLiveRouteAudit,
|
||||
hasExplicitPeriodAnchor: (normalizedPayload) => hasExplicitPeriodAnchorFromNormalized(normalizedPayload),
|
||||
extractDroppedIntentSegments: (normalizedPayload) => extractDiscardedIntentSegments(normalizedPayload),
|
||||
buildDebugRoutes: (routeSummary) => toDebugRoutes(routeSummary),
|
||||
extractExecutionState: (normalizedPayload) => extractExecutionState(normalizedPayload),
|
||||
sanitizeReply: (value, fallback) => sanitizeOutgoingAssistantText(value, fallback),
|
||||
persistInvestigationState: (targetSessionId, snapshot) => this.sessions.setInvestigationState(targetSessionId, snapshot),
|
||||
messageIdFactory: () => `msg-${(0, nanoid_1.nanoid)(10)}`,
|
||||
appendItem: (targetSessionId, item) => this.sessions.appendItem(targetSessionId, item),
|
||||
getSession: (targetSessionId) => this.sessions.getSession(targetSessionId),
|
||||
persistSession: (sessionState) => this.sessionLogger.persistSession(sessionState),
|
||||
cloneConversation: (items) => cloneItems(items),
|
||||
logEvent: (runtimePayload) => (0, log_1.logJson)(runtimePayload)
|
||||
})
|
||||
});
|
||||
const sessionOrganizationScope = resolveSessionOrganizationScopeContext(userMessage, session.items);
|
||||
const addressRuntime = await (0, assistantAddressAttemptRuntimeAdapter_1.runAssistantAddressAttemptRuntime)({
|
||||
featureAssistantAddressQueryV1: config_1.FEATURE_ASSISTANT_ADDRESS_QUERY_V1,
|
||||
sessionId,
|
||||
userMessage,
|
||||
sessionItems: session.items,
|
||||
payload,
|
||||
sessionScope: {
|
||||
knownOrganizations: sessionOrganizationScope.knownOrganizations,
|
||||
selectedOrganization: sessionOrganizationScope.selectedOrganization,
|
||||
activeOrganization: sessionOrganizationScope.activeOrganization
|
||||
},
|
||||
featureAddressLlmPredecomposeV1: config_1.FEATURE_ASSISTANT_ADDRESS_QUERY_LLM_PREDECOMPOSE_V1,
|
||||
runAddressLlmPreDecompose: async () => runAddressLlmPreDecompose(this.normalizerService, payload, userMessage),
|
||||
buildAddressLlmPredecomposeContractV1: predecomposeContract_1.buildAddressLlmPredecomposeContractV1,
|
||||
sanitizeAddressMessageForFallback,
|
||||
toNonEmptyString,
|
||||
resolveAddressFollowupCarryoverContext,
|
||||
resolveAssistantOrchestrationDecision,
|
||||
buildAddressDialogContinuationContractV2,
|
||||
runtimeAnalysisContextAsOfDate: runtimeAnalysisContext.as_of_date,
|
||||
compactWhitespace,
|
||||
mergeFollowupContextWithOrganizationScope,
|
||||
runAddressQueryTryHandle: (laneMessageUsed, options) => this.addressQueryService.tryHandle(laneMessageUsed, options),
|
||||
isRetryableAddressLimitedResult,
|
||||
mergeKnownOrganizations,
|
||||
hasAssistantDataScopeMetaQuestionSignal,
|
||||
shouldHandleAsAssistantCapabilityMetaQuery,
|
||||
hasDestructiveDataActionSignal,
|
||||
hasDangerOrCoercionSignal,
|
||||
hasOperationalAdminActionRequestSignal,
|
||||
hasOrganizationFactLookupSignal,
|
||||
hasOrganizationFactFollowupSignal,
|
||||
shouldEmitOrganizationSelectionReply,
|
||||
hasAssistantCapabilityQuestionSignal,
|
||||
resolveDataScopeProbe: () => resolveAssistantDataScopeProbe(),
|
||||
applyScriptGuard: (chatText, runtimeUserMessage) => applyLivingChatScriptGuard(chatText, runtimeUserMessage),
|
||||
applyGroundingGuard: (guardInput) => applyLivingChatGroundingGuard(guardInput),
|
||||
buildAssistantSafetyRefusalReply,
|
||||
buildAssistantDataScopeContractReply,
|
||||
buildAssistantOrganizationFactBoundaryReply,
|
||||
buildAssistantDataScopeSelectionReply,
|
||||
buildAssistantOperationalBoundaryReply,
|
||||
buildAssistantCapabilityContractReply,
|
||||
chatClient: this.chatClient,
|
||||
loadAssistantCanonExcerpt: assistantCanon_1.loadAssistantCanonExcerpt,
|
||||
sanitizeOutgoingAssistantText,
|
||||
defaultModel: config_1.DEFAULT_MODEL,
|
||||
defaultBaseUrl: config_1.DEFAULT_OPENAI_BASE_URL,
|
||||
defaultApiKey: process.env.OPENAI_API_KEY ?? "",
|
||||
buildAddressDebugPayload,
|
||||
buildAddressFollowupOffer,
|
||||
appendItem: (targetSessionId, item) => this.sessions.appendItem(targetSessionId, item),
|
||||
getSession: (targetSessionId) => this.sessions.getSession(targetSessionId),
|
||||
persistSession: (sessionState) => this.sessionLogger.persistSession(sessionState),
|
||||
cloneConversation: (items) => cloneItems(items),
|
||||
logEvent: (payload) => (0, log_1.logJson)(payload),
|
||||
messageIdFactory: () => `msg-${(0, nanoid_1.nanoid)(10)}`,
|
||||
nowIso: () => new Date().toISOString()
|
||||
});
|
||||
const addressRuntimeMetaForDeep = addressRuntime.addressRuntimeMetaForDeep;
|
||||
if (addressRuntime.handled && addressRuntime.response) {
|
||||
return addressRuntime.response;
|
||||
}
|
||||
const deepTurnRuntime = await (0, assistantDeepTurnAttemptRuntimeAdapter_1.runAssistantDeepTurnAttemptRuntime)({
|
||||
sessionId,
|
||||
questionId: userItem.message_id,
|
||||
userMessage,
|
||||
payload,
|
||||
runtimeAnalysisContext,
|
||||
sessionInvestigationState: session.investigation_state,
|
||||
addressRuntimeMetaForDeep,
|
||||
featureInvestigationStateV1: config_1.FEATURE_ASSISTANT_INVESTIGATION_STATE_V1,
|
||||
featureStateFollowupBindingV1: config_1.FEATURE_ASSISTANT_STATE_FOLLOWUP_BINDING_V1,
|
||||
featureContractsV11: config_1.FEATURE_ASSISTANT_CONTRACTS_V11,
|
||||
featureAnswerPolicyV11: config_1.FEATURE_ASSISTANT_ANSWER_POLICY_V11,
|
||||
featureProblemCentricAnswerV1: config_1.FEATURE_ASSISTANT_PROBLEM_CENTRIC_ANSWER_V1,
|
||||
featureLifecycleAnswerV1: config_1.FEATURE_ASSISTANT_LIFECYCLE_ANSWER_V1,
|
||||
buildFollowupStateBinding,
|
||||
normalize: (normalizePayload) => this.normalizerService.normalize(normalizePayload),
|
||||
resolveBusinessScopeAlignment,
|
||||
inferP0DomainFromMessage,
|
||||
resolveBusinessScopeFromLiveContext,
|
||||
extractRequirements,
|
||||
toExecutionPlan,
|
||||
enforceRbpLiveRoutePlan,
|
||||
enforceFaLiveRoutePlan,
|
||||
executeRouteRuntime: (route, fragmentText, options) => this.dataLayer.executeRouteRuntime(route, fragmentText, options),
|
||||
mapNoRouteReason,
|
||||
buildSkippedResult,
|
||||
evaluateCoverage,
|
||||
checkGrounding,
|
||||
collectRbpLiveRouteAudit,
|
||||
collectFaLiveRouteAudit,
|
||||
hasExplicitPeriodAnchor: (normalizedPayload) => hasExplicitPeriodAnchorFromNormalized(normalizedPayload),
|
||||
extractDroppedIntentSegments: (normalizedPayload) => extractDiscardedIntentSegments(normalizedPayload),
|
||||
buildDebugRoutes: (routeSummary) => toDebugRoutes(routeSummary),
|
||||
extractExecutionState: (normalizedPayload) => extractExecutionState(normalizedPayload),
|
||||
sanitizeReply: (value, fallback) => sanitizeOutgoingAssistantText(value, fallback),
|
||||
persistInvestigationState: (targetSessionId, snapshot) => this.sessions.setInvestigationState(targetSessionId, snapshot),
|
||||
messageIdFactory: () => `msg-${(0, nanoid_1.nanoid)(10)}`,
|
||||
appendItem: (targetSessionId, item) => this.sessions.appendItem(targetSessionId, item),
|
||||
getSession: (targetSessionId) => this.sessions.getSession(targetSessionId),
|
||||
persistSession: (sessionState) => this.sessionLogger.persistSession(sessionState),
|
||||
cloneConversation: (items) => cloneItems(items),
|
||||
logEvent: (payload) => (0, log_1.logJson)(payload)
|
||||
});
|
||||
return deepTurnRuntime.response;
|
||||
return turnRuntime.response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
import type { RunAssistantAddressRuntimeOutput } from "./assistantAddressRuntimeAdapter";
|
||||
import type { RunAssistantUserTurnBootstrapRuntimeOutput } from "./assistantUserTurnBootstrapRuntimeAdapter";
|
||||
|
||||
export interface AssistantSessionOrganizationScopeContext {
|
||||
knownOrganizations: string[];
|
||||
selectedOrganization: string | null;
|
||||
activeOrganization: string | null;
|
||||
}
|
||||
|
||||
export interface RunAssistantTurnAttemptRuntimeAddressInput<PayloadType = unknown> {
|
||||
payload: PayloadType;
|
||||
sessionId: string;
|
||||
userMessage: string;
|
||||
sessionItems: unknown[];
|
||||
runtimeAnalysisContext: { as_of_date: string | null };
|
||||
sessionOrganizationScope: AssistantSessionOrganizationScopeContext;
|
||||
}
|
||||
|
||||
export interface RunAssistantTurnAttemptRuntimeDeepInput<PayloadType = unknown> {
|
||||
payload: PayloadType;
|
||||
sessionId: string;
|
||||
questionId: string;
|
||||
userMessage: string;
|
||||
runtimeAnalysisContext: unknown;
|
||||
sessionInvestigationState: unknown;
|
||||
addressRuntimeMetaForDeep: Record<string, unknown> | null;
|
||||
}
|
||||
|
||||
export interface RunAssistantTurnAttemptRuntimeInput<ResponseType = unknown, PayloadType = unknown> {
|
||||
payload: PayloadType;
|
||||
runUserTurnBootstrapRuntime: (payload: PayloadType) => RunAssistantUserTurnBootstrapRuntimeOutput;
|
||||
resolveSessionOrganizationScopeContext: (
|
||||
userMessage: string,
|
||||
sessionItems: unknown[]
|
||||
) => AssistantSessionOrganizationScopeContext;
|
||||
runAddressAttemptRuntime: (
|
||||
input: RunAssistantTurnAttemptRuntimeAddressInput<PayloadType>
|
||||
) => Promise<RunAssistantAddressRuntimeOutput<ResponseType>>;
|
||||
runDeepTurnAttemptRuntime: (
|
||||
input: RunAssistantTurnAttemptRuntimeDeepInput<PayloadType>
|
||||
) => Promise<{ response: ResponseType }>;
|
||||
}
|
||||
|
||||
export interface RunAssistantTurnAttemptRuntimeOutput<ResponseType = unknown> {
|
||||
response: ResponseType;
|
||||
source: "address" | "deep";
|
||||
addressRuntimeMetaForDeep: Record<string, unknown> | null;
|
||||
userTurn: RunAssistantUserTurnBootstrapRuntimeOutput;
|
||||
sessionOrganizationScope: AssistantSessionOrganizationScopeContext;
|
||||
}
|
||||
|
||||
export async function runAssistantTurnAttemptRuntime<ResponseType = unknown, PayloadType = unknown>(
|
||||
input: RunAssistantTurnAttemptRuntimeInput<ResponseType, PayloadType>
|
||||
): Promise<RunAssistantTurnAttemptRuntimeOutput<ResponseType>> {
|
||||
const userTurn = input.runUserTurnBootstrapRuntime(input.payload);
|
||||
const sessionOrganizationScope = input.resolveSessionOrganizationScopeContext(
|
||||
userTurn.userMessage,
|
||||
userTurn.session.items
|
||||
);
|
||||
const addressRuntime = await input.runAddressAttemptRuntime({
|
||||
payload: input.payload,
|
||||
sessionId: userTurn.sessionId,
|
||||
userMessage: userTurn.userMessage,
|
||||
sessionItems: userTurn.session.items,
|
||||
runtimeAnalysisContext: userTurn.runtimeAnalysisContext,
|
||||
sessionOrganizationScope
|
||||
});
|
||||
|
||||
const addressRuntimeMetaForDeep = addressRuntime.addressRuntimeMetaForDeep ?? null;
|
||||
if (addressRuntime.handled && addressRuntime.response) {
|
||||
return {
|
||||
response: addressRuntime.response,
|
||||
source: "address",
|
||||
addressRuntimeMetaForDeep,
|
||||
userTurn,
|
||||
sessionOrganizationScope
|
||||
};
|
||||
}
|
||||
|
||||
const deepTurnRuntime = await input.runDeepTurnAttemptRuntime({
|
||||
payload: input.payload,
|
||||
sessionId: userTurn.sessionId,
|
||||
questionId: userTurn.userItem.message_id,
|
||||
userMessage: userTurn.userMessage,
|
||||
runtimeAnalysisContext: userTurn.runtimeAnalysisContext,
|
||||
sessionInvestigationState: userTurn.session.investigation_state,
|
||||
addressRuntimeMetaForDeep
|
||||
});
|
||||
|
||||
return {
|
||||
response: deepTurnRuntime.response,
|
||||
source: "deep",
|
||||
addressRuntimeMetaForDeep,
|
||||
userTurn,
|
||||
sessionOrganizationScope
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user