112 lines
4.2 KiB
TypeScript
112 lines
4.2 KiB
TypeScript
import type { AssistantReplyType } from "../types/assistant";
|
|
import type {
|
|
AssistantCapabilityBindingAction,
|
|
AssistantCapabilityRuntimeBindingContract
|
|
} from "../types/assistantRuntimeContracts";
|
|
|
|
export interface ApplyAssistantCapabilityBindingResponseGuardInput {
|
|
assistantReply: string;
|
|
replyType: AssistantReplyType;
|
|
capabilityBinding: AssistantCapabilityRuntimeBindingContract | null | undefined;
|
|
}
|
|
|
|
export interface AssistantCapabilityBindingResponseGuardAudit {
|
|
schema_version: "assistant_capability_binding_response_guard_v1";
|
|
guard_owner: "assistantCapabilityBindingResponseGuard";
|
|
applied: boolean;
|
|
action: AssistantCapabilityBindingAction | "none";
|
|
original_reply_type: AssistantReplyType;
|
|
guarded_reply_type: AssistantReplyType;
|
|
reason_codes: string[];
|
|
}
|
|
|
|
export interface ApplyAssistantCapabilityBindingResponseGuardOutput {
|
|
assistantReply: string;
|
|
replyType: AssistantReplyType;
|
|
audit: AssistantCapabilityBindingResponseGuardAudit;
|
|
}
|
|
|
|
function formatMissingAnchors(anchors: string[]): string {
|
|
if (anchors.length === 0) {
|
|
return "нужный объект, период или организацию";
|
|
}
|
|
return anchors.join(", ");
|
|
}
|
|
|
|
function buildClarificationReply(binding: AssistantCapabilityRuntimeBindingContract): string {
|
|
return [
|
|
"Нужно уточнение, чтобы не подставить неподтвержденный объект в расчет.",
|
|
`Не хватает: ${formatMissingAnchors(binding.missing_anchors)}.`,
|
|
"Уточните это, и я продолжу тот же сценарий."
|
|
].join("\n");
|
|
}
|
|
|
|
function buildBlockedReply(binding: AssistantCapabilityRuntimeBindingContract): string {
|
|
const reasons = binding.violations.length > 0 ? binding.violations.join(", ") : "runtime_binding_blocked";
|
|
return [
|
|
"Не могу надежно подтвердить ответ в текущем контексте.",
|
|
`Проверка сценария остановила ответ: ${reasons}.`,
|
|
"Лучше уточнить объект или перезапустить вопрос от корневого запроса, чем выдавать это как подтвержденный факт."
|
|
].join("\n");
|
|
}
|
|
|
|
export function applyAssistantCapabilityBindingResponseGuard(
|
|
input: ApplyAssistantCapabilityBindingResponseGuardInput
|
|
): ApplyAssistantCapabilityBindingResponseGuardOutput {
|
|
const binding = input.capabilityBinding;
|
|
const baseAudit: AssistantCapabilityBindingResponseGuardAudit = {
|
|
schema_version: "assistant_capability_binding_response_guard_v1",
|
|
guard_owner: "assistantCapabilityBindingResponseGuard",
|
|
applied: false,
|
|
action: binding?.binding_action ?? "none",
|
|
original_reply_type: input.replyType,
|
|
guarded_reply_type: input.replyType,
|
|
reason_codes: binding?.reason_codes ?? []
|
|
};
|
|
|
|
if (!binding || binding.binding_action === "allow" || binding.binding_action === "observe_only") {
|
|
return {
|
|
assistantReply: input.assistantReply,
|
|
replyType: input.replyType,
|
|
audit: baseAudit
|
|
};
|
|
}
|
|
|
|
if (binding.binding_action === "clarify") {
|
|
return {
|
|
assistantReply: buildClarificationReply(binding),
|
|
replyType: "partial_coverage",
|
|
audit: {
|
|
...baseAudit,
|
|
applied: true,
|
|
guarded_reply_type: "partial_coverage",
|
|
reason_codes: [...baseAudit.reason_codes, "capability_binding_guard_clarification_reply"]
|
|
}
|
|
};
|
|
}
|
|
|
|
if (binding.binding_action === "block") {
|
|
return {
|
|
assistantReply: buildBlockedReply(binding),
|
|
replyType: "partial_coverage",
|
|
audit: {
|
|
...baseAudit,
|
|
applied: true,
|
|
guarded_reply_type: "partial_coverage",
|
|
reason_codes: [...baseAudit.reason_codes, "capability_binding_guard_blocked_reply"]
|
|
}
|
|
};
|
|
}
|
|
|
|
return {
|
|
assistantReply: input.assistantReply,
|
|
replyType: input.replyType === "factual" ? "partial_coverage" : input.replyType,
|
|
audit: {
|
|
...baseAudit,
|
|
applied: input.replyType === "factual",
|
|
guarded_reply_type: input.replyType === "factual" ? "partial_coverage" : input.replyType,
|
|
reason_codes: [...baseAudit.reason_codes, "capability_binding_guard_limited_reply_type"]
|
|
}
|
|
};
|
|
}
|