import type { AssistantMcpDiscoveryRuntimeEntryPointContract } from "./assistantMcpDiscoveryRuntimeEntryPoint"; import type { AssistantMcpRouteCandidateContract } from "./assistantMcpDiscoveryRuntimeBridge"; import type { AssistantEvidencePlannerContract } from "./assistantEvidencePlanner"; export interface AssistantMcpDiscoveryDebugAttachmentFields { assistant_mcp_discovery_entry_point_v1: AssistantMcpDiscoveryRuntimeEntryPointContract | null; mcp_discovery_entry_status: string | null; mcp_discovery_attempted: boolean; mcp_discovery_hot_runtime_wired: false; mcp_discovery_bridge_status: string | null; mcp_discovery_selected_chain_id: string | null; mcp_discovery_evidence_plan_v1: AssistantEvidencePlannerContract | null; mcp_discovery_evidence_plan_status: string | null; mcp_discovery_evidence_plan_answer_mode: string | null; mcp_discovery_evidence_plan_missing_axes: string[]; mcp_discovery_evidence_plan_expected_coverage: string | null; mcp_discovery_catalog_chain_template_matches: string[]; mcp_discovery_catalog_chain_alignment_status: string | null; mcp_discovery_catalog_chain_top_match: string | null; mcp_discovery_catalog_chain_selected_matches_top: boolean; mcp_discovery_route_candidate_v1: AssistantMcpRouteCandidateContract | null; mcp_discovery_route_candidate_status: string | null; mcp_discovery_route_candidate_fact_family: string | null; mcp_discovery_route_candidate_action_family: string | null; mcp_discovery_route_candidate_proof_expectation: string | null; mcp_discovery_route_candidate_missing_axes: string[]; mcp_discovery_route_candidate_provided_axes: string[]; mcp_discovery_route_candidate_executable_now: boolean; mcp_discovery_route_candidate_enablement_reason: string | null; mcp_discovery_route_candidate_next_action: string | null; mcp_discovery_answer_mode: string | null; mcp_discovery_business_fact_answer_allowed: boolean; mcp_discovery_user_facing_response_allowed: boolean; mcp_discovery_requires_clarification: boolean; } export interface AttachAssistantMcpDiscoveryDebugInput { entryPoint?: unknown; addressRuntimeMeta?: Record | null; } function toRecordObject(value: unknown): Record | null { if (!value || typeof value !== "object" || Array.isArray(value)) { return null; } return value as Record; } 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 toStringArray(value: unknown): string[] { if (!Array.isArray(value)) { return []; } const result: string[] = []; for (const item of value) { const text = toNonEmptyString(item); if (text && !result.includes(text)) { result.push(text); } } return result; } function isMcpDiscoveryEntryPointContract(value: unknown): value is AssistantMcpDiscoveryRuntimeEntryPointContract { const record = toRecordObject(value); return ( record?.schema_version === "assistant_mcp_discovery_runtime_entry_point_v1" && record?.policy_owner === "assistantMcpDiscoveryRuntimeEntryPoint" ); } function isRouteCandidateContract(value: unknown): value is AssistantMcpRouteCandidateContract { const record = toRecordObject(value); return ( record?.schema_version === "assistant_mcp_route_candidate_v1" && record?.policy_owner === "assistantMcpDiscoveryRuntimeBridge" ); } function isEvidencePlannerContract(value: unknown): value is AssistantEvidencePlannerContract { const record = toRecordObject(value); return record?.schema_version === "assistant_evidence_planner_v1" && record?.policy_owner === "assistantEvidencePlanner"; } function resolveEntryPoint(input: AttachAssistantMcpDiscoveryDebugInput): AssistantMcpDiscoveryRuntimeEntryPointContract | null { if (isMcpDiscoveryEntryPointContract(input.entryPoint)) { return input.entryPoint; } const runtimeMetaEntryPoint = input.addressRuntimeMeta?.mcpDiscoveryRuntimeEntryPoint ?? input.addressRuntimeMeta?.assistantMcpDiscoveryRuntimeEntryPoint ?? input.addressRuntimeMeta?.assistant_mcp_discovery_entry_point_v1; return isMcpDiscoveryEntryPointContract(runtimeMetaEntryPoint) ? runtimeMetaEntryPoint : null; } export function buildAssistantMcpDiscoveryDebugAttachmentFields( input: AttachAssistantMcpDiscoveryDebugInput ): AssistantMcpDiscoveryDebugAttachmentFields { const entryPoint = resolveEntryPoint(input); const bridge = toRecordObject(entryPoint?.bridge); const planner = toRecordObject(bridge?.planner); const evidencePlan = isEvidencePlannerContract(planner?.evidence_plan) ? planner.evidence_plan : null; const evidencePlanAxes = toRecordObject(evidencePlan?.evidence_axes); const evidencePlanCoverageGate = toRecordObject(evidencePlan?.coverage_gate); const evidencePlanAnswerContract = toRecordObject(evidencePlan?.answer_contract); const chainAlignment = toRecordObject(planner?.catalog_chain_template_alignment); const routeCandidate = isRouteCandidateContract(bridge?.route_candidate) ? bridge.route_candidate : null; const answerDraft = toRecordObject(bridge?.answer_draft); return { assistant_mcp_discovery_entry_point_v1: entryPoint, mcp_discovery_entry_status: toNonEmptyString(entryPoint?.entry_status), mcp_discovery_attempted: Boolean(entryPoint?.discovery_attempted), mcp_discovery_hot_runtime_wired: false, mcp_discovery_bridge_status: toNonEmptyString(bridge?.bridge_status), mcp_discovery_selected_chain_id: toNonEmptyString(planner?.selected_chain_id), mcp_discovery_evidence_plan_v1: evidencePlan, mcp_discovery_evidence_plan_status: toNonEmptyString(evidencePlan?.planner_status), mcp_discovery_evidence_plan_answer_mode: toNonEmptyString(evidencePlanAnswerContract?.answer_mode), mcp_discovery_evidence_plan_missing_axes: toStringArray(evidencePlanAxes?.missing_axes), mcp_discovery_evidence_plan_expected_coverage: toNonEmptyString(evidencePlanCoverageGate?.expected_coverage), mcp_discovery_catalog_chain_template_matches: toStringArray(planner?.catalog_chain_template_matches), mcp_discovery_catalog_chain_alignment_status: toNonEmptyString(chainAlignment?.alignment_status), mcp_discovery_catalog_chain_top_match: toNonEmptyString(chainAlignment?.top_chain_template_match), mcp_discovery_catalog_chain_selected_matches_top: chainAlignment?.selected_chain_matches_top === true, mcp_discovery_route_candidate_v1: routeCandidate, mcp_discovery_route_candidate_status: toNonEmptyString(routeCandidate?.candidate_status), mcp_discovery_route_candidate_fact_family: toNonEmptyString(routeCandidate?.business_fact_family), mcp_discovery_route_candidate_action_family: toNonEmptyString(routeCandidate?.action_family), mcp_discovery_route_candidate_proof_expectation: toNonEmptyString(routeCandidate?.proof_expectation), mcp_discovery_route_candidate_missing_axes: toStringArray(routeCandidate?.missing_axes), mcp_discovery_route_candidate_provided_axes: toStringArray(routeCandidate?.provided_axes), mcp_discovery_route_candidate_executable_now: routeCandidate?.executable_now === true, mcp_discovery_route_candidate_enablement_reason: toNonEmptyString(routeCandidate?.enablement_reason), mcp_discovery_route_candidate_next_action: toNonEmptyString(routeCandidate?.recommended_next_action), mcp_discovery_answer_mode: toNonEmptyString(answerDraft?.answer_mode), mcp_discovery_business_fact_answer_allowed: bridge?.business_fact_answer_allowed === true, mcp_discovery_user_facing_response_allowed: bridge?.user_facing_response_allowed === true, mcp_discovery_requires_clarification: bridge?.requires_user_clarification === true }; } export function attachAssistantMcpDiscoveryDebug>( debugPayload: T, input: AttachAssistantMcpDiscoveryDebugInput ): T & AssistantMcpDiscoveryDebugAttachmentFields { return { ...debugPayload, ...buildAssistantMcpDiscoveryDebugAttachmentFields(input) }; }