ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Рефакторинг этапов 2.2 - Усилена оркестрацию в deep/address гейте и follow-up binding в assistantService.ts. Починен кейс UTF-8 follow-up refinement (теперь followup_state_usage.applied=true в нужном сценарии). Убраны регрессии по assistantLivingRouter и stage3 lifecycle probe. Корректное поведение для llm canonical candidate (чтобы не уезжало в clarification_required там, где должен быть address factual).

This commit is contained in:
2026-04-11 14:56:14 +03:00
parent 19f5f19d8e
commit b5bd4fd737
46 changed files with 2471 additions and 370 deletions
@@ -18,10 +18,43 @@ export interface AssistantRetrievalCallRecord {
reason: string | null;
}
export type AssistantRetrievalScalar = string | number | boolean | null;
export type AssistantRetrievalFieldValue =
| AssistantRetrievalScalar
| AssistantRetrievalFieldValue[]
| { [key: string]: AssistantRetrievalFieldValue };
export type AssistantRetrievalRecord = Record<string, AssistantRetrievalFieldValue>;
export interface AssistantRetrievalRawResultLike {
status: "ok" | "empty" | "partial" | "error";
result_type: "list" | "summary" | "object" | "chain" | "ranking";
items: AssistantRetrievalRecord[];
summary: AssistantRetrievalRecord;
evidence: AssistantRetrievalRecord[];
why_included: string[];
selection_reason: string[];
risk_factors: string[];
business_interpretation: string[];
confidence: "high" | "medium" | "low";
limitations: string[];
errors: string[];
}
export type AssistantRetrievalRawListItem = AssistantRetrievalFieldValue;
export type AssistantRetrievalRawList = AssistantRetrievalFieldValue[];
export type AssistantRetrievalRawResult =
| AssistantRetrievalRawResultLike
| AssistantRetrievalRawList
| string
| number
| boolean
| null;
export interface AssistantRetrievalRawResultRecord {
fragment_id: string;
route: string;
raw_result: unknown;
raw_result: AssistantRetrievalRawResult;
}
export interface AssistantDeepTurnRetrievalExecutionInput {
@@ -33,7 +66,7 @@ export interface AssistantDeepTurnRetrievalExecutionInput {
options: {
temporalHint: AssistantLiveTemporalHint | null;
}
) => Promise<unknown>;
) => Promise<AssistantRetrievalRawResult>;
mapNoRouteReason: (reason: string | null) => string;
buildSkippedResult: (item: AssistantExecutionPlanItem) => UnifiedRetrievalResult;
normalizeRetrievalResultFn?: typeof normalizeRetrievalResult;
@@ -45,7 +78,7 @@ export interface AssistantDeepTurnRetrievalExecutionOutput {
retrievalResults: UnifiedRetrievalResult[];
}
function buildRouteExecutorErrorRawResult(route: string, message: string): Record<string, unknown> {
function buildRouteExecutorErrorRawResult(route: string, message: string): AssistantRetrievalRawResult {
return {
status: "error",
result_type: "summary",
@@ -64,6 +97,24 @@ function buildRouteExecutorErrorRawResult(route: string, message: string): Recor
};
}
function normalizeRawResult(
value: AssistantRetrievalRawResult | object | null | undefined
): AssistantRetrievalRawResult {
if (value === null || value === undefined) {
return null;
}
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
return value;
}
if (Array.isArray(value)) {
return value as AssistantRetrievalRawList;
}
if (typeof value === "object") {
return value as AssistantRetrievalRawResultLike;
}
return null;
}
export async function executeAssistantDeepTurnRetrievalPlan(
input: AssistantDeepTurnRetrievalExecutionInput
): Promise<AssistantDeepTurnRetrievalExecutionOutput> {
@@ -99,13 +150,14 @@ export async function executeAssistantDeepTurnRetrievalPlan(
const raw = await input.executeRouteRuntime(planItem.route, planItem.fragment_text, {
temporalHint: input.liveTemporalHint
});
const normalizedRaw = normalizeRawResult(raw);
retrievalResultsRaw.push({
fragment_id: planItem.fragment_id,
route: planItem.route,
raw_result: raw
raw_result: normalizedRaw
});
retrievalResults.push(
normalizeRetrievalResultSafe(planItem.fragment_id, planItem.requirement_ids, planItem.route, raw)
normalizeRetrievalResultSafe(planItem.fragment_id, planItem.requirement_ids, planItem.route, normalizedRaw)
);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);