ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Рефакторинг этапов 2.772.80 - Убрано as any из адресного response-runtime и добавил явную нормализацию перед финализацией / Убран cast в builderе deep-response composition

This commit is contained in:
2026-04-11 10:35:29 +03:00
parent 9f3749fd4a
commit dedf193542
6 changed files with 532 additions and 59 deletions
@@ -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,