ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Рефакторинг этапов 2.46: склейка всего address-потока в отдельный assistantAddressAttemptRuntimeAdapter, для того чтобы из handleMessage убрать три локальных closure целиком. Все три моста (lane, response, living chat) прокидываются и не ломают контракт.
This commit is contained in:
parent
5790e25b68
commit
5f4e898c7c
|
|
@ -1437,7 +1437,38 @@ Validation:
|
|||
- `assistantDeepTurnPackagingRuntimeAdapter.test.ts`
|
||||
- `assistantWave10SettlementCorrectiveRegression.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 completed)**
|
||||
Implemented in current pass (Phase 2.46):
|
||||
1. Activated full address-turn attempt runtime boundary inside `assistantService`:
|
||||
- rewired address handling call-site to `runAssistantAddressAttemptRuntime(...)`;
|
||||
- removed local inline closures for lane-attempt, lane-response, and living-chat handoff wiring from `handleMessage`.
|
||||
2. Finalized and type-hardened address attempt adapter contract:
|
||||
- `assistantAddressAttemptRuntimeAdapter.ts`
|
||||
- aligned `logEvent` and `messageIdFactory` contract typing to runtime expectations.
|
||||
3. Added focused unit tests:
|
||||
- `assistantAddressAttemptRuntimeAdapter.test.ts`
|
||||
|
||||
Validation:
|
||||
1. `npm run build` passed.
|
||||
2. Targeted living/address/deep followup pack passed:
|
||||
- `assistantAddressAttemptRuntimeAdapter.test.ts`
|
||||
- `assistantDeepTurnAttemptRuntimeAdapter.test.ts`
|
||||
- `assistantDeepTurnResponseAttemptRuntimeAdapter.test.ts`
|
||||
- `assistantDeepTurnAnalysisAttemptRuntimeAdapter.test.ts`
|
||||
- `assistantDeepTurnAnalysisRuntimeAdapter.test.ts`
|
||||
- `assistantAddressLaneResponseAttemptRuntimeAdapter.test.ts`
|
||||
- `assistantLivingChatAttemptRuntimeAdapter.test.ts`
|
||||
- `assistantAddressLaneAttemptRuntimeAdapter.test.ts`
|
||||
- `assistantUserTurnBootstrapRuntimeAdapter.test.ts`
|
||||
- `assistantLivingChatLlmRuntimeAdapter.test.ts`
|
||||
- `assistantLivingChatHandlerRuntimeAdapter.test.ts`
|
||||
- `assistantLivingChatRuntimeAdapter.test.ts`
|
||||
- `assistantAddressRuntimeAdapter.test.ts`
|
||||
- `assistantAddressLaneResponseRuntimeAdapter.test.ts`
|
||||
- `assistantDeepTurnResponseRuntimeAdapter.test.ts`
|
||||
- `assistantDeepTurnPackagingRuntimeAdapter.test.ts`
|
||||
- `assistantWave10SettlementCorrectiveRegression.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 completed)**
|
||||
|
||||
## Stage 3 (P2): Hybrid Semantic Layer (LLM + Deterministic Guards)
|
||||
|
||||
|
|
|
|||
117
llm_normalizer/backend/dist/services/assistantAddressAttemptRuntimeAdapter.js
vendored
Normal file
117
llm_normalizer/backend/dist/services/assistantAddressAttemptRuntimeAdapter.js
vendored
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.runAssistantAddressAttemptRuntime = runAssistantAddressAttemptRuntime;
|
||||
const assistantAddressRuntimeAdapter_1 = require("./assistantAddressRuntimeAdapter");
|
||||
const assistantAddressLaneAttemptRuntimeAdapter_1 = require("./assistantAddressLaneAttemptRuntimeAdapter");
|
||||
const assistantAddressLaneResponseAttemptRuntimeAdapter_1 = require("./assistantAddressLaneResponseAttemptRuntimeAdapter");
|
||||
const assistantLivingChatAttemptRuntimeAdapter_1 = require("./assistantLivingChatAttemptRuntimeAdapter");
|
||||
async function runAssistantAddressAttemptRuntime(input) {
|
||||
const runAddressRuntimeSafe = input.runAddressRuntime ?? assistantAddressRuntimeAdapter_1.runAssistantAddressRuntime;
|
||||
const runAddressLaneAttemptRuntimeSafe = input.runAddressLaneAttemptRuntime ?? assistantAddressLaneAttemptRuntimeAdapter_1.runAssistantAddressLaneAttemptRuntime;
|
||||
const runAddressLaneResponseAttemptRuntimeSafe = input.runAddressLaneResponseAttemptRuntime ?? assistantAddressLaneResponseAttemptRuntimeAdapter_1.runAssistantAddressLaneResponseAttemptRuntime;
|
||||
const runLivingChatAttemptRuntimeSafe = input.runLivingChatAttemptRuntime ?? assistantLivingChatAttemptRuntimeAdapter_1.runAssistantLivingChatAttemptRuntime;
|
||||
const finalizeAddressLaneResponse = (addressLane, effectiveAddressUserMessage, carryoverMeta = null, llmPreDecomposeMeta = null) => runAddressLaneResponseAttemptRuntimeSafe({
|
||||
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 = async (modeDecision, addressRuntimeMeta = null) => runLivingChatAttemptRuntimeSafe({
|
||||
sessionId: input.sessionId,
|
||||
userMessage: input.userMessage,
|
||||
sessionItems: input.sessionItems,
|
||||
modeDecision,
|
||||
sessionScope: {
|
||||
knownOrganizations: input.sessionScope.knownOrganizations,
|
||||
selectedOrganization: input.sessionScope.selectedOrganization,
|
||||
activeOrganization: input.sessionScope.activeOrganization
|
||||
},
|
||||
addressRuntimeMeta,
|
||||
traceIdFactory: () => `chat-${input.messageIdFactory().replace(/^msg-/, "")}`,
|
||||
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({
|
||||
messageUsed,
|
||||
carryMeta,
|
||||
analysisDateHint,
|
||||
activeOrganization: input.sessionScope.activeOrganization,
|
||||
mergeFollowupContextWithOrganizationScope: input.mergeFollowupContextWithOrganizationScope,
|
||||
runAddressQueryTryHandle: input.runAddressQueryTryHandle
|
||||
});
|
||||
return runAddressRuntimeSafe({
|
||||
featureAssistantAddressQueryV1: input.featureAssistantAddressQueryV1,
|
||||
sessionId: input.sessionId,
|
||||
userMessage: input.userMessage,
|
||||
sessionItems: input.sessionItems,
|
||||
llmProvider: input.payload.llmProvider,
|
||||
useMock: Boolean(input.payload.useMock),
|
||||
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,
|
||||
payloadContextPeriodHint: input.payload?.context?.period_hint,
|
||||
compactWhitespace: input.compactWhitespace,
|
||||
runAddressLaneAttempt,
|
||||
isRetryableAddressLimitedResult: input.isRetryableAddressLimitedResult,
|
||||
finalizeAddressLaneResponse,
|
||||
tryHandleLivingChat,
|
||||
logEvent: input.logEvent,
|
||||
nowIso: input.nowIso,
|
||||
runAddressOrchestrationRuntime: input.runAddressOrchestrationRuntime,
|
||||
runAddressToolGateRuntime: input.runAddressToolGateRuntime,
|
||||
runAddressLaneRuntime: input.runAddressLaneRuntime
|
||||
});
|
||||
}
|
||||
|
|
@ -62,12 +62,9 @@ const openaiResponsesClient_1 = __importStar(require("./openaiResponsesClient"))
|
|||
const addressMcpClient_1 = __importStar(require("./addressMcpClient"));
|
||||
const capabilitiesRegistry_1 = __importStar(require("./capabilitiesRegistry"));
|
||||
const assistantCanon_1 = __importStar(require("./assistantCanon"));
|
||||
const assistantAddressLaneResponseAttemptRuntimeAdapter_1 = __importStar(require("./assistantAddressLaneResponseAttemptRuntimeAdapter"));
|
||||
const assistantAddressAttemptRuntimeAdapter_1 = __importStar(require("./assistantAddressAttemptRuntimeAdapter"));
|
||||
const assistantCoverageGrounding_1 = __importStar(require("./assistantCoverageGrounding"));
|
||||
const assistantDeepTurnAttemptRuntimeAdapter_1 = __importStar(require("./assistantDeepTurnAttemptRuntimeAdapter"));
|
||||
const assistantAddressRuntimeAdapter_1 = __importStar(require("./assistantAddressRuntimeAdapter"));
|
||||
const assistantAddressLaneAttemptRuntimeAdapter_1 = __importStar(require("./assistantAddressLaneAttemptRuntimeAdapter"));
|
||||
const assistantLivingChatAttemptRuntimeAdapter_1 = __importStar(require("./assistantLivingChatAttemptRuntimeAdapter"));
|
||||
const assistantUserTurnBootstrapRuntimeAdapter_1 = __importStar(require("./assistantUserTurnBootstrapRuntimeAdapter"));
|
||||
const assistantQueryPlanning_1 = __importStar(require("./assistantQueryPlanning"));
|
||||
const iconv_lite_1 = __importDefault(require("iconv-lite"));
|
||||
|
|
@ -4385,40 +4382,30 @@ class AssistantService {
|
|||
nowIso: () => new Date().toISOString()
|
||||
});
|
||||
const sessionOrganizationScope = resolveSessionOrganizationScopeContext(userMessage, session.items);
|
||||
const finalizeAddressLaneResponse = (addressLane, effectiveAddressUserMessage, carryoverMeta = null, llmPreDecomposeMeta = null) => (0, assistantAddressLaneResponseAttemptRuntimeAdapter_1.runAssistantAddressLaneResponseAttemptRuntime)({
|
||||
sessionId,
|
||||
userMessage,
|
||||
effectiveAddressUserMessage,
|
||||
addressLane,
|
||||
carryoverMeta,
|
||||
llmPreDecomposeMeta,
|
||||
knownOrganizations: sessionOrganizationScope.knownOrganizations,
|
||||
activeOrganization: sessionOrganizationScope.activeOrganization,
|
||||
sanitizeOutgoingAssistantText,
|
||||
buildAddressDebugPayload,
|
||||
buildAddressFollowupOffer,
|
||||
mergeKnownOrganizations,
|
||||
toNonEmptyString,
|
||||
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)}`
|
||||
});
|
||||
const tryHandleLivingChat = async (modeDecision, addressRuntimeMeta = null) => (0, assistantLivingChatAttemptRuntimeAdapter_1.runAssistantLivingChatAttemptRuntime)({
|
||||
const addressRuntime = await (0, assistantAddressAttemptRuntimeAdapter_1.runAssistantAddressAttemptRuntime)({
|
||||
featureAssistantAddressQueryV1: config_1.FEATURE_ASSISTANT_ADDRESS_QUERY_V1,
|
||||
sessionId,
|
||||
userMessage,
|
||||
sessionItems: session.items,
|
||||
modeDecision,
|
||||
payload,
|
||||
sessionScope: {
|
||||
knownOrganizations: sessionOrganizationScope.knownOrganizations,
|
||||
selectedOrganization: sessionOrganizationScope.selectedOrganization,
|
||||
activeOrganization: sessionOrganizationScope.activeOrganization
|
||||
},
|
||||
addressRuntimeMeta,
|
||||
traceIdFactory: () => `chat-${(0, nanoid_1.nanoid)(10)}`,
|
||||
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,
|
||||
|
|
@ -4438,56 +4425,23 @@ class AssistantService {
|
|||
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(),
|
||||
payload,
|
||||
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 ?? ""
|
||||
});
|
||||
let addressRuntimeMetaForDeep = null;
|
||||
const runAddressLaneAttempt = async (messageUsed, carryMeta, analysisDateHint) => (0, assistantAddressLaneAttemptRuntimeAdapter_1.runAssistantAddressLaneAttemptRuntime)({
|
||||
messageUsed,
|
||||
carryMeta: carryMeta ?? null,
|
||||
analysisDateHint: analysisDateHint ?? null,
|
||||
activeOrganization: sessionOrganizationScope.activeOrganization,
|
||||
mergeFollowupContextWithOrganizationScope,
|
||||
runAddressQueryTryHandle: (laneMessageUsed, options) => this.addressQueryService.tryHandle(laneMessageUsed, options)
|
||||
});
|
||||
const addressRuntime = await (0, assistantAddressRuntimeAdapter_1.runAssistantAddressRuntime)({
|
||||
featureAssistantAddressQueryV1: config_1.FEATURE_ASSISTANT_ADDRESS_QUERY_V1,
|
||||
sessionId,
|
||||
userMessage,
|
||||
sessionItems: session.items,
|
||||
llmProvider: payload?.llmProvider,
|
||||
useMock: Boolean(payload.useMock),
|
||||
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,
|
||||
payloadContextPeriodHint: payload?.context?.period_hint,
|
||||
compactWhitespace,
|
||||
runAddressLaneAttempt,
|
||||
isRetryableAddressLimitedResult,
|
||||
finalizeAddressLaneResponse,
|
||||
tryHandleLivingChat: (modeDecision, runtimeMeta) => tryHandleLivingChat(modeDecision, runtimeMeta),
|
||||
logEvent: (payload) => (0, log_1.logJson)(payload),
|
||||
nowIso: () => new Date().toISOString()
|
||||
});
|
||||
addressRuntimeMetaForDeep = addressRuntime.addressRuntimeMetaForDeep;
|
||||
const addressRuntimeMetaForDeep = addressRuntime.addressRuntimeMetaForDeep;
|
||||
if (addressRuntime.handled && addressRuntime.response) {
|
||||
return addressRuntime.response;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,228 @@
|
|||
import {
|
||||
runAssistantAddressRuntime,
|
||||
type RunAssistantAddressRuntimeInput,
|
||||
type RunAssistantAddressRuntimeOutput
|
||||
} from "./assistantAddressRuntimeAdapter";
|
||||
import {
|
||||
runAssistantAddressLaneAttemptRuntime,
|
||||
type RunAssistantAddressLaneAttemptRuntimeInput
|
||||
} from "./assistantAddressLaneAttemptRuntimeAdapter";
|
||||
import {
|
||||
runAssistantAddressLaneResponseAttemptRuntime,
|
||||
type RunAssistantAddressLaneResponseAttemptRuntimeInput
|
||||
} from "./assistantAddressLaneResponseAttemptRuntimeAdapter";
|
||||
import {
|
||||
runAssistantLivingChatAttemptRuntime,
|
||||
type RunAssistantLivingChatAttemptRuntimeInput
|
||||
} from "./assistantLivingChatAttemptRuntimeAdapter";
|
||||
|
||||
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;
|
||||
mergeFollowupContextWithOrganizationScope: RunAssistantAddressLaneAttemptRuntimeInput["mergeFollowupContextWithOrganizationScope"];
|
||||
runAddressQueryTryHandle: RunAssistantAddressLaneAttemptRuntimeInput["runAddressQueryTryHandle"];
|
||||
mergeKnownOrganizations: RunAssistantAddressLaneResponseAttemptRuntimeInput<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"];
|
||||
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"];
|
||||
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({
|
||||
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 as any,
|
||||
toNonEmptyString: input.toNonEmptyString,
|
||||
appendItem: input.appendItem,
|
||||
getSession: input.getSession,
|
||||
persistSession: input.persistSession,
|
||||
cloneConversation: input.cloneConversation,
|
||||
logEvent: input.logEvent,
|
||||
messageIdFactory: input.messageIdFactory
|
||||
} as RunAssistantAddressLaneResponseAttemptRuntimeInput<ResponseType>);
|
||||
|
||||
const tryHandleLivingChat: RunAssistantAddressRuntimeInput<ResponseType>["tryHandleLivingChat"] = async (
|
||||
modeDecision,
|
||||
addressRuntimeMeta = null
|
||||
) =>
|
||||
runLivingChatAttemptRuntimeSafe({
|
||||
sessionId: input.sessionId,
|
||||
userMessage: input.userMessage,
|
||||
sessionItems: input.sessionItems,
|
||||
modeDecision,
|
||||
sessionScope: {
|
||||
knownOrganizations: input.sessionScope.knownOrganizations,
|
||||
selectedOrganization: input.sessionScope.selectedOrganization,
|
||||
activeOrganization: input.sessionScope.activeOrganization
|
||||
},
|
||||
addressRuntimeMeta,
|
||||
traceIdFactory: () => `chat-${input.messageIdFactory().replace(/^msg-/, "")}`,
|
||||
toNonEmptyString: input.toNonEmptyString,
|
||||
mergeKnownOrganizations: input.mergeKnownOrganizations as any,
|
||||
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
|
||||
} as RunAssistantLivingChatAttemptRuntimeInput<ResponseType>);
|
||||
|
||||
const runAddressLaneAttempt: RunAssistantAddressRuntimeInput<ResponseType>["runAddressLaneAttempt"] = async (
|
||||
messageUsed,
|
||||
carryMeta,
|
||||
analysisDateHint
|
||||
) =>
|
||||
runAddressLaneAttemptRuntimeSafe({
|
||||
messageUsed,
|
||||
carryMeta,
|
||||
analysisDateHint,
|
||||
activeOrganization: input.sessionScope.activeOrganization,
|
||||
mergeFollowupContextWithOrganizationScope: input.mergeFollowupContextWithOrganizationScope,
|
||||
runAddressQueryTryHandle: input.runAddressQueryTryHandle
|
||||
});
|
||||
|
||||
return runAddressRuntimeSafe({
|
||||
featureAssistantAddressQueryV1: input.featureAssistantAddressQueryV1,
|
||||
sessionId: input.sessionId,
|
||||
userMessage: input.userMessage,
|
||||
sessionItems: input.sessionItems,
|
||||
llmProvider: input.payload.llmProvider,
|
||||
useMock: Boolean(input.payload.useMock),
|
||||
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,
|
||||
payloadContextPeriodHint: input.payload?.context?.period_hint,
|
||||
compactWhitespace: input.compactWhitespace,
|
||||
runAddressLaneAttempt,
|
||||
isRetryableAddressLimitedResult: input.isRetryableAddressLimitedResult,
|
||||
finalizeAddressLaneResponse,
|
||||
tryHandleLivingChat,
|
||||
logEvent: input.logEvent,
|
||||
nowIso: input.nowIso,
|
||||
runAddressOrchestrationRuntime: input.runAddressOrchestrationRuntime,
|
||||
runAddressToolGateRuntime: input.runAddressToolGateRuntime,
|
||||
runAddressLaneRuntime: input.runAddressLaneRuntime
|
||||
});
|
||||
}
|
||||
|
|
@ -16,12 +16,9 @@ import * as openaiResponsesClient_1 from "./openaiResponsesClient";
|
|||
import * as addressMcpClient_1 from "./addressMcpClient";
|
||||
import * as capabilitiesRegistry_1 from "./capabilitiesRegistry";
|
||||
import * as assistantCanon_1 from "./assistantCanon";
|
||||
import * as assistantAddressLaneResponseAttemptRuntimeAdapter_1 from "./assistantAddressLaneResponseAttemptRuntimeAdapter";
|
||||
import * as assistantAddressAttemptRuntimeAdapter_1 from "./assistantAddressAttemptRuntimeAdapter";
|
||||
import * as assistantCoverageGrounding_1 from "./assistantCoverageGrounding";
|
||||
import * as assistantDeepTurnAttemptRuntimeAdapter_1 from "./assistantDeepTurnAttemptRuntimeAdapter";
|
||||
import * as assistantAddressRuntimeAdapter_1 from "./assistantAddressRuntimeAdapter";
|
||||
import * as assistantAddressLaneAttemptRuntimeAdapter_1 from "./assistantAddressLaneAttemptRuntimeAdapter";
|
||||
import * as assistantLivingChatAttemptRuntimeAdapter_1 from "./assistantLivingChatAttemptRuntimeAdapter";
|
||||
import * as assistantUserTurnBootstrapRuntimeAdapter_1 from "./assistantUserTurnBootstrapRuntimeAdapter";
|
||||
import * as assistantQueryPlanning_1 from "./assistantQueryPlanning";
|
||||
import iconv from "iconv-lite";
|
||||
|
|
@ -4340,40 +4337,30 @@ export class AssistantService {
|
|||
nowIso: () => new Date().toISOString()
|
||||
});
|
||||
const sessionOrganizationScope = resolveSessionOrganizationScopeContext(userMessage, session.items);
|
||||
const finalizeAddressLaneResponse = (addressLane, effectiveAddressUserMessage, carryoverMeta = null, llmPreDecomposeMeta = null) => (0, assistantAddressLaneResponseAttemptRuntimeAdapter_1.runAssistantAddressLaneResponseAttemptRuntime)({
|
||||
sessionId,
|
||||
userMessage,
|
||||
effectiveAddressUserMessage,
|
||||
addressLane,
|
||||
carryoverMeta,
|
||||
llmPreDecomposeMeta,
|
||||
knownOrganizations: sessionOrganizationScope.knownOrganizations,
|
||||
activeOrganization: sessionOrganizationScope.activeOrganization,
|
||||
sanitizeOutgoingAssistantText,
|
||||
buildAddressDebugPayload,
|
||||
buildAddressFollowupOffer,
|
||||
mergeKnownOrganizations,
|
||||
toNonEmptyString,
|
||||
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)}`
|
||||
});
|
||||
const tryHandleLivingChat = async (modeDecision, addressRuntimeMeta = null) => (0, assistantLivingChatAttemptRuntimeAdapter_1.runAssistantLivingChatAttemptRuntime)({
|
||||
const addressRuntime = await (0, assistantAddressAttemptRuntimeAdapter_1.runAssistantAddressAttemptRuntime)({
|
||||
featureAssistantAddressQueryV1: config_1.FEATURE_ASSISTANT_ADDRESS_QUERY_V1,
|
||||
sessionId,
|
||||
userMessage,
|
||||
sessionItems: session.items,
|
||||
modeDecision,
|
||||
payload,
|
||||
sessionScope: {
|
||||
knownOrganizations: sessionOrganizationScope.knownOrganizations,
|
||||
selectedOrganization: sessionOrganizationScope.selectedOrganization,
|
||||
activeOrganization: sessionOrganizationScope.activeOrganization
|
||||
},
|
||||
addressRuntimeMeta,
|
||||
traceIdFactory: () => `chat-${(0, nanoid_1.nanoid)(10)}`,
|
||||
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,
|
||||
|
|
@ -4393,56 +4380,23 @@ export class AssistantService {
|
|||
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(),
|
||||
payload,
|
||||
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 ?? ""
|
||||
});
|
||||
let addressRuntimeMetaForDeep = null;
|
||||
const runAddressLaneAttempt = async (messageUsed, carryMeta, analysisDateHint) => (0, assistantAddressLaneAttemptRuntimeAdapter_1.runAssistantAddressLaneAttemptRuntime)({
|
||||
messageUsed,
|
||||
carryMeta: carryMeta ?? null,
|
||||
analysisDateHint: analysisDateHint ?? null,
|
||||
activeOrganization: sessionOrganizationScope.activeOrganization,
|
||||
mergeFollowupContextWithOrganizationScope,
|
||||
runAddressQueryTryHandle: (laneMessageUsed, options) => this.addressQueryService.tryHandle(laneMessageUsed, options)
|
||||
});
|
||||
const addressRuntime = await (0, assistantAddressRuntimeAdapter_1.runAssistantAddressRuntime)({
|
||||
featureAssistantAddressQueryV1: config_1.FEATURE_ASSISTANT_ADDRESS_QUERY_V1,
|
||||
sessionId,
|
||||
userMessage,
|
||||
sessionItems: session.items,
|
||||
llmProvider: payload?.llmProvider,
|
||||
useMock: Boolean(payload.useMock),
|
||||
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,
|
||||
payloadContextPeriodHint: payload?.context?.period_hint,
|
||||
compactWhitespace,
|
||||
runAddressLaneAttempt,
|
||||
isRetryableAddressLimitedResult,
|
||||
finalizeAddressLaneResponse,
|
||||
tryHandleLivingChat: (modeDecision, runtimeMeta) => tryHandleLivingChat(modeDecision, runtimeMeta),
|
||||
logEvent: (payload) => (0, log_1.logJson)(payload),
|
||||
nowIso: () => new Date().toISOString()
|
||||
});
|
||||
addressRuntimeMetaForDeep = addressRuntime.addressRuntimeMetaForDeep;
|
||||
const addressRuntimeMetaForDeep = addressRuntime.addressRuntimeMetaForDeep;
|
||||
if (addressRuntime.handled && addressRuntime.response) {
|
||||
return addressRuntime.response;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,196 @@
|
|||
import { describe, expect, it, vi } from "vitest";
|
||||
import { runAssistantAddressAttemptRuntime } from "../src/services/assistantAddressAttemptRuntimeAdapter";
|
||||
|
||||
function buildInput(overrides: Record<string, unknown> = {}) {
|
||||
return {
|
||||
featureAssistantAddressQueryV1: true,
|
||||
sessionId: "asst-1",
|
||||
userMessage: "where are overdue docs",
|
||||
sessionItems: [],
|
||||
payload: {
|
||||
llmProvider: "openai",
|
||||
useMock: 1,
|
||||
context: {
|
||||
period_hint: "2020-07-31"
|
||||
},
|
||||
apiKey: "key",
|
||||
model: "gpt-5",
|
||||
baseUrl: "http://localhost"
|
||||
},
|
||||
sessionScope: {
|
||||
knownOrganizations: ["Org A"],
|
||||
selectedOrganization: "Org A",
|
||||
activeOrganization: "Org A"
|
||||
},
|
||||
featureAddressLlmPredecomposeV1: true,
|
||||
runAddressLlmPreDecompose: async () => ({}),
|
||||
buildAddressLlmPredecomposeContractV1: () => ({}),
|
||||
sanitizeAddressMessageForFallback: (value: string) => value,
|
||||
toNonEmptyString: (value: unknown) =>
|
||||
typeof value === "string" && value.trim().length > 0 ? value.trim() : null,
|
||||
resolveAddressFollowupCarryoverContext: () => null,
|
||||
resolveAssistantOrchestrationDecision: () => ({ mode: "address_query", runAddressLane: true }),
|
||||
buildAddressDialogContinuationContractV2: () => ({}),
|
||||
runtimeAnalysisContextAsOfDate: "2020-07-31",
|
||||
compactWhitespace: (value: string) => String(value ?? "").replace(/\s+/g, " ").trim(),
|
||||
mergeFollowupContextWithOrganizationScope: (followupContext: Record<string, unknown> | null) =>
|
||||
followupContext,
|
||||
runAddressQueryTryHandle: async () => ({ response_type: "READY" }),
|
||||
isRetryableAddressLimitedResult: () => false,
|
||||
mergeKnownOrganizations: (knownOrganizations: string[], selectedOrganization: string | null) => ({
|
||||
knownOrganizations,
|
||||
selectedOrganization
|
||||
}),
|
||||
hasAssistantDataScopeMetaQuestionSignal: () => false,
|
||||
shouldHandleAsAssistantCapabilityMetaQuery: () => false,
|
||||
hasDestructiveDataActionSignal: () => false,
|
||||
hasDangerOrCoercionSignal: () => false,
|
||||
hasOperationalAdminActionRequestSignal: () => false,
|
||||
hasOrganizationFactLookupSignal: () => false,
|
||||
hasOrganizationFactFollowupSignal: () => false,
|
||||
shouldEmitOrganizationSelectionReply: () => false,
|
||||
hasAssistantCapabilityQuestionSignal: () => false,
|
||||
resolveDataScopeProbe: () => null,
|
||||
applyScriptGuard: (chatText: string) => chatText,
|
||||
applyGroundingGuard: (guardInput: Record<string, unknown>) => guardInput,
|
||||
buildAssistantSafetyRefusalReply: () => "safety",
|
||||
buildAssistantDataScopeContractReply: () => "scope",
|
||||
buildAssistantOrganizationFactBoundaryReply: () => "boundary",
|
||||
buildAssistantDataScopeSelectionReply: () => "selection",
|
||||
buildAssistantOperationalBoundaryReply: () => "operational",
|
||||
buildAssistantCapabilityContractReply: () => "capability",
|
||||
chatClient: {} as any,
|
||||
loadAssistantCanonExcerpt: () => "",
|
||||
sanitizeOutgoingAssistantText: (value: unknown, fallback = "") => {
|
||||
const text = typeof value === "string" ? value.trim() : "";
|
||||
return text || fallback;
|
||||
},
|
||||
defaultModel: "gpt-5",
|
||||
defaultBaseUrl: "http://localhost",
|
||||
defaultApiKey: "key",
|
||||
buildAddressDebugPayload: () => ({}),
|
||||
buildAddressFollowupOffer: () => null,
|
||||
appendItem: () => {},
|
||||
getSession: () => ({
|
||||
session_id: "asst-1",
|
||||
updated_at: "",
|
||||
items: [],
|
||||
investigation_state: null
|
||||
}),
|
||||
persistSession: () => {},
|
||||
cloneConversation: (items: unknown[]) => items,
|
||||
logEvent: () => {},
|
||||
messageIdFactory: () => "msg-111",
|
||||
nowIso: () => "2026-01-01T00:00:00.000Z",
|
||||
...overrides
|
||||
} as any;
|
||||
}
|
||||
|
||||
describe("assistant address attempt runtime adapter", () => {
|
||||
it("wires lane, response and living-chat attempt runtimes through one boundary", async () => {
|
||||
const runAddressLaneAttemptRuntime = vi.fn(async () => ({
|
||||
response_type: "READY"
|
||||
}));
|
||||
const runAddressLaneResponseAttemptRuntime = vi.fn(() => ({
|
||||
kind: "address"
|
||||
}));
|
||||
const runLivingChatAttemptRuntime = vi.fn(async () => ({
|
||||
kind: "chat"
|
||||
}));
|
||||
const runAddressRuntime = vi.fn(async (input: any) => {
|
||||
const laneResult = await input.runAddressLaneAttempt(
|
||||
"lane-message",
|
||||
{ followupContext: { previous_intent: "docs_by_counterparty" } },
|
||||
"2020-08-31"
|
||||
);
|
||||
expect(laneResult).toEqual({ response_type: "READY" });
|
||||
|
||||
const livingChatResult = await input.tryHandleLivingChat(
|
||||
{ mode: "chat", reason: "living_chat_signal_detected" },
|
||||
{ source: "address_runtime" }
|
||||
);
|
||||
expect(livingChatResult).toEqual({ kind: "chat" });
|
||||
|
||||
const response = input.finalizeAddressLaneResponse(
|
||||
{ reply_text: "address reply", reply_type: "factual_with_explanation" },
|
||||
"lane-message",
|
||||
{ previousReplyType: "partial_coverage" },
|
||||
{ mode: "supported", confidence: "high" }
|
||||
);
|
||||
expect(response).toEqual({ kind: "address" });
|
||||
|
||||
return {
|
||||
handled: true,
|
||||
response: { ok: true, lane: "address" },
|
||||
addressRuntimeMetaForDeep: { source: "address_runtime" }
|
||||
};
|
||||
});
|
||||
|
||||
const runtime = await runAssistantAddressAttemptRuntime(
|
||||
buildInput({
|
||||
runAddressRuntime,
|
||||
runAddressLaneAttemptRuntime,
|
||||
runAddressLaneResponseAttemptRuntime,
|
||||
runLivingChatAttemptRuntime
|
||||
})
|
||||
);
|
||||
|
||||
expect(runtime).toEqual({
|
||||
handled: true,
|
||||
response: { ok: true, lane: "address" },
|
||||
addressRuntimeMetaForDeep: { source: "address_runtime" }
|
||||
});
|
||||
expect(runAddressRuntime).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
llmProvider: "openai",
|
||||
useMock: true,
|
||||
payloadContextPeriodHint: "2020-07-31"
|
||||
})
|
||||
);
|
||||
expect(runAddressLaneAttemptRuntime).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
messageUsed: "lane-message",
|
||||
analysisDateHint: "2020-08-31",
|
||||
activeOrganization: "Org A"
|
||||
})
|
||||
);
|
||||
expect(runLivingChatAttemptRuntime).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
sessionId: "asst-1",
|
||||
sessionScope: expect.objectContaining({
|
||||
selectedOrganization: "Org A"
|
||||
})
|
||||
})
|
||||
);
|
||||
expect(runAddressLaneResponseAttemptRuntime).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
sessionId: "asst-1",
|
||||
effectiveAddressUserMessage: "lane-message",
|
||||
knownOrganizations: ["Org A"]
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it("passes empty payload fields to address runtime without breaking defaults", async () => {
|
||||
const runAddressRuntime = vi.fn(async () => ({
|
||||
handled: false,
|
||||
response: null,
|
||||
addressRuntimeMetaForDeep: null
|
||||
}));
|
||||
|
||||
await runAssistantAddressAttemptRuntime(
|
||||
buildInput({
|
||||
payload: {},
|
||||
runAddressRuntime
|
||||
})
|
||||
);
|
||||
|
||||
expect(runAddressRuntime).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
llmProvider: undefined,
|
||||
useMock: false,
|
||||
payloadContextPeriodHint: undefined
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,4 +1,64 @@
|
|||
[
|
||||
{
|
||||
"generation_id": "gen-mnte8abx-ax3v3tr",
|
||||
"created_at": "2026-04-10T21:03:44.205Z",
|
||||
"mode": "qwen_seed",
|
||||
"count": 10,
|
||||
"domain": null,
|
||||
"questions": [
|
||||
"Покажи контрагентов с максимальными долгами, которые уже больше месяца не платят, и проверь, нет ли у них непроверенных авансовых отгрузок.",
|
||||
"Где по покупателям висят заказы на конец месяца, но денег за них нет - требует ручной сверки?",
|
||||
"Посмотри контрагентов, где сальдо не совпадает с актом сверки, и уточни, кого нужно уже непременно запросить справку по этой разнице.",
|
||||
"Какие авансы давно остались висящими без закрытия - их пора либо отменять, либо перекладывать на счета реальных поставок?",
|
||||
"Где у нас документы есть, но нет денег за них, и это уже выглядит как серьезная задолженность контрагента?",
|
||||
"Проверь контрагентов с максимальными долгами - нет ли среди них тех, кто просто не закрыл накладные или оставил их без оплаты?",
|
||||
"Какие реализации зависли на конец периода и могут портить выручку, если не проверять заранее?",
|
||||
"Покажи контрагентов с максимальными долгами и уточни, нет ли среди них тех, кто просто игнорирует наши накладные.",
|
||||
"Какие поставщики уже больше месяца не закрывают свои счета - это требует ручной проверки?",
|
||||
"Проверь зависшие авансы и уточни, можно ли их перепривязать на текущие отгрузки или пора списывать как нереальные?"
|
||||
],
|
||||
"generated_by": "manual_reviewer",
|
||||
"saved_case_set_file": "assistant_autogen_qwen_seed_20260410210344_gen-mnte8abx-ax3v3tr.json",
|
||||
"context": {
|
||||
"llm_provider": "local",
|
||||
"model": "Qwen2.5 14B Instruct 1M",
|
||||
"assistant_prompt_version": "address_query_runtime_v1",
|
||||
"decomposition_prompt_version": "normalizer_v2_0_2",
|
||||
"prompt_fingerprint": "Ты semantic-normalizer для бухгалтерского ассистента NDC.\nТвоя роль: только нормализация запроса пользователя в строгий JSON-контракт.\n\nЖесткие правила:\n1) Не давай бухгалтерский ответ по сути вопроса.\n2) Возвращай только JSON без markdown и пояснений.\n3) JSON обязан соответствовать переданной schema normalized_query_v1.\n4) Если период не указан, не выдумывай его; отмечай ambiguity.\n5) Для цепочек документов/проводок/оплат поднимай causal и cross-entity признаки.\n6) Для точечного object trace (номер/строка/ref) поднимай needs_exact_object_trace=true.\n7) Используй терминологию NDC.\nYou are semantic-normalizer for accounting assistant NDC.\nReturn strict JSON only, no markdown, no comments.\n\nTarget schema: normalized_query_v2_0_2.\n\nCore behavior (v2.0.2):\n1. Decompose message into semantic fragments.\n2. Classify fragment domain relevance and business scope.\n3. Fill route-critical flags and ",
|
||||
"autogen_personality_id": "general",
|
||||
"autogen_personality_prompt": "Генерируй реалистичные живые вопросы бухгалтера по 1С. Добавляй разговорные формулировки и опечатки, но сохраняй бизнес-смысл. акцент на контрагентов, долги нсд, счета, общий вывод по компании - контрагенты, заказчикам, скока денег кто принес и какие остатки по счетам, поиск документов, сальдо, банковские операции, незакрытые договора, документы по договорам, долги, Активность заказчиков по периодам, Поставщики и выплаты"
|
||||
}
|
||||
},
|
||||
{
|
||||
"generation_id": "gen-mnte6y9p-4v1kfbw",
|
||||
"created_at": "2026-04-10T21:02:41.918Z",
|
||||
"mode": "qwen_seed",
|
||||
"count": 10,
|
||||
"domain": null,
|
||||
"questions": [
|
||||
"Какие поставщики пока не закрыли взаиморасчёты на конец месяца и это выглядит как серьёзная проблема, а не просто задержка?",
|
||||
"Где у нас висят покупатели 'грузили - денег нет - закрытия нет' и кто из них требует ручной проверки уже сейчас?",
|
||||
"Покажи контрагентов с вероятным несоответствием сальдо, если мы запросим их акт сверки прямо сейчас.",
|
||||
"Где у нас есть оплаты, но документы для закрытия взаиморасчётов всё ещё не пришли?",
|
||||
"Какие контрагенты имеют документы, но нет нормального закрытия по оплатам?",
|
||||
"Есть ли зависшие авансы, которые давно нужно перепроверить или закрыть?",
|
||||
"Какие реализации на конец периода выглядят так, будто они зависли и могут испортить картину по выручке?",
|
||||
"Где у нас отгрузки с проблемами не только в оплате, но и в самой связке документов?",
|
||||
"Кто из поставщиков активно работает с нами последнее время и сколько денег принесли за последние 3 месяца?",
|
||||
"Какие незакрытые договора есть на данный момент и что связано с ними по документам, долги и оплаты?"
|
||||
],
|
||||
"generated_by": "manual_reviewer",
|
||||
"saved_case_set_file": "assistant_autogen_qwen_seed_20260410210241_gen-mnte6y9p-4v1kfbw.json",
|
||||
"context": {
|
||||
"llm_provider": "local",
|
||||
"model": "Qwen2.5 14B Instruct 1M",
|
||||
"assistant_prompt_version": "address_query_runtime_v1",
|
||||
"decomposition_prompt_version": "normalizer_v2_0_2",
|
||||
"prompt_fingerprint": "Ты semantic-normalizer для бухгалтерского ассистента NDC.\nТвоя роль: только нормализация запроса пользователя в строгий JSON-контракт.\n\nЖесткие правила:\n1) Не давай бухгалтерский ответ по сути вопроса.\n2) Возвращай только JSON без markdown и пояснений.\n3) JSON обязан соответствовать переданной schema normalized_query_v1.\n4) Если период не указан, не выдумывай его; отмечай ambiguity.\n5) Для цепочек документов/проводок/оплат поднимай causal и cross-entity признаки.\n6) Для точечного object trace (номер/строка/ref) поднимай needs_exact_object_trace=true.\n7) Используй терминологию NDC.\nYou are semantic-normalizer for accounting assistant NDC.\nReturn strict JSON only, no markdown, no comments.\n\nTarget schema: normalized_query_v2_0_2.\n\nCore behavior (v2.0.2):\n1. Decompose message into semantic fragments.\n2. Classify fragment domain relevance and business scope.\n3. Fill route-critical flags and ",
|
||||
"autogen_personality_id": "general",
|
||||
"autogen_personality_prompt": "Генерируй реалистичные живые вопросы бухгалтера по 1С. Добавляй разговорные формулировки и опечатки, но сохраняй бизнес-смысл. акцент на контрагентов, долги нсд, счета, общий вывод по компании - контрагенты, заказчикам, скока денег кто принес и какие остатки по счетам, поиск документов, сальдо, банковские операции, незакрытые договора, документы по договорам, долги, Активность заказчиков по периодам, Поставщики и выплаты"
|
||||
}
|
||||
},
|
||||
{
|
||||
"generation_id": "gen-mnsolawk-vugqyoc",
|
||||
"created_at": "2026-04-10T09:06:01.461Z",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,174 @@
|
|||
{
|
||||
"suite_id": "assistant_autogen_gen-mnte6y9p-4v1kfbw",
|
||||
"suite_version": "0.1.0",
|
||||
"schema_version": "assistant_autogen_suite_v0_1",
|
||||
"generated_at": "2026-04-10T21:02:41.918Z",
|
||||
"generation_id": "gen-mnte6y9p-4v1kfbw",
|
||||
"mode": "qwen_seed",
|
||||
"domain": null,
|
||||
"scenario_count": 10,
|
||||
"case_ids": [
|
||||
"AUTO-001",
|
||||
"AUTO-002",
|
||||
"AUTO-003",
|
||||
"AUTO-004",
|
||||
"AUTO-005",
|
||||
"AUTO-006",
|
||||
"AUTO-007",
|
||||
"AUTO-008",
|
||||
"AUTO-009",
|
||||
"AUTO-010"
|
||||
],
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "AUTO-001",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Какие поставщики пока не закрыли взаиморасчёты на конец месяца и это выглядит как серьёзная проблема, а не просто задержка?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-002",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Где у нас висят покупатели 'грузили - денег нет - закрытия нет' и кто из них требует ручной проверки уже сейчас?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-003",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Покажи контрагентов с вероятным несоответствием сальдо, если мы запросим их акт сверки прямо сейчас."
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-004",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Где у нас есть оплаты, но документы для закрытия взаиморасчётов всё ещё не пришли?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-005",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Какие контрагенты имеют документы, но нет нормального закрытия по оплатам?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-006",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Есть ли зависшие авансы, которые давно нужно перепроверить или закрыть?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-007",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Какие реализации на конец периода выглядят так, будто они зависли и могут испортить картину по выручке?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-008",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Где у нас отгрузки с проблемами не только в оплате, но и в самой связке документов?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-009",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Кто из поставщиков активно работает с нами последнее время и сколько денег принесли за последние 3 месяца?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-010",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Какие незакрытые договора есть на данный момент и что связано с ними по документам, долги и оплаты?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
{
|
||||
"suite_id": "assistant_autogen_gen-mnte8abx-ax3v3tr",
|
||||
"suite_version": "0.1.0",
|
||||
"schema_version": "assistant_autogen_suite_v0_1",
|
||||
"generated_at": "2026-04-10T21:03:44.205Z",
|
||||
"generation_id": "gen-mnte8abx-ax3v3tr",
|
||||
"mode": "qwen_seed",
|
||||
"domain": null,
|
||||
"scenario_count": 10,
|
||||
"case_ids": [
|
||||
"AUTO-001",
|
||||
"AUTO-002",
|
||||
"AUTO-003",
|
||||
"AUTO-004",
|
||||
"AUTO-005",
|
||||
"AUTO-006",
|
||||
"AUTO-007",
|
||||
"AUTO-008",
|
||||
"AUTO-009",
|
||||
"AUTO-010"
|
||||
],
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "AUTO-001",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Покажи контрагентов с максимальными долгами, которые уже больше месяца не платят, и проверь, нет ли у них непроверенных авансовых отгрузок."
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-002",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Где по покупателям висят заказы на конец месяца, но денег за них нет - требует ручной сверки?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-003",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Посмотри контрагентов, где сальдо не совпадает с актом сверки, и уточни, кого нужно уже непременно запросить справку по этой разнице."
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-004",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Какие авансы давно остались висящими без закрытия - их пора либо отменять, либо перекладывать на счета реальных поставок?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-005",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Где у нас документы есть, но нет денег за них, и это уже выглядит как серьезная задолженность контрагента?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-006",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Проверь контрагентов с максимальными долгами - нет ли среди них тех, кто просто не закрыл накладные или оставил их без оплаты?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-007",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Какие реализации зависли на конец периода и могут портить выручку, если не проверять заранее?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-008",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Покажи контрагентов с максимальными долгами и уточни, нет ли среди них тех, кто просто игнорирует наши накладные."
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-009",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Какие поставщики уже больше месяца не закрывают свои счета - это требует ручной проверки?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-010",
|
||||
"scenario_tag": "qwen_seed_general",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Проверь зависшие авансы и уточни, можно ли их перепривязать на текущие отгрузки или пора списывать как нереальные?"
|
||||
}
|
||||
],
|
||||
"expected_hints": {
|
||||
"expected_reply_type": null,
|
||||
"expected_degraded_to": null
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
{
|
||||
"suite_id": "assistant_autogen_runtime_job-bOkyd627Q3",
|
||||
"suite_version": "0.1.0",
|
||||
"schema_version": "assistant_autogen_runtime_v0_1",
|
||||
"scenario_count": 10,
|
||||
"case_ids": [
|
||||
"AUTO-001",
|
||||
"AUTO-002",
|
||||
"AUTO-003",
|
||||
"AUTO-004",
|
||||
"AUTO-005",
|
||||
"AUTO-006",
|
||||
"AUTO-007",
|
||||
"AUTO-008",
|
||||
"AUTO-009",
|
||||
"AUTO-010"
|
||||
],
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "AUTO-001",
|
||||
"scenario_tag": "autogen_runtime",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Покажи контрагентов с максимальными долгами, которые уже больше месяца не платят, и проверь, нет ли у них непроверенных авансовых отгрузок."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-002",
|
||||
"scenario_tag": "autogen_runtime",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Где по покупателям висят заказы на конец месяца, но денег за них нет - требует ручной сверки?"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-003",
|
||||
"scenario_tag": "autogen_runtime",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Посмотри контрагентов, где сальдо не совпадает с актом сверки, и уточни, кого нужно уже непременно запросить справку по этой разнице."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-004",
|
||||
"scenario_tag": "autogen_runtime",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Какие авансы давно остались висящими без закрытия - их пора либо отменять, либо перекладывать на счета реальных поставок?"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-005",
|
||||
"scenario_tag": "autogen_runtime",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Где у нас документы есть, но нет денег за них, и это уже выглядит как серьезная задолженность контрагента?"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-006",
|
||||
"scenario_tag": "autogen_runtime",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Проверь контрагентов с максимальными долгами - нет ли среди них тех, кто просто не закрыл накладные или оставил их без оплаты?"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-007",
|
||||
"scenario_tag": "autogen_runtime",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Какие реализации зависли на конец периода и могут портить выручку, если не проверять заранее?"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-008",
|
||||
"scenario_tag": "autogen_runtime",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Покажи контрагентов с максимальными долгами и уточни, нет ли среди них тех, кто просто игнорирует наши накладные."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-009",
|
||||
"scenario_tag": "autogen_runtime",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Какие поставщики уже больше месяца не закрывают свои счета - это требует ручной проверки?"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"case_id": "AUTO-010",
|
||||
"scenario_tag": "autogen_runtime",
|
||||
"question_type": "direct",
|
||||
"broadness_level": "medium",
|
||||
"turns": [
|
||||
{
|
||||
"user_message": "Проверь зависшие авансы и уточни, можно ли их перепривязать на текущие отгрузки или пора списывать как нереальные?"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue