332 lines
11 KiB
TypeScript
332 lines
11 KiB
TypeScript
import {
|
|
ASSISTANT_STATE_TRANSITION_RUNTIME_SCHEMA_VERSION,
|
|
type AssistantCarryoverDepth,
|
|
type AssistantCoverageGateState,
|
|
type AssistantRuntimeContractShadowDecision,
|
|
type AssistantStateTransitionApplicationStatus,
|
|
type AssistantStateTransitionRuntimeContract,
|
|
type AssistantTruthAnswerPolicyRuntimeContract,
|
|
type AssistantTransitionClassId
|
|
} from "../types/assistantRuntimeContracts";
|
|
import { resolveAssistantRuntimeContractShadow } from "./assistantRuntimeContractResolver";
|
|
import { getAssistantTransitionContract } from "./assistantRuntimeContractRegistry";
|
|
import { resolveAssistantTruthAnswerPolicyRuntime } from "./assistantTruthAnswerPolicyRuntimeAdapter";
|
|
|
|
export interface ResolveAssistantStateTransitionRuntimeInput {
|
|
addressDebug?: Record<string, unknown> | null;
|
|
addressRuntimeMeta?: Record<string, unknown> | null;
|
|
groundingStatus?: unknown;
|
|
coverageReport?: Record<string, unknown> | null;
|
|
replyType?: unknown;
|
|
runtimeContractShadow?: AssistantRuntimeContractShadowDecision | null;
|
|
truthAnswerPolicy?: AssistantTruthAnswerPolicyRuntimeContract | null;
|
|
}
|
|
|
|
export interface AssistantStateTransitionRuntimeFields {
|
|
assistant_state_transition_v1: AssistantStateTransitionRuntimeContract;
|
|
state_transition_contract: AssistantStateTransitionRuntimeContract;
|
|
state_transition_id: AssistantTransitionClassId | null;
|
|
state_transition_status: AssistantStateTransitionApplicationStatus;
|
|
effective_carryover_depth: AssistantCarryoverDepth;
|
|
}
|
|
|
|
function toRecordObject(value: unknown): Record<string, unknown> | null {
|
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
return null;
|
|
}
|
|
return value as Record<string, unknown>;
|
|
}
|
|
|
|
function toNonEmptyString(value: unknown): string | null {
|
|
if (value === null || value === undefined) {
|
|
return null;
|
|
}
|
|
const text = String(value).trim();
|
|
return text.length > 0 ? text : null;
|
|
}
|
|
|
|
function uniqueStrings(values: string[]): string[] {
|
|
return Array.from(new Set(values.filter((item) => item.trim().length > 0)));
|
|
}
|
|
|
|
function baseStateActions(): AssistantStateTransitionRuntimeContract["state_actions"] {
|
|
return {
|
|
living_mode_state: "none",
|
|
root_frame_state: "none",
|
|
selected_object_frame_state: "none",
|
|
meta_frame_state: "none",
|
|
clarification_state: "none",
|
|
coverage_gate_state: "none",
|
|
answer_context_state: "none"
|
|
};
|
|
}
|
|
|
|
function stateActionsFor(transitionId: AssistantTransitionClassId | null): AssistantStateTransitionRuntimeContract["state_actions"] {
|
|
const actions = baseStateActions();
|
|
if (!transitionId) {
|
|
return actions;
|
|
}
|
|
actions.living_mode_state = "update";
|
|
actions.coverage_gate_state = "create";
|
|
|
|
if (transitionId === "T1") {
|
|
return {
|
|
...actions,
|
|
root_frame_state: "create",
|
|
selected_object_frame_state: "clear",
|
|
meta_frame_state: "clear",
|
|
clarification_state: "clear",
|
|
answer_context_state: "create"
|
|
};
|
|
}
|
|
if (transitionId === "T2") {
|
|
return {
|
|
...actions,
|
|
root_frame_state: "update",
|
|
selected_object_frame_state: "clear",
|
|
meta_frame_state: "clear",
|
|
clarification_state: "clear",
|
|
answer_context_state: "create"
|
|
};
|
|
}
|
|
if (transitionId === "T3") {
|
|
return {
|
|
...actions,
|
|
root_frame_state: "preserve",
|
|
selected_object_frame_state: "create",
|
|
meta_frame_state: "clear",
|
|
clarification_state: "clear",
|
|
answer_context_state: "create"
|
|
};
|
|
}
|
|
if (transitionId === "T4" || transitionId === "T5") {
|
|
return {
|
|
...actions,
|
|
root_frame_state: "preserve",
|
|
selected_object_frame_state: "reuse",
|
|
meta_frame_state: "clear",
|
|
clarification_state: "clear",
|
|
answer_context_state: "create"
|
|
};
|
|
}
|
|
if (transitionId === "T6") {
|
|
return {
|
|
...actions,
|
|
root_frame_state: "preserve",
|
|
selected_object_frame_state: "clear",
|
|
meta_frame_state: "clear",
|
|
clarification_state: "clear",
|
|
answer_context_state: "create"
|
|
};
|
|
}
|
|
if (transitionId === "T7") {
|
|
return {
|
|
...actions,
|
|
root_frame_state: "preserve",
|
|
selected_object_frame_state: "preserve",
|
|
meta_frame_state: "none",
|
|
clarification_state: "update",
|
|
answer_context_state: "none"
|
|
};
|
|
}
|
|
if (transitionId === "T8") {
|
|
return {
|
|
...actions,
|
|
root_frame_state: "preserve",
|
|
selected_object_frame_state: "preserve",
|
|
meta_frame_state: "create",
|
|
clarification_state: "none",
|
|
answer_context_state: "reuse"
|
|
};
|
|
}
|
|
if (transitionId === "T9") {
|
|
return {
|
|
...actions,
|
|
root_frame_state: "preserve",
|
|
selected_object_frame_state: "preserve",
|
|
meta_frame_state: "create",
|
|
clarification_state: "none",
|
|
coverage_gate_state: "preserve",
|
|
answer_context_state: "reuse"
|
|
};
|
|
}
|
|
return {
|
|
...actions,
|
|
root_frame_state: "none",
|
|
selected_object_frame_state: "clear",
|
|
meta_frame_state: "none",
|
|
clarification_state: "none",
|
|
coverage_gate_state: "block",
|
|
answer_context_state: "none"
|
|
};
|
|
}
|
|
|
|
function applicationStatusFor(input: {
|
|
transitionId: AssistantTransitionClassId | null;
|
|
coverageGateState: AssistantCoverageGateState;
|
|
}): AssistantStateTransitionApplicationStatus {
|
|
if (!input.transitionId) {
|
|
return "unresolved";
|
|
}
|
|
if (input.coverageGateState.truth_mode === "clarification_required") {
|
|
return "clarification_required";
|
|
}
|
|
if (input.transitionId === "T10" || input.coverageGateState.coverage_status === "blocked" || input.coverageGateState.truth_mode === "unsupported") {
|
|
return "blocked";
|
|
}
|
|
return "applied";
|
|
}
|
|
|
|
function effectiveCarryoverDepthFor(input: {
|
|
declared: AssistantCarryoverDepth | null;
|
|
truthGate: AssistantCarryoverDepth;
|
|
status: AssistantStateTransitionApplicationStatus;
|
|
}): AssistantCarryoverDepth {
|
|
if (input.status === "unresolved" || input.status === "blocked") {
|
|
return "none";
|
|
}
|
|
if (!input.declared) {
|
|
return input.truthGate;
|
|
}
|
|
if (input.status === "clarification_required") {
|
|
return input.declared === "full" ? "full" : input.truthGate;
|
|
}
|
|
if (input.truthGate === "none") {
|
|
return "none";
|
|
}
|
|
if (input.declared === "full") {
|
|
return input.truthGate;
|
|
}
|
|
if (input.truthGate === "full") {
|
|
return input.declared;
|
|
}
|
|
return input.declared === input.truthGate ? input.declared : "none";
|
|
}
|
|
|
|
function resolveShadow(
|
|
input: ResolveAssistantStateTransitionRuntimeInput,
|
|
debug: Record<string, unknown>
|
|
): AssistantRuntimeContractShadowDecision {
|
|
return (
|
|
input.runtimeContractShadow ??
|
|
(toRecordObject(debug.assistant_runtime_contract_v1) as AssistantRuntimeContractShadowDecision | null) ??
|
|
resolveAssistantRuntimeContractShadow({
|
|
addressDebug: debug,
|
|
addressRuntimeMeta: input.addressRuntimeMeta,
|
|
groundingStatus: input.groundingStatus
|
|
})
|
|
);
|
|
}
|
|
|
|
function resolveTruthPolicy(
|
|
input: ResolveAssistantStateTransitionRuntimeInput,
|
|
debug: Record<string, unknown>
|
|
): AssistantTruthAnswerPolicyRuntimeContract {
|
|
return (
|
|
input.truthAnswerPolicy ??
|
|
(toRecordObject(debug.assistant_truth_answer_policy_v1) as AssistantTruthAnswerPolicyRuntimeContract | null) ??
|
|
resolveAssistantTruthAnswerPolicyRuntime({
|
|
addressDebug: debug,
|
|
addressRuntimeMeta: input.addressRuntimeMeta,
|
|
groundingStatus: input.groundingStatus,
|
|
coverageReport: input.coverageReport,
|
|
replyType: input.replyType
|
|
})
|
|
);
|
|
}
|
|
|
|
function reasonCodesFor(input: {
|
|
shadow: AssistantRuntimeContractShadowDecision;
|
|
truthPolicy: AssistantTruthAnswerPolicyRuntimeContract;
|
|
transitionId: AssistantTransitionClassId | null;
|
|
applicationStatus: AssistantStateTransitionApplicationStatus;
|
|
}): string[] {
|
|
return uniqueStrings([
|
|
`transition_status_${input.applicationStatus}`,
|
|
...(input.transitionId ? [`transition_${input.transitionId}`] : ["transition_unresolved"]),
|
|
...input.shadow.transition_contract_reason,
|
|
...input.shadow.capability_contract_reason,
|
|
...input.truthPolicy.truth_gate.reason_codes
|
|
]).slice(0, 40);
|
|
}
|
|
|
|
export function resolveAssistantStateTransitionRuntime(
|
|
input: ResolveAssistantStateTransitionRuntimeInput
|
|
): AssistantStateTransitionRuntimeContract {
|
|
const debug = toRecordObject(input.addressDebug) ?? {};
|
|
const shadow = resolveShadow(input, debug);
|
|
const truthPolicy = resolveTruthPolicy(input, debug);
|
|
const transitionId = shadow.transition_contract_id;
|
|
const transition = transitionId ? getAssistantTransitionContract(transitionId) : null;
|
|
const status = applicationStatusFor({
|
|
transitionId,
|
|
coverageGateState: truthPolicy.truth_gate
|
|
});
|
|
const effectiveCarryoverDepth = effectiveCarryoverDepthFor({
|
|
declared: transition?.allowed_carryover_depth ?? null,
|
|
truthGate: truthPolicy.truth_gate.carryover_eligibility,
|
|
status
|
|
});
|
|
const forbiddenCarryover = uniqueStrings([
|
|
...(transition?.forbidden_carryover ?? []),
|
|
...(status === "blocked" ? ["blocked_as_confirmed_factual_answer"] : []),
|
|
...(effectiveCarryoverDepth === "none" ? ["implicit_followup_reuse"] : [])
|
|
]);
|
|
|
|
return {
|
|
schema_version: ASSISTANT_STATE_TRANSITION_RUNTIME_SCHEMA_VERSION,
|
|
state_owner: "assistantStateTransitionRuntimeAdapter",
|
|
transition_id: transitionId,
|
|
transition_title: transition?.title ?? shadow.transition_contract_title,
|
|
application_status: status,
|
|
declared_carryover_depth: transition?.allowed_carryover_depth ?? null,
|
|
truth_gate_carryover_depth: truthPolicy.truth_gate.carryover_eligibility,
|
|
effective_carryover_depth: effectiveCarryoverDepth,
|
|
required_prior_state: transition?.required_prior_state ?? [],
|
|
expected_answer_mode: transition?.expected_answer_mode ?? null,
|
|
state_mutations: transition?.state_mutations ?? [],
|
|
forbidden_carryover: forbiddenCarryover,
|
|
state_actions: stateActionsFor(transitionId),
|
|
coverage_gate_state: {
|
|
coverage_status: truthPolicy.truth_gate.coverage_status,
|
|
evidence_grade: truthPolicy.truth_gate.evidence_grade,
|
|
grounding_status: truthPolicy.truth_gate.grounding_status,
|
|
truth_mode: truthPolicy.truth_gate.truth_mode,
|
|
carryover_eligibility: truthPolicy.truth_gate.carryover_eligibility,
|
|
reason_codes: truthPolicy.truth_gate.reason_codes
|
|
},
|
|
reason_codes: reasonCodesFor({
|
|
shadow,
|
|
truthPolicy,
|
|
transitionId,
|
|
applicationStatus: status
|
|
})
|
|
};
|
|
}
|
|
|
|
export function buildAssistantStateTransitionRuntimeFields(
|
|
input: ResolveAssistantStateTransitionRuntimeInput
|
|
): AssistantStateTransitionRuntimeFields {
|
|
const transition = resolveAssistantStateTransitionRuntime(input);
|
|
return {
|
|
assistant_state_transition_v1: transition,
|
|
state_transition_contract: transition,
|
|
state_transition_id: transition.transition_id,
|
|
state_transition_status: transition.application_status,
|
|
effective_carryover_depth: transition.effective_carryover_depth
|
|
};
|
|
}
|
|
|
|
export function attachAssistantStateTransition<T extends Record<string, unknown>>(
|
|
debugPayload: T,
|
|
input: Omit<ResolveAssistantStateTransitionRuntimeInput, "addressDebug">
|
|
): T & AssistantStateTransitionRuntimeFields {
|
|
return {
|
|
...debugPayload,
|
|
...buildAssistantStateTransitionRuntimeFields({
|
|
...input,
|
|
addressDebug: debugPayload
|
|
})
|
|
};
|
|
}
|