ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Рефакторинг этапов 2.772.80 - Убрано as any из адресного response-runtime и добавил явную нормализацию перед финализацией / Убран cast в builderе deep-response composition
This commit is contained in:
parent
9f3749fd4a
commit
dedf193542
|
|
@ -1890,7 +1890,37 @@ Validation:
|
|||
- `assistantTurnRuntimeDepsAdapter.test.ts`
|
||||
- `assistantTurnAttemptRuntimeAdapter.test.ts`
|
||||
|
||||
Status: **In progress (Phase 2.1 + 2.2 + 2.3 + 2.4 + 2.5 + 2.6 + 2.7 + 2.8 + 2.9 + 2.10 + 2.11 + 2.12 + 2.13 + 2.14 + 2.15 + 2.16 + 2.17 + 2.18 + 2.19 + 2.20 + 2.21 + 2.22 + 2.23 + 2.24 + 2.25 + 2.26 + 2.27 + 2.28 + 2.29 + 2.30 + 2.31 + 2.32 + 2.33 + 2.34 + 2.35 + 2.36 + 2.37 + 2.38 + 2.39 + 2.40 + 2.41 + 2.42 + 2.43 + 2.44 + 2.45 + 2.46 + 2.47 + 2.48 + 2.49 + 2.50 + 2.51 + 2.52 + 2.53 + 2.54 + 2.55 + 2.56 + 2.57 + 2.58 + 2.59 + 2.60 + 2.61 + 2.62 + 2.63 + 2.64 + 2.65 + 2.66 + 2.67 + 2.68 + 2.69 + 2.70 + 2.71 + 2.72 + 2.73 + 2.74 + 2.75 + 2.76 completed)**
|
||||
Implemented in current pass (Phase 2.77 + 2.78 + 2.79 + 2.80):
|
||||
1. Removed unsafe casts from address lane response runtime finalization path:
|
||||
- `assistantAddressLaneResponseRuntimeAdapter.ts`
|
||||
- introduced explicit normalization for:
|
||||
- `replyType` (fallback-safe);
|
||||
- `carryoverMeta` extraction from followup context;
|
||||
- `llmPreDecomposeMeta` sparse contract mapping;
|
||||
- address debug payload handoff into finalize stage.
|
||||
2. Hardened deep response runtime bridge to packaging stage:
|
||||
- `assistantDeepTurnResponseRuntimeAdapter.ts`
|
||||
- replaced `as any` payload handoff with typed normalizers for:
|
||||
- execution plan;
|
||||
- runtime analysis context;
|
||||
- business scope resolution;
|
||||
- record/audit buckets;
|
||||
- address-runtime meta.
|
||||
3. Updated deep response runtime input builder to pass typed composition contract directly:
|
||||
- `assistantDeepTurnResponseRuntimeInputBuilder.ts`
|
||||
- removed composition cast in analysis->response mapping.
|
||||
|
||||
Validation:
|
||||
1. `npm run build` passed.
|
||||
2. Targeted response/address/deep pack passed:
|
||||
- `assistantAddressLaneResponseRuntimeAdapter.test.ts`
|
||||
- `assistantAddressLaneResponseAttemptRuntimeAdapter.test.ts`
|
||||
- `assistantDeepTurnResponseRuntimeInputBuilder.test.ts`
|
||||
- `assistantDeepTurnResponseRuntimeAdapter.test.ts`
|
||||
- `assistantDeepTurnResponseAttemptRuntimeAdapter.test.ts`
|
||||
- `assistantDeepTurnAttemptRuntimeAdapter.test.ts`
|
||||
|
||||
Status: **In progress (Phase 2.1 + 2.2 + 2.3 + 2.4 + 2.5 + 2.6 + 2.7 + 2.8 + 2.9 + 2.10 + 2.11 + 2.12 + 2.13 + 2.14 + 2.15 + 2.16 + 2.17 + 2.18 + 2.19 + 2.20 + 2.21 + 2.22 + 2.23 + 2.24 + 2.25 + 2.26 + 2.27 + 2.28 + 2.29 + 2.30 + 2.31 + 2.32 + 2.33 + 2.34 + 2.35 + 2.36 + 2.37 + 2.38 + 2.39 + 2.40 + 2.41 + 2.42 + 2.43 + 2.44 + 2.45 + 2.46 + 2.47 + 2.48 + 2.49 + 2.50 + 2.51 + 2.52 + 2.53 + 2.54 + 2.55 + 2.56 + 2.57 + 2.58 + 2.59 + 2.60 + 2.61 + 2.62 + 2.63 + 2.64 + 2.65 + 2.66 + 2.67 + 2.68 + 2.69 + 2.70 + 2.71 + 2.72 + 2.73 + 2.74 + 2.75 + 2.76 + 2.77 + 2.78 + 2.79 + 2.80 completed)**
|
||||
|
||||
## Stage 3 (P2): Hybrid Semantic Layer (LLM + Deterministic Guards)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,128 @@
|
|||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.runAssistantAddressLaneResponseRuntime = runAssistantAddressLaneResponseRuntime;
|
||||
const assistantAddressTurnFinalizeRuntimeAdapter_1 = require("./assistantAddressTurnFinalizeRuntimeAdapter");
|
||||
function toRecordObject(value) {
|
||||
if (!value || typeof value !== "object") {
|
||||
return null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function toNullableString(value) {
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : null;
|
||||
}
|
||||
function toNullableBoolean(value) {
|
||||
if (typeof value === "boolean") {
|
||||
return value;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
function normalizeAddressReplyType(value) {
|
||||
return value === "factual" || value === "partial_coverage" ? value : "partial_coverage";
|
||||
}
|
||||
function normalizeAddressLaneDebug(value) {
|
||||
return (toRecordObject(value) ?? {});
|
||||
}
|
||||
function normalizeCarryoverMeta(value) {
|
||||
const source = toRecordObject(value);
|
||||
if (!source) {
|
||||
return null;
|
||||
}
|
||||
const followupContext = toRecordObject(source.followupContext);
|
||||
const previousAddressIntent = toNullableString(source.previousAddressIntent) ??
|
||||
toNullableString(followupContext?.previous_intent);
|
||||
const previousAddressAnchor = toNullableString(source.previousAddressAnchor) ??
|
||||
toNullableString(followupContext?.previous_anchor);
|
||||
if (!previousAddressIntent && !previousAddressAnchor) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
previousAddressIntent,
|
||||
previousAddressAnchor
|
||||
};
|
||||
}
|
||||
function normalizeLlmPreDecomposeMeta(value) {
|
||||
const source = toRecordObject(value);
|
||||
if (!source) {
|
||||
return null;
|
||||
}
|
||||
const dialogContinuationContractRaw = toRecordObject(source.dialogContinuationContract);
|
||||
const addressRetryAuditRaw = toRecordObject(source.addressRetryAudit);
|
||||
const predecomposeContractRaw = toRecordObject(source.predecomposeContract);
|
||||
const predecomposePeriodRaw = toRecordObject(predecomposeContractRaw?.period);
|
||||
const normalized = {};
|
||||
const attempted = toNullableBoolean(source.attempted);
|
||||
if (attempted !== undefined)
|
||||
normalized.attempted = attempted;
|
||||
const applied = toNullableBoolean(source.applied);
|
||||
if (applied !== undefined)
|
||||
normalized.applied = applied;
|
||||
const provider = toNullableString(source.provider);
|
||||
if (provider)
|
||||
normalized.provider = provider;
|
||||
const traceId = toNullableString(source.traceId);
|
||||
if (traceId)
|
||||
normalized.traceId = traceId;
|
||||
const reason = toNullableString(source.reason);
|
||||
if (reason)
|
||||
normalized.reason = reason;
|
||||
const fallbackRuleHit = toNullableString(source.fallbackRuleHit);
|
||||
if (fallbackRuleHit)
|
||||
normalized.fallbackRuleHit = fallbackRuleHit;
|
||||
const sanitizedUserMessage = toNullableString(source.sanitizedUserMessage);
|
||||
if (sanitizedUserMessage)
|
||||
normalized.sanitizedUserMessage = sanitizedUserMessage;
|
||||
const toolGateDecision = toNullableString(source.toolGateDecision);
|
||||
if (toolGateDecision)
|
||||
normalized.toolGateDecision = toolGateDecision;
|
||||
const toolGateReason = toNullableString(source.toolGateReason);
|
||||
if (toolGateReason)
|
||||
normalized.toolGateReason = toolGateReason;
|
||||
if (dialogContinuationContractRaw) {
|
||||
const decision = toNullableString(dialogContinuationContractRaw.decision);
|
||||
const targetIntent = toNullableString(dialogContinuationContractRaw.target_intent);
|
||||
if (decision || targetIntent) {
|
||||
normalized.dialogContinuationContract = {
|
||||
decision,
|
||||
target_intent: targetIntent
|
||||
};
|
||||
}
|
||||
}
|
||||
if (addressRetryAuditRaw) {
|
||||
const retryAttempted = toNullableBoolean(addressRetryAuditRaw.attempted);
|
||||
const retryReason = toNullableString(addressRetryAuditRaw.reason);
|
||||
const initialLimitedCategory = toNullableString(addressRetryAuditRaw.initial_limited_category);
|
||||
const retryResultCategory = toNullableString(addressRetryAuditRaw.retry_result_category);
|
||||
if (retryAttempted !== undefined ||
|
||||
retryReason ||
|
||||
initialLimitedCategory ||
|
||||
retryResultCategory) {
|
||||
normalized.addressRetryAudit = {
|
||||
attempted: retryAttempted,
|
||||
reason: retryReason,
|
||||
initial_limited_category: initialLimitedCategory,
|
||||
retry_result_category: retryResultCategory
|
||||
};
|
||||
}
|
||||
}
|
||||
if (predecomposeContractRaw) {
|
||||
const intent = toNullableString(predecomposeContractRaw.intent);
|
||||
const aggregationProfile = toNullableString(predecomposeContractRaw.aggregation_profile);
|
||||
const periodScope = toNullableString(predecomposePeriodRaw?.scope);
|
||||
if (intent || aggregationProfile || periodScope) {
|
||||
normalized.predecomposeContract = {
|
||||
intent,
|
||||
aggregation_profile: aggregationProfile,
|
||||
period: periodScope ? { scope: periodScope } : null
|
||||
};
|
||||
}
|
||||
}
|
||||
const hasUsefulField = Object.values(normalized).some((item) => item !== undefined && item !== null);
|
||||
return hasUsefulField ? normalized : null;
|
||||
}
|
||||
function runAssistantAddressLaneResponseRuntime(input) {
|
||||
const finalizeAddressTurnSafe = input.finalizeAddressTurn ?? assistantAddressTurnFinalizeRuntimeAdapter_1.finalizeAssistantAddressTurn;
|
||||
const safeAddressReply = input.sanitizeOutgoingAssistantText(input.addressLane.reply_text);
|
||||
|
|
@ -27,11 +149,11 @@ function runAssistantAddressLaneResponseRuntime(input) {
|
|||
userMessage: input.userMessage,
|
||||
effectiveAddressUserMessage: input.effectiveAddressUserMessage,
|
||||
assistantReply: safeAddressReply,
|
||||
replyType: input.addressLane.reply_type,
|
||||
addressLaneDebug: (input.addressLane.debug ?? null),
|
||||
replyType: normalizeAddressReplyType(input.addressLane.reply_type),
|
||||
addressLaneDebug: normalizeAddressLaneDebug(input.addressLane.debug),
|
||||
debug,
|
||||
carryoverMeta: (input.carryoverMeta ?? null),
|
||||
llmPreDecomposeMeta: (input.llmPreDecomposeMeta ?? null),
|
||||
carryoverMeta: normalizeCarryoverMeta(input.carryoverMeta),
|
||||
llmPreDecomposeMeta: normalizeLlmPreDecomposeMeta(input.llmPreDecomposeMeta),
|
||||
appendItem: input.appendItem,
|
||||
getSession: input.getSession,
|
||||
persistSession: input.persistSession,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,94 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||
exports.runAssistantDeepTurnResponseRuntime = runAssistantDeepTurnResponseRuntime;
|
||||
const assistantDeepTurnPackagingRuntimeAdapter_1 = require("./assistantDeepTurnPackagingRuntimeAdapter");
|
||||
const assistantDeepTurnFinalizeRuntimeAdapter_1 = require("./assistantDeepTurnFinalizeRuntimeAdapter");
|
||||
function toRecordObject(value) {
|
||||
if (!value || typeof value !== "object") {
|
||||
return null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function toNullableString(value) {
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : null;
|
||||
}
|
||||
function toStringArray(value) {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
}
|
||||
return value
|
||||
.map((item) => (typeof item === "string" ? item.trim() : ""))
|
||||
.filter((item) => item.length > 0);
|
||||
}
|
||||
function toSnapshotMode(value) {
|
||||
return value === "force_snapshot" || value === "force_live" ? value : "auto";
|
||||
}
|
||||
function normalizeExecutionPlan(value) {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
}
|
||||
return value.map((item, index) => {
|
||||
const source = toRecordObject(item);
|
||||
return {
|
||||
fragment_id: toNullableString(source?.fragment_id) ?? `fragment_${index + 1}`,
|
||||
requirement_ids: toStringArray(source?.requirement_ids),
|
||||
route: toNullableString(source?.route) ?? "unknown_route",
|
||||
should_execute: Boolean(source?.should_execute),
|
||||
no_route_reason: toNullableString(source?.no_route_reason),
|
||||
clarification_reason: toNullableString(source?.clarification_reason)
|
||||
};
|
||||
});
|
||||
}
|
||||
function normalizeRecordArray(value) {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
}
|
||||
return value
|
||||
.map((item) => toRecordObject(item))
|
||||
.filter((item) => Boolean(item));
|
||||
}
|
||||
function normalizeRecord(value) {
|
||||
return toRecordObject(value) ?? {};
|
||||
}
|
||||
function normalizeRuntimeAnalysisContext(value) {
|
||||
const source = toRecordObject(value);
|
||||
return {
|
||||
active: Boolean(source?.active),
|
||||
as_of_date: toNullableString(source?.as_of_date),
|
||||
period_from: toNullableString(source?.period_from),
|
||||
period_to: toNullableString(source?.period_to),
|
||||
source: toNullableString(source?.source),
|
||||
snapshot_mode: toSnapshotMode(source?.snapshot_mode)
|
||||
};
|
||||
}
|
||||
function normalizeBusinessScopeResolution(value) {
|
||||
const source = toRecordObject(value);
|
||||
return {
|
||||
business_scope_raw: toStringArray(source?.business_scope_raw),
|
||||
business_scope_resolved: toStringArray(source?.business_scope_resolved),
|
||||
company_grounding_applied: Boolean(source?.company_grounding_applied),
|
||||
scope_resolution_reason: toStringArray(source?.scope_resolution_reason)
|
||||
};
|
||||
}
|
||||
function normalizeAddressRuntimeMetaForDeep(value) {
|
||||
const source = toRecordObject(value);
|
||||
if (!source) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
attempted: typeof source.attempted === "boolean" ? source.attempted : undefined,
|
||||
applied: typeof source.applied === "boolean" ? source.applied : undefined,
|
||||
reason: toNullableString(source.reason),
|
||||
provider: toNullableString(source.provider),
|
||||
fallbackRuleHit: toNullableString(source.fallbackRuleHit),
|
||||
toolGateDecision: toNullableString(source.toolGateDecision),
|
||||
toolGateReason: toNullableString(source.toolGateReason),
|
||||
predecomposeContract: toRecordObject(source.predecomposeContract),
|
||||
orchestrationContract: toRecordObject(source.orchestrationContract)
|
||||
};
|
||||
}
|
||||
function runAssistantDeepTurnResponseRuntime(input) {
|
||||
const runPackagingRuntimeSafe = input.runPackagingRuntime ?? assistantDeepTurnPackagingRuntimeAdapter_1.runAssistantDeepTurnPackagingRuntime;
|
||||
const runFinalizeDeepTurnSafe = input.runFinalizeDeepTurn ?? assistantDeepTurnFinalizeRuntimeAdapter_1.finalizeAssistantDeepTurn;
|
||||
|
|
@ -14,33 +102,33 @@ function runAssistantDeepTurnResponseRuntime(input) {
|
|||
normalized: input.normalized,
|
||||
normalizedQuestion: input.normalizedQuestion,
|
||||
routeSummary: input.routeSummary,
|
||||
executionPlan: input.executionPlan,
|
||||
executionPlan: normalizeExecutionPlan(input.executionPlan),
|
||||
requirementExtractionRequirements: input.requirementExtractionRequirements,
|
||||
coverageEvaluationRequirements: input.coverageEvaluationRequirements,
|
||||
coverageReport: input.coverageReport,
|
||||
groundingCheck: input.groundingCheck,
|
||||
retrievalCalls: input.retrievalCalls,
|
||||
retrievalResultsRaw: input.retrievalResultsRaw,
|
||||
retrievalCalls: normalizeRecordArray(input.retrievalCalls),
|
||||
retrievalResultsRaw: Array.isArray(input.retrievalResultsRaw) ? input.retrievalResultsRaw : [],
|
||||
retrievalResults: input.retrievalResults,
|
||||
questionTypeClass: input.questionTypeClass,
|
||||
companyAnchors: input.companyAnchors,
|
||||
runtimeAnalysisContext: input.runtimeAnalysisContext,
|
||||
businessScopeResolution: input.businessScopeResolution,
|
||||
temporalGuard: input.temporalGuard,
|
||||
polarityAudit: input.polarityAudit,
|
||||
claimAnchorAudit: input.claimAnchorAudit,
|
||||
runtimeAnalysisContext: normalizeRuntimeAnalysisContext(input.runtimeAnalysisContext),
|
||||
businessScopeResolution: normalizeBusinessScopeResolution(input.businessScopeResolution),
|
||||
temporalGuard: normalizeRecord(input.temporalGuard),
|
||||
polarityAudit: normalizeRecord(input.polarityAudit),
|
||||
claimAnchorAudit: normalizeRecord(input.claimAnchorAudit),
|
||||
targetedEvidenceAudit: input.targetedEvidenceAudit,
|
||||
evidenceAdmissibilityGateAudit: input.evidenceAdmissibilityGateAudit,
|
||||
rbpLiveRouteAudit: input.rbpLiveRouteAudit,
|
||||
faLiveRouteAudit: input.faLiveRouteAudit,
|
||||
groundedAnswerEligibilityGuard: input.groundedAnswerEligibilityGuard,
|
||||
rbpLiveRouteAudit: input.rbpLiveRouteAudit ?? null,
|
||||
faLiveRouteAudit: input.faLiveRouteAudit ?? null,
|
||||
groundedAnswerEligibilityGuard: normalizeRecord(input.groundedAnswerEligibilityGuard),
|
||||
followupStateUsage: input.followupStateUsage,
|
||||
followupApplied: input.followupApplied,
|
||||
composition: input.composition,
|
||||
featureContractsV11: input.featureContractsV11,
|
||||
featureAnswerPolicyV11: input.featureAnswerPolicyV11,
|
||||
previousInvestigationState: input.previousInvestigationState ?? null,
|
||||
addressRuntimeMetaForDeep: input.addressRuntimeMetaForDeep,
|
||||
addressRuntimeMetaForDeep: normalizeAddressRuntimeMetaForDeep(input.addressRuntimeMetaForDeep),
|
||||
extractDroppedIntentSegments: input.extractDroppedIntentSegments,
|
||||
buildDebugRoutes: input.buildDebugRoutes,
|
||||
extractExecutionState: input.extractExecutionState,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import type { AssistantAddressLaneLike, AssistantAddressFollowupCarryoverLike } from "./assistantAddressLaneRuntimeAdapter";
|
||||
import type { AssistantMessageResponsePayload } from "../types/assistant";
|
||||
import type { AssistantMessageResponsePayload, AssistantReplyType } from "../types/assistant";
|
||||
import type { AddressExecutionDebug } from "../types/addressQuery";
|
||||
import {
|
||||
finalizeAssistantAddressTurn,
|
||||
type AddressCarryoverMetaLogInput,
|
||||
type AddressLlmPreDecomposeMetaLogInput,
|
||||
type FinalizeAssistantAddressTurnInput
|
||||
} from "./assistantAddressTurnFinalizeRuntimeAdapter";
|
||||
|
||||
|
|
@ -40,6 +43,137 @@ export interface RunAssistantAddressLaneResponseRuntimeOutput<ResponseType = Ass
|
|||
debug: Record<string, unknown>;
|
||||
}
|
||||
|
||||
function toRecordObject(value: unknown): Record<string, unknown> | null {
|
||||
if (!value || typeof value !== "object") {
|
||||
return null;
|
||||
}
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
function toNullableString(value: unknown): string | null {
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : null;
|
||||
}
|
||||
|
||||
function toNullableBoolean(value: unknown): boolean | undefined {
|
||||
if (typeof value === "boolean") {
|
||||
return value;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function normalizeAddressReplyType(value: unknown): AssistantReplyType {
|
||||
return value === "factual" || value === "partial_coverage" ? value : "partial_coverage";
|
||||
}
|
||||
|
||||
function normalizeAddressLaneDebug(value: unknown): AddressExecutionDebug {
|
||||
return (toRecordObject(value) ?? {}) as unknown as AddressExecutionDebug;
|
||||
}
|
||||
|
||||
function normalizeCarryoverMeta(value: unknown): AddressCarryoverMetaLogInput | null {
|
||||
const source = toRecordObject(value);
|
||||
if (!source) {
|
||||
return null;
|
||||
}
|
||||
const followupContext = toRecordObject(source.followupContext);
|
||||
const previousAddressIntent =
|
||||
toNullableString(source.previousAddressIntent) ??
|
||||
toNullableString(followupContext?.previous_intent);
|
||||
const previousAddressAnchor =
|
||||
toNullableString(source.previousAddressAnchor) ??
|
||||
toNullableString(followupContext?.previous_anchor);
|
||||
if (!previousAddressIntent && !previousAddressAnchor) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
previousAddressIntent,
|
||||
previousAddressAnchor
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeLlmPreDecomposeMeta(value: unknown): AddressLlmPreDecomposeMetaLogInput | null {
|
||||
const source = toRecordObject(value);
|
||||
if (!source) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const dialogContinuationContractRaw = toRecordObject(source.dialogContinuationContract);
|
||||
const addressRetryAuditRaw = toRecordObject(source.addressRetryAudit);
|
||||
const predecomposeContractRaw = toRecordObject(source.predecomposeContract);
|
||||
const predecomposePeriodRaw = toRecordObject(predecomposeContractRaw?.period);
|
||||
|
||||
const normalized: AddressLlmPreDecomposeMetaLogInput = {};
|
||||
|
||||
const attempted = toNullableBoolean(source.attempted);
|
||||
if (attempted !== undefined) normalized.attempted = attempted;
|
||||
const applied = toNullableBoolean(source.applied);
|
||||
if (applied !== undefined) normalized.applied = applied;
|
||||
const provider = toNullableString(source.provider);
|
||||
if (provider) normalized.provider = provider;
|
||||
const traceId = toNullableString(source.traceId);
|
||||
if (traceId) normalized.traceId = traceId;
|
||||
const reason = toNullableString(source.reason);
|
||||
if (reason) normalized.reason = reason;
|
||||
const fallbackRuleHit = toNullableString(source.fallbackRuleHit);
|
||||
if (fallbackRuleHit) normalized.fallbackRuleHit = fallbackRuleHit;
|
||||
const sanitizedUserMessage = toNullableString(source.sanitizedUserMessage);
|
||||
if (sanitizedUserMessage) normalized.sanitizedUserMessage = sanitizedUserMessage;
|
||||
const toolGateDecision = toNullableString(source.toolGateDecision);
|
||||
if (toolGateDecision) normalized.toolGateDecision = toolGateDecision;
|
||||
const toolGateReason = toNullableString(source.toolGateReason);
|
||||
if (toolGateReason) normalized.toolGateReason = toolGateReason;
|
||||
|
||||
if (dialogContinuationContractRaw) {
|
||||
const decision = toNullableString(dialogContinuationContractRaw.decision);
|
||||
const targetIntent = toNullableString(dialogContinuationContractRaw.target_intent);
|
||||
if (decision || targetIntent) {
|
||||
normalized.dialogContinuationContract = {
|
||||
decision,
|
||||
target_intent: targetIntent
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (addressRetryAuditRaw) {
|
||||
const retryAttempted = toNullableBoolean(addressRetryAuditRaw.attempted);
|
||||
const retryReason = toNullableString(addressRetryAuditRaw.reason);
|
||||
const initialLimitedCategory = toNullableString(addressRetryAuditRaw.initial_limited_category);
|
||||
const retryResultCategory = toNullableString(addressRetryAuditRaw.retry_result_category);
|
||||
if (
|
||||
retryAttempted !== undefined ||
|
||||
retryReason ||
|
||||
initialLimitedCategory ||
|
||||
retryResultCategory
|
||||
) {
|
||||
normalized.addressRetryAudit = {
|
||||
attempted: retryAttempted,
|
||||
reason: retryReason,
|
||||
initial_limited_category: initialLimitedCategory,
|
||||
retry_result_category: retryResultCategory
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (predecomposeContractRaw) {
|
||||
const intent = toNullableString(predecomposeContractRaw.intent);
|
||||
const aggregationProfile = toNullableString(predecomposeContractRaw.aggregation_profile);
|
||||
const periodScope = toNullableString(predecomposePeriodRaw?.scope);
|
||||
if (intent || aggregationProfile || periodScope) {
|
||||
normalized.predecomposeContract = {
|
||||
intent,
|
||||
aggregation_profile: aggregationProfile,
|
||||
period: periodScope ? { scope: periodScope } : null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const hasUsefulField = Object.values(normalized).some((item) => item !== undefined && item !== null);
|
||||
return hasUsefulField ? normalized : null;
|
||||
}
|
||||
|
||||
export function runAssistantAddressLaneResponseRuntime<ResponseType = AssistantMessageResponsePayload>(
|
||||
input: RunAssistantAddressLaneResponseRuntimeInput<ResponseType>
|
||||
): RunAssistantAddressLaneResponseRuntimeOutput<ResponseType> {
|
||||
|
|
@ -69,11 +203,11 @@ export function runAssistantAddressLaneResponseRuntime<ResponseType = AssistantM
|
|||
userMessage: input.userMessage,
|
||||
effectiveAddressUserMessage: input.effectiveAddressUserMessage,
|
||||
assistantReply: safeAddressReply,
|
||||
replyType: input.addressLane.reply_type as any,
|
||||
addressLaneDebug: (input.addressLane.debug ?? null) as any,
|
||||
replyType: normalizeAddressReplyType(input.addressLane.reply_type),
|
||||
addressLaneDebug: normalizeAddressLaneDebug(input.addressLane.debug),
|
||||
debug,
|
||||
carryoverMeta: (input.carryoverMeta ?? null) as any,
|
||||
llmPreDecomposeMeta: (input.llmPreDecomposeMeta ?? null) as any,
|
||||
carryoverMeta: normalizeCarryoverMeta(input.carryoverMeta),
|
||||
llmPreDecomposeMeta: normalizeLlmPreDecomposeMeta(input.llmPreDecomposeMeta),
|
||||
appendItem: input.appendItem,
|
||||
getSession: input.getSession,
|
||||
persistSession: input.persistSession,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { AssistantMessageResponsePayload, AssistantReplyType } from "../types/assistant";
|
||||
import type { AssistantMessageResponsePayload } from "../types/assistant";
|
||||
import type { NormalizeResponsePayload, RouteHintSummary } from "../types/normalizer";
|
||||
import type { InvestigationStateWithProblemUnits } from "../types/stage2ProblemUnits";
|
||||
import {
|
||||
|
|
@ -11,11 +11,6 @@ import {
|
|||
type FinalizeAssistantDeepTurnInput
|
||||
} from "./assistantDeepTurnFinalizeRuntimeAdapter";
|
||||
|
||||
type CompositionLike = {
|
||||
reply_type: AssistantReplyType;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
export interface RunAssistantDeepTurnResponseRuntimeInput {
|
||||
featureInvestigationStateV1: boolean;
|
||||
featureContractsV11: boolean;
|
||||
|
|
@ -32,14 +27,14 @@ export interface RunAssistantDeepTurnResponseRuntimeInput {
|
|||
normalizedQuestion: string;
|
||||
routeSummary: RouteHintSummary | null;
|
||||
executionPlan: unknown[];
|
||||
requirementExtractionRequirements: unknown[];
|
||||
coverageEvaluationRequirements: unknown[];
|
||||
coverageReport: unknown;
|
||||
groundingCheck: unknown;
|
||||
requirementExtractionRequirements: AssistantDeepTurnPackagingRuntimeInput["requirementExtractionRequirements"];
|
||||
coverageEvaluationRequirements: AssistantDeepTurnPackagingRuntimeInput["coverageEvaluationRequirements"];
|
||||
coverageReport: AssistantDeepTurnPackagingRuntimeInput["coverageReport"];
|
||||
groundingCheck: AssistantDeepTurnPackagingRuntimeInput["groundingCheck"];
|
||||
retrievalCalls: unknown[];
|
||||
retrievalResultsRaw: unknown[];
|
||||
retrievalResults: unknown[];
|
||||
questionTypeClass: string;
|
||||
retrievalResults: AssistantDeepTurnPackagingRuntimeInput["retrievalResults"];
|
||||
questionTypeClass: AssistantDeepTurnPackagingRuntimeInput["questionTypeClass"];
|
||||
companyAnchors: unknown;
|
||||
runtimeAnalysisContext: unknown;
|
||||
businessScopeResolution: unknown;
|
||||
|
|
@ -51,10 +46,10 @@ export interface RunAssistantDeepTurnResponseRuntimeInput {
|
|||
rbpLiveRouteAudit: unknown;
|
||||
faLiveRouteAudit: unknown;
|
||||
groundedAnswerEligibilityGuard: unknown;
|
||||
followupStateUsage: unknown;
|
||||
followupStateUsage: AssistantDeepTurnPackagingRuntimeInput["followupStateUsage"];
|
||||
followupApplied: boolean;
|
||||
composition: CompositionLike;
|
||||
previousInvestigationState: InvestigationStateWithProblemUnits | null | undefined;
|
||||
composition: AssistantDeepTurnPackagingRuntimeInput["composition"];
|
||||
previousInvestigationState: AssistantDeepTurnPackagingRuntimeInput["previousInvestigationState"];
|
||||
addressRuntimeMetaForDeep: unknown;
|
||||
extractDroppedIntentSegments: (normalizedPayload: NormalizeResponsePayload["normalized"]) => string[];
|
||||
buildDebugRoutes: (routeSummary: RouteHintSummary | null) => Array<Record<string, unknown>>;
|
||||
|
|
@ -78,6 +73,110 @@ export interface RunAssistantDeepTurnResponseRuntimeOutput {
|
|||
debug: Record<string, unknown>;
|
||||
}
|
||||
|
||||
function toRecordObject(value: unknown): Record<string, unknown> | null {
|
||||
if (!value || typeof value !== "object") {
|
||||
return null;
|
||||
}
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
function toNullableString(value: unknown): string | null {
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : null;
|
||||
}
|
||||
|
||||
function toStringArray(value: unknown): string[] {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
}
|
||||
return value
|
||||
.map((item) => (typeof item === "string" ? item.trim() : ""))
|
||||
.filter((item) => item.length > 0);
|
||||
}
|
||||
|
||||
function toSnapshotMode(value: unknown): "auto" | "force_snapshot" | "force_live" {
|
||||
return value === "force_snapshot" || value === "force_live" ? value : "auto";
|
||||
}
|
||||
|
||||
function normalizeExecutionPlan(value: unknown[]): AssistantDeepTurnPackagingRuntimeInput["executionPlan"] {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
}
|
||||
return value.map((item, index) => {
|
||||
const source = toRecordObject(item);
|
||||
return {
|
||||
fragment_id: toNullableString(source?.fragment_id) ?? `fragment_${index + 1}`,
|
||||
requirement_ids: toStringArray(source?.requirement_ids),
|
||||
route: toNullableString(source?.route) ?? "unknown_route",
|
||||
should_execute: Boolean(source?.should_execute),
|
||||
no_route_reason: toNullableString(source?.no_route_reason),
|
||||
clarification_reason: toNullableString(source?.clarification_reason)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeRecordArray(value: unknown[]): Array<Record<string, unknown>> {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
}
|
||||
return value
|
||||
.map((item) => toRecordObject(item))
|
||||
.filter((item): item is Record<string, unknown> => Boolean(item));
|
||||
}
|
||||
|
||||
function normalizeRecord(value: unknown): Record<string, unknown> {
|
||||
return toRecordObject(value) ?? {};
|
||||
}
|
||||
|
||||
function normalizeRuntimeAnalysisContext(
|
||||
value: unknown
|
||||
): AssistantDeepTurnPackagingRuntimeInput["runtimeAnalysisContext"] {
|
||||
const source = toRecordObject(value);
|
||||
return {
|
||||
active: Boolean(source?.active),
|
||||
as_of_date: toNullableString(source?.as_of_date),
|
||||
period_from: toNullableString(source?.period_from),
|
||||
period_to: toNullableString(source?.period_to),
|
||||
source: toNullableString(source?.source),
|
||||
snapshot_mode: toSnapshotMode(source?.snapshot_mode)
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeBusinessScopeResolution(
|
||||
value: unknown
|
||||
): AssistantDeepTurnPackagingRuntimeInput["businessScopeResolution"] {
|
||||
const source = toRecordObject(value);
|
||||
return {
|
||||
business_scope_raw: toStringArray(source?.business_scope_raw),
|
||||
business_scope_resolved: toStringArray(source?.business_scope_resolved),
|
||||
company_grounding_applied: Boolean(source?.company_grounding_applied),
|
||||
scope_resolution_reason: toStringArray(source?.scope_resolution_reason)
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeAddressRuntimeMetaForDeep(
|
||||
value: unknown
|
||||
): AssistantDeepTurnPackagingRuntimeInput["addressRuntimeMetaForDeep"] {
|
||||
const source = toRecordObject(value);
|
||||
if (!source) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
attempted: typeof source.attempted === "boolean" ? source.attempted : undefined,
|
||||
applied: typeof source.applied === "boolean" ? source.applied : undefined,
|
||||
reason: toNullableString(source.reason),
|
||||
provider: toNullableString(source.provider),
|
||||
fallbackRuleHit: toNullableString(source.fallbackRuleHit),
|
||||
toolGateDecision: toNullableString(source.toolGateDecision),
|
||||
toolGateReason: toNullableString(source.toolGateReason),
|
||||
predecomposeContract: toRecordObject(source.predecomposeContract),
|
||||
orchestrationContract: toRecordObject(source.orchestrationContract)
|
||||
};
|
||||
}
|
||||
|
||||
export function runAssistantDeepTurnResponseRuntime(
|
||||
input: RunAssistantDeepTurnResponseRuntimeInput
|
||||
): RunAssistantDeepTurnResponseRuntimeOutput {
|
||||
|
|
@ -92,33 +191,33 @@ export function runAssistantDeepTurnResponseRuntime(
|
|||
normalized: input.normalized,
|
||||
normalizedQuestion: input.normalizedQuestion,
|
||||
routeSummary: input.routeSummary,
|
||||
executionPlan: input.executionPlan as any,
|
||||
requirementExtractionRequirements: input.requirementExtractionRequirements as any,
|
||||
coverageEvaluationRequirements: input.coverageEvaluationRequirements as any,
|
||||
coverageReport: input.coverageReport as any,
|
||||
groundingCheck: input.groundingCheck as any,
|
||||
retrievalCalls: input.retrievalCalls as any,
|
||||
retrievalResultsRaw: input.retrievalResultsRaw as any,
|
||||
retrievalResults: input.retrievalResults as any,
|
||||
executionPlan: normalizeExecutionPlan(input.executionPlan),
|
||||
requirementExtractionRequirements: input.requirementExtractionRequirements,
|
||||
coverageEvaluationRequirements: input.coverageEvaluationRequirements,
|
||||
coverageReport: input.coverageReport,
|
||||
groundingCheck: input.groundingCheck,
|
||||
retrievalCalls: normalizeRecordArray(input.retrievalCalls),
|
||||
retrievalResultsRaw: Array.isArray(input.retrievalResultsRaw) ? input.retrievalResultsRaw : [],
|
||||
retrievalResults: input.retrievalResults,
|
||||
questionTypeClass: input.questionTypeClass,
|
||||
companyAnchors: input.companyAnchors,
|
||||
runtimeAnalysisContext: input.runtimeAnalysisContext as any,
|
||||
businessScopeResolution: input.businessScopeResolution as any,
|
||||
temporalGuard: input.temporalGuard as any,
|
||||
polarityAudit: input.polarityAudit as any,
|
||||
claimAnchorAudit: input.claimAnchorAudit as any,
|
||||
targetedEvidenceAudit: input.targetedEvidenceAudit as any,
|
||||
evidenceAdmissibilityGateAudit: input.evidenceAdmissibilityGateAudit as any,
|
||||
rbpLiveRouteAudit: input.rbpLiveRouteAudit as any,
|
||||
faLiveRouteAudit: input.faLiveRouteAudit as any,
|
||||
groundedAnswerEligibilityGuard: input.groundedAnswerEligibilityGuard as any,
|
||||
followupStateUsage: input.followupStateUsage as any,
|
||||
runtimeAnalysisContext: normalizeRuntimeAnalysisContext(input.runtimeAnalysisContext),
|
||||
businessScopeResolution: normalizeBusinessScopeResolution(input.businessScopeResolution),
|
||||
temporalGuard: normalizeRecord(input.temporalGuard),
|
||||
polarityAudit: normalizeRecord(input.polarityAudit),
|
||||
claimAnchorAudit: normalizeRecord(input.claimAnchorAudit),
|
||||
targetedEvidenceAudit: input.targetedEvidenceAudit,
|
||||
evidenceAdmissibilityGateAudit: input.evidenceAdmissibilityGateAudit,
|
||||
rbpLiveRouteAudit: input.rbpLiveRouteAudit ?? null,
|
||||
faLiveRouteAudit: input.faLiveRouteAudit ?? null,
|
||||
groundedAnswerEligibilityGuard: normalizeRecord(input.groundedAnswerEligibilityGuard),
|
||||
followupStateUsage: input.followupStateUsage,
|
||||
followupApplied: input.followupApplied,
|
||||
composition: input.composition as any,
|
||||
composition: input.composition,
|
||||
featureContractsV11: input.featureContractsV11,
|
||||
featureAnswerPolicyV11: input.featureAnswerPolicyV11,
|
||||
previousInvestigationState: input.previousInvestigationState ?? null,
|
||||
addressRuntimeMetaForDeep: input.addressRuntimeMetaForDeep as any,
|
||||
addressRuntimeMetaForDeep: normalizeAddressRuntimeMetaForDeep(input.addressRuntimeMetaForDeep),
|
||||
extractDroppedIntentSegments: input.extractDroppedIntentSegments,
|
||||
buildDebugRoutes: input.buildDebugRoutes,
|
||||
extractExecutionState: input.extractExecutionState,
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ export function buildAssistantDeepTurnResponseRuntimeInput(
|
|||
groundedAnswerEligibilityGuard: analysis.groundedAnswerEligibilityGuard,
|
||||
followupStateUsage: input.followupStateUsage,
|
||||
followupApplied: input.followupApplied,
|
||||
composition: analysis.composition as any,
|
||||
composition: analysis.composition,
|
||||
previousInvestigationState: input.previousInvestigationState ?? null,
|
||||
addressRuntimeMetaForDeep: input.addressRuntimeMetaForDeep,
|
||||
extractDroppedIntentSegments: input.extractDroppedIntentSegments,
|
||||
|
|
|
|||
Loading…
Reference in New Issue