ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Рефакторинг этапов 2.27 вынос оркестрации tryHandleLivingChat (decision/execution ветки) в отдельный runtime adapter.
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
export interface AssistantLivingChatSessionScopeInput {
|
||||
knownOrganizations?: unknown[];
|
||||
selectedOrganization?: unknown;
|
||||
activeOrganization?: unknown;
|
||||
}
|
||||
|
||||
export interface AssistantLivingChatModeDecisionInput {
|
||||
mode?: string | null;
|
||||
reason?: string | null;
|
||||
}
|
||||
|
||||
export interface AssistantLivingChatRuntimeInput {
|
||||
userMessage: string;
|
||||
sessionItems: unknown[];
|
||||
modeDecision?: AssistantLivingChatModeDecisionInput | null;
|
||||
sessionScope: AssistantLivingChatSessionScopeInput;
|
||||
addressRuntimeMeta?: Record<string, unknown> | null;
|
||||
traceIdFactory: () => string;
|
||||
toNonEmptyString: (value: unknown) => string | null;
|
||||
mergeKnownOrganizations: (values: unknown[]) => string[];
|
||||
hasAssistantDataScopeMetaQuestionSignal: (message: string) => boolean;
|
||||
shouldHandleAsAssistantCapabilityMetaQuery: (message: string) => boolean;
|
||||
hasDestructiveDataActionSignal: (message: string) => boolean;
|
||||
hasDangerOrCoercionSignal: (message: string) => boolean;
|
||||
hasOperationalAdminActionRequestSignal: (message: string) => boolean;
|
||||
hasOrganizationFactLookupSignal: (message: string) => boolean;
|
||||
hasOrganizationFactFollowupSignal: (message: string, items: unknown[]) => boolean;
|
||||
shouldEmitOrganizationSelectionReply: (message: string, activeOrganization: string | null) => boolean;
|
||||
hasAssistantCapabilityQuestionSignal: (message: string) => boolean;
|
||||
resolveDataScopeProbe: () => Promise<Record<string, unknown> | null>;
|
||||
executeLlmChat: () => Promise<string>;
|
||||
applyScriptGuard: (chatText: string, userMessage: string) => {
|
||||
text: string;
|
||||
applied: boolean;
|
||||
reason: string | null;
|
||||
};
|
||||
applyGroundingGuard: (input: {
|
||||
userMessage: string;
|
||||
chatText: string;
|
||||
organization: string | null;
|
||||
}) => {
|
||||
text: string;
|
||||
applied: boolean;
|
||||
reason: string | null;
|
||||
};
|
||||
buildAssistantSafetyRefusalReply: () => string;
|
||||
buildAssistantDataScopeContractReply: (scopeProbe: Record<string, unknown> | null) => string;
|
||||
buildAssistantOrganizationFactBoundaryReply: (organization: string | null) => string;
|
||||
buildAssistantDataScopeSelectionReply: (organization: string | null) => string;
|
||||
buildAssistantOperationalBoundaryReply: () => string;
|
||||
buildAssistantCapabilityContractReply: () => string;
|
||||
}
|
||||
|
||||
export interface AssistantLivingChatRuntimeOutput {
|
||||
handled: boolean;
|
||||
chatText: string;
|
||||
debug: Record<string, unknown> | null;
|
||||
}
|
||||
|
||||
export async function runAssistantLivingChatRuntime(
|
||||
input: AssistantLivingChatRuntimeInput
|
||||
): Promise<AssistantLivingChatRuntimeOutput> {
|
||||
const userMessage = String(input.userMessage ?? "");
|
||||
const dataScopeMetaQuery = input.hasAssistantDataScopeMetaQuestionSignal(userMessage);
|
||||
const capabilityMetaQuery = input.shouldHandleAsAssistantCapabilityMetaQuery(userMessage);
|
||||
const destructiveSignal = input.hasDestructiveDataActionSignal(userMessage);
|
||||
const dangerSignal = input.hasDangerOrCoercionSignal(userMessage);
|
||||
const operationalSignal = input.hasOperationalAdminActionRequestSignal(userMessage);
|
||||
|
||||
let dataScopeProbe: Record<string, unknown> | null = null;
|
||||
let chatText = "";
|
||||
let livingChatSource = "llm_chat";
|
||||
let livingChatScriptGuardApplied = false;
|
||||
let livingChatScriptGuardReason: string | null = null;
|
||||
let livingChatGroundingGuardApplied = false;
|
||||
let livingChatGroundingGuardReason: string | null = null;
|
||||
let knownOrganizations = input.mergeKnownOrganizations(input.sessionScope.knownOrganizations ?? []);
|
||||
let selectedOrganization = input.toNonEmptyString(input.sessionScope.selectedOrganization);
|
||||
let activeOrganization = input.toNonEmptyString(input.sessionScope.activeOrganization);
|
||||
|
||||
if (capabilityMetaQuery && (destructiveSignal || dangerSignal)) {
|
||||
chatText = input.buildAssistantSafetyRefusalReply();
|
||||
livingChatSource = "deterministic_safety_refusal";
|
||||
} else if (dataScopeMetaQuery) {
|
||||
dataScopeProbe = await input.resolveDataScopeProbe();
|
||||
chatText = input.buildAssistantDataScopeContractReply(dataScopeProbe);
|
||||
knownOrganizations = input.mergeKnownOrganizations([
|
||||
...knownOrganizations,
|
||||
...(Array.isArray(dataScopeProbe?.organizations) ? (dataScopeProbe.organizations as unknown[]) : [])
|
||||
]);
|
||||
if (!activeOrganization && knownOrganizations.length === 1) {
|
||||
activeOrganization = knownOrganizations[0];
|
||||
}
|
||||
livingChatSource =
|
||||
dataScopeProbe?.status === "resolved"
|
||||
? "deterministic_data_scope_contract_live"
|
||||
: "deterministic_data_scope_contract";
|
||||
} else if ((selectedOrganization || activeOrganization) && input.hasOrganizationFactLookupSignal(userMessage)) {
|
||||
const scopedOrganization = selectedOrganization ?? activeOrganization ?? null;
|
||||
chatText = input.buildAssistantOrganizationFactBoundaryReply(scopedOrganization);
|
||||
activeOrganization = scopedOrganization ?? activeOrganization;
|
||||
livingChatSource = "deterministic_organization_fact_boundary";
|
||||
} else if (
|
||||
(selectedOrganization || activeOrganization) &&
|
||||
input.hasOrganizationFactFollowupSignal(userMessage, input.sessionItems)
|
||||
) {
|
||||
const scopedOrganization = selectedOrganization ?? activeOrganization ?? null;
|
||||
chatText = input.buildAssistantOrganizationFactBoundaryReply(scopedOrganization);
|
||||
activeOrganization = scopedOrganization ?? activeOrganization;
|
||||
livingChatSource = "deterministic_organization_fact_boundary_followup";
|
||||
} else if (
|
||||
!capabilityMetaQuery &&
|
||||
input.shouldEmitOrganizationSelectionReply(userMessage, selectedOrganization ?? activeOrganization)
|
||||
) {
|
||||
const scopedOrganization = selectedOrganization ?? activeOrganization ?? null;
|
||||
chatText = input.buildAssistantDataScopeSelectionReply(scopedOrganization);
|
||||
activeOrganization = scopedOrganization ?? activeOrganization;
|
||||
livingChatSource = "deterministic_data_scope_selection_contract";
|
||||
} else if (capabilityMetaQuery && operationalSignal && !input.hasAssistantCapabilityQuestionSignal(userMessage)) {
|
||||
chatText = input.buildAssistantOperationalBoundaryReply();
|
||||
livingChatSource = "deterministic_operational_boundary";
|
||||
} else if (capabilityMetaQuery) {
|
||||
chatText = input.buildAssistantCapabilityContractReply();
|
||||
livingChatSource = "deterministic_capability_contract";
|
||||
} else {
|
||||
chatText = await input.executeLlmChat();
|
||||
const scriptGuard = input.applyScriptGuard(chatText, userMessage);
|
||||
chatText = scriptGuard.text;
|
||||
if (scriptGuard.applied) {
|
||||
livingChatScriptGuardApplied = true;
|
||||
livingChatScriptGuardReason = scriptGuard.reason;
|
||||
livingChatSource = "llm_chat_script_guard";
|
||||
}
|
||||
const groundingGuard = input.applyGroundingGuard({
|
||||
userMessage,
|
||||
chatText,
|
||||
organization: activeOrganization ?? selectedOrganization ?? null
|
||||
});
|
||||
chatText = groundingGuard.text;
|
||||
if (groundingGuard.applied) {
|
||||
livingChatGroundingGuardApplied = true;
|
||||
livingChatGroundingGuardReason = groundingGuard.reason;
|
||||
livingChatSource = "llm_chat_grounding_guard";
|
||||
}
|
||||
}
|
||||
|
||||
if (!chatText) {
|
||||
return {
|
||||
handled: false,
|
||||
chatText: "",
|
||||
debug: null
|
||||
};
|
||||
}
|
||||
|
||||
const addressRuntimeMeta = (input.addressRuntimeMeta && typeof input.addressRuntimeMeta === "object"
|
||||
? input.addressRuntimeMeta
|
||||
: {}) as Record<string, unknown>;
|
||||
const predecomposeContract =
|
||||
addressRuntimeMeta.predecomposeContract && typeof addressRuntimeMeta.predecomposeContract === "object"
|
||||
? (addressRuntimeMeta.predecomposeContract as Record<string, unknown>)
|
||||
: null;
|
||||
|
||||
const debug: Record<string, unknown> = {
|
||||
trace_id: input.traceIdFactory(),
|
||||
prompt_version: "living_chat_router_v1",
|
||||
schema_version: "living_chat_router_v1",
|
||||
fallback_type: "none",
|
||||
detected_mode: "chat",
|
||||
detected_mode_confidence: "high",
|
||||
execution_lane: "living_chat",
|
||||
living_router_mode: input.modeDecision?.mode ?? "chat",
|
||||
living_router_reason: input.modeDecision?.reason ?? "living_chat_signal_detected",
|
||||
living_chat_response_source: livingChatSource,
|
||||
living_chat_script_guard_applied: livingChatScriptGuardApplied,
|
||||
living_chat_script_guard_reason: livingChatScriptGuardReason,
|
||||
living_chat_grounding_guard_applied: livingChatGroundingGuardApplied,
|
||||
living_chat_grounding_guard_reason: livingChatGroundingGuardReason,
|
||||
living_chat_data_scope_probe_status: dataScopeProbe?.status ?? null,
|
||||
living_chat_data_scope_probe_channel: dataScopeProbe?.channel ?? null,
|
||||
living_chat_data_scope_probe_org_count: Array.isArray(dataScopeProbe?.organizations)
|
||||
? dataScopeProbe.organizations.length
|
||||
: 0,
|
||||
living_chat_data_scope_probe_organizations: Array.isArray(dataScopeProbe?.organizations)
|
||||
? input.mergeKnownOrganizations(dataScopeProbe.organizations as unknown[])
|
||||
: [],
|
||||
living_chat_data_scope_probe_error: dataScopeProbe?.error ?? null,
|
||||
living_chat_selected_organization: selectedOrganization ?? null,
|
||||
assistant_known_organizations: knownOrganizations,
|
||||
assistant_active_organization: activeOrganization ?? null,
|
||||
address_llm_predecompose_attempted: Boolean(addressRuntimeMeta.attempted),
|
||||
address_llm_predecompose_applied: Boolean(addressRuntimeMeta.applied),
|
||||
address_llm_predecompose_reason: addressRuntimeMeta.reason ?? null,
|
||||
address_llm_predecompose_contract: predecomposeContract,
|
||||
orchestration_contract_v1: addressRuntimeMeta.orchestrationContract ?? null,
|
||||
tool_gate_decision: addressRuntimeMeta.toolGateDecision ?? null,
|
||||
tool_gate_reason: addressRuntimeMeta.toolGateReason ?? null,
|
||||
normalized: null,
|
||||
normalizer_output: null
|
||||
};
|
||||
|
||||
return {
|
||||
handled: true,
|
||||
chatText,
|
||||
debug
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user