317 lines
12 KiB
TypeScript
317 lines
12 KiB
TypeScript
import {
|
|
ASSISTANT_RUNTIME_CONTRACTS_SCHEMA_VERSION,
|
|
type AssistantCarryoverDepth,
|
|
type AssistantRuntimeContractShadowDecision,
|
|
type AssistantTransitionClassId
|
|
} from "../types/assistantRuntimeContracts";
|
|
import type { AddressIntent } from "../types/addressQuery";
|
|
import { toAddressTruthGateContract } from "./addressTruthGatePolicy";
|
|
import {
|
|
getAssistantCapabilityContract,
|
|
getAssistantCapabilityContractByIntent,
|
|
getAssistantTransitionContract
|
|
} from "./assistantRuntimeContractRegistry";
|
|
|
|
export interface ResolveAssistantRuntimeContractShadowInput {
|
|
userMessage?: unknown;
|
|
addressDebug?: Record<string, unknown> | null;
|
|
addressRuntimeMeta?: Record<string, unknown> | null;
|
|
groundingStatus?: unknown;
|
|
}
|
|
|
|
export interface AssistantRuntimeContractShadowFields {
|
|
assistant_runtime_contract_v1: AssistantRuntimeContractShadowDecision;
|
|
transition_contract_id: AssistantTransitionClassId | null;
|
|
capability_contract_id: string | null;
|
|
truth_gate_contract_status: AssistantRuntimeContractShadowDecision["truth_gate_contract_status"];
|
|
}
|
|
|
|
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 isAddressIntent(value: string | null): value is AddressIntent {
|
|
return Boolean(value) && value !== "unknown";
|
|
}
|
|
|
|
function asNumber(value: unknown): number | null {
|
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
return value;
|
|
}
|
|
if (typeof value === "string" && value.trim().length > 0) {
|
|
const parsed = Number(value);
|
|
return Number.isFinite(parsed) ? parsed : null;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function runtimeMetaFrom(input: ResolveAssistantRuntimeContractShadowInput): Record<string, unknown> | null {
|
|
const direct = toRecordObject(input.addressRuntimeMeta);
|
|
if (direct) {
|
|
return direct;
|
|
}
|
|
const debug = toRecordObject(input.addressDebug);
|
|
if (!debug) {
|
|
return null;
|
|
}
|
|
const dialogContinuationContract = toRecordObject(debug.dialog_continuation_contract_v2);
|
|
const orchestrationContract = toRecordObject(debug.orchestration_contract_v1);
|
|
if (!dialogContinuationContract && !orchestrationContract) {
|
|
return null;
|
|
}
|
|
return {
|
|
dialogContinuationContract,
|
|
orchestrationContract,
|
|
toolGateDecision: debug.tool_gate_decision,
|
|
toolGateReason: debug.tool_gate_reason
|
|
};
|
|
}
|
|
|
|
function resolveCapabilityContractId(debug: Record<string, unknown>, meta: Record<string, unknown> | null): {
|
|
capabilityId: string | null;
|
|
reasons: string[];
|
|
} {
|
|
const explicitCapabilityId = toNonEmptyString(debug.capability_id);
|
|
if (explicitCapabilityId && getAssistantCapabilityContract(explicitCapabilityId)) {
|
|
return {
|
|
capabilityId: explicitCapabilityId,
|
|
reasons: ["debug_capability_id_matched_contract"]
|
|
};
|
|
}
|
|
|
|
const orchestrationContract = toRecordObject(meta?.orchestrationContract) ?? toRecordObject(debug.orchestration_contract_v1);
|
|
const intent =
|
|
toNonEmptyString(debug.detected_intent) ??
|
|
toNonEmptyString(orchestrationContract?.address_intent);
|
|
if (isAddressIntent(intent)) {
|
|
const contract = getAssistantCapabilityContractByIntent(intent);
|
|
if (contract) {
|
|
return {
|
|
capabilityId: contract.capability_id,
|
|
reasons: ["intent_matched_capability_contract"]
|
|
};
|
|
}
|
|
}
|
|
|
|
return {
|
|
capabilityId: null,
|
|
reasons: explicitCapabilityId ? ["debug_capability_id_has_no_contract"] : ["capability_contract_not_resolved"]
|
|
};
|
|
}
|
|
|
|
function isSelectedObjectCapability(capabilityId: string | null): boolean {
|
|
if (!capabilityId) {
|
|
return false;
|
|
}
|
|
const contract = getAssistantCapabilityContract(capabilityId);
|
|
return Boolean(contract?.requires_focus_object);
|
|
}
|
|
|
|
function resolveTransitionId(input: {
|
|
debug: Record<string, unknown>;
|
|
meta: Record<string, unknown> | null;
|
|
capabilityId: string | null;
|
|
groundingStatus: string | null;
|
|
}): { transitionId: AssistantTransitionClassId | null; reasons: string[] } {
|
|
const dialogContinuationContract =
|
|
toRecordObject(input.meta?.dialogContinuationContract) ??
|
|
toRecordObject(input.debug.dialog_continuation_contract_v2);
|
|
const orchestrationContract =
|
|
toRecordObject(input.meta?.orchestrationContract) ??
|
|
toRecordObject(input.debug.orchestration_contract_v1);
|
|
const finalDecision = toRecordObject(orchestrationContract?.final_decision);
|
|
const hardMetaMode = toNonEmptyString(orchestrationContract?.hard_meta_mode);
|
|
const toolGateReason =
|
|
toNonEmptyString(input.meta?.toolGateReason) ??
|
|
toNonEmptyString(input.debug.tool_gate_reason) ??
|
|
toNonEmptyString(finalDecision?.tool_gate_reason);
|
|
const continuationDecision = toNonEmptyString(dialogContinuationContract?.decision);
|
|
const targetIntent =
|
|
toNonEmptyString(dialogContinuationContract?.target_intent) ??
|
|
toNonEmptyString(input.debug.detected_intent);
|
|
const currentFrameKind = toNonEmptyString(toRecordObject(input.debug.address_root_frame_context)?.current_frame_kind);
|
|
const missingFilters = Array.isArray(input.debug.missing_required_filters) ? input.debug.missing_required_filters.length : 0;
|
|
|
|
if (
|
|
input.groundingStatus === "route_mismatch_blocked" ||
|
|
input.debug.route_expectation_status === "mismatch" ||
|
|
input.debug.limited_reason_category === "execution_error"
|
|
) {
|
|
return { transitionId: "T10", reasons: ["blocked_or_route_mismatch_debug_status"] };
|
|
}
|
|
|
|
if (missingFilters > 0 || input.debug.limited_reason_category === "missing_anchor") {
|
|
return { transitionId: "T7", reasons: ["missing_anchor_or_filter_requires_clarification"] };
|
|
}
|
|
|
|
if (toolGateReason === "memory_recap_followup_detected") {
|
|
return { transitionId: "T9", reasons: ["memory_recap_tool_gate_reason"] };
|
|
}
|
|
|
|
if (toolGateReason === "unsupported_current_turn_meaning_boundary") {
|
|
return { transitionId: "T10", reasons: ["unsupported_current_turn_meaning_boundary"] };
|
|
}
|
|
|
|
if (hardMetaMode === "capability" || toolGateReason === "assistant_capability_query_detected") {
|
|
return { transitionId: "T8", reasons: ["capability_meta_followup_tool_gate_reason"] };
|
|
}
|
|
|
|
if (isSelectedObjectCapability(input.capabilityId)) {
|
|
if (continuationDecision === "continue_previous") {
|
|
return { transitionId: "T4", reasons: ["selected_object_capability_continue_previous"] };
|
|
}
|
|
if (continuationDecision === "new_topic") {
|
|
return { transitionId: "T3", reasons: ["selected_object_capability_explicit_entry"] };
|
|
}
|
|
return { transitionId: "T5", reasons: ["selected_object_capability_without_explicit_continuation_decision"] };
|
|
}
|
|
|
|
if (currentFrameKind === "inventory_drilldown" && targetIntent && targetIntent !== "inventory_on_hand_as_of_date") {
|
|
return { transitionId: "T6", reasons: ["root_context_reused_after_drilldown_context"] };
|
|
}
|
|
|
|
if (continuationDecision === "continue_previous") {
|
|
return { transitionId: "T2", reasons: ["root_followup_continue_previous"] };
|
|
}
|
|
|
|
if (input.capabilityId) {
|
|
return { transitionId: "T1", reasons: ["capability_contract_root_or_new_entry"] };
|
|
}
|
|
|
|
return { transitionId: null, reasons: ["transition_contract_not_resolved"] };
|
|
}
|
|
|
|
function resolveTruthGateStatus(input: {
|
|
debug: Record<string, unknown>;
|
|
groundingStatus: string | null;
|
|
explicitTruthGateStatus?: AssistantRuntimeContractShadowDecision["truth_gate_contract_status"] | null;
|
|
}): AssistantRuntimeContractShadowDecision["truth_gate_contract_status"] {
|
|
if (input.explicitTruthGateStatus) {
|
|
return input.explicitTruthGateStatus;
|
|
}
|
|
if (input.groundingStatus === "route_mismatch_blocked" || input.debug.route_expectation_status === "mismatch") {
|
|
return "blocked_route_expectation_failure";
|
|
}
|
|
if (input.debug.limited_reason_category === "execution_error") {
|
|
return "blocked_execution_error";
|
|
}
|
|
if (input.debug.limited_reason_category === "missing_anchor") {
|
|
return "blocked_missing_anchor";
|
|
}
|
|
if (
|
|
input.debug.temporal_guard_outcome === "ambiguous_limited" ||
|
|
input.debug.temporal_alignment_status === "conflicting"
|
|
) {
|
|
return "limited_temporal_or_contextual";
|
|
}
|
|
if (input.debug.limited_reason_category || input.groundingStatus === "partial") {
|
|
return "partial_supported";
|
|
}
|
|
const rowsMatched = asNumber(input.debug.rows_matched);
|
|
const routeExpectationStatus = toNonEmptyString(input.debug.route_expectation_status);
|
|
if ((input.groundingStatus === "grounded" || (rowsMatched !== null && rowsMatched > 0)) && (!routeExpectationStatus || routeExpectationStatus === "matched")) {
|
|
return "full_confirmed";
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
function carryoverEligibilityFor(
|
|
transitionId: AssistantTransitionClassId | null,
|
|
truthGateStatus: AssistantRuntimeContractShadowDecision["truth_gate_contract_status"],
|
|
explicitCarryoverEligibility?: AssistantCarryoverDepth | null
|
|
): AssistantCarryoverDepth {
|
|
if (truthGateStatus.startsWith("blocked")) {
|
|
return "none";
|
|
}
|
|
if (explicitCarryoverEligibility) {
|
|
return explicitCarryoverEligibility;
|
|
}
|
|
if (transitionId === "T3" || transitionId === "T4" || transitionId === "T5") {
|
|
return "object_only";
|
|
}
|
|
if (transitionId === "T8" || transitionId === "T9") {
|
|
return "meta_only";
|
|
}
|
|
if (transitionId === "T1" || transitionId === "T2" || transitionId === "T6") {
|
|
return "root_only";
|
|
}
|
|
if (transitionId === "T7") {
|
|
return "full";
|
|
}
|
|
return "none";
|
|
}
|
|
|
|
export function resolveAssistantRuntimeContractShadow(
|
|
input: ResolveAssistantRuntimeContractShadowInput
|
|
): AssistantRuntimeContractShadowDecision {
|
|
const debug = toRecordObject(input.addressDebug) ?? {};
|
|
const meta = runtimeMetaFrom(input);
|
|
const addressTruthGate = toAddressTruthGateContract(debug.address_truth_gate_v1);
|
|
const groundingStatus =
|
|
toNonEmptyString(input.groundingStatus) ??
|
|
toNonEmptyString(toRecordObject(debug.answer_grounding_check)?.status);
|
|
const capability = resolveCapabilityContractId(debug, meta);
|
|
const transition = resolveTransitionId({
|
|
debug,
|
|
meta,
|
|
capabilityId: capability.capabilityId,
|
|
groundingStatus
|
|
});
|
|
const transitionContract = transition.transitionId ? getAssistantTransitionContract(transition.transitionId) : null;
|
|
const truthGateStatus = resolveTruthGateStatus({
|
|
debug,
|
|
groundingStatus,
|
|
explicitTruthGateStatus: addressTruthGate?.truth_gate_status ?? null
|
|
});
|
|
return {
|
|
schema_version: ASSISTANT_RUNTIME_CONTRACTS_SCHEMA_VERSION,
|
|
transition_contract_id: transition.transitionId,
|
|
transition_contract_title: transitionContract?.title ?? null,
|
|
transition_contract_reason: transition.reasons,
|
|
capability_contract_id: capability.capabilityId,
|
|
capability_contract_reason: capability.reasons,
|
|
truth_gate_contract_status: truthGateStatus,
|
|
carryover_eligibility: carryoverEligibilityFor(
|
|
transition.transitionId,
|
|
truthGateStatus,
|
|
addressTruthGate?.carryover_eligibility ?? null
|
|
)
|
|
};
|
|
}
|
|
|
|
export function buildAssistantRuntimeContractShadowFields(
|
|
input: ResolveAssistantRuntimeContractShadowInput
|
|
): AssistantRuntimeContractShadowFields {
|
|
const decision = resolveAssistantRuntimeContractShadow(input);
|
|
return {
|
|
assistant_runtime_contract_v1: decision,
|
|
transition_contract_id: decision.transition_contract_id,
|
|
capability_contract_id: decision.capability_contract_id,
|
|
truth_gate_contract_status: decision.truth_gate_contract_status
|
|
};
|
|
}
|
|
|
|
export function attachAssistantRuntimeContractShadow<T extends Record<string, unknown>>(
|
|
debugPayload: T,
|
|
input: Omit<ResolveAssistantRuntimeContractShadowInput, "addressDebug">
|
|
): T & AssistantRuntimeContractShadowFields {
|
|
return {
|
|
...debugPayload,
|
|
...buildAssistantRuntimeContractShadowFields({
|
|
...input,
|
|
addressDebug: debugPayload
|
|
})
|
|
};
|
|
}
|