/** * BSO M9.5 — /deny-review/:task_id HTML 审阅页 + elicitation/complete 事件流 * * Refs: docs/prd/PRD-BSO-M9-HARNESS-HOOKS.md §3.3.4 * * 用户在浏览器里看到这个页面后: * - "同意" → POST /deny-review/:task_id/approve → reviewStore.decide → 广播 complete 事件 * - "修改" → POST /deny-review/:task_id/modify → 同上 (decision='modified') * - "撤销" → POST /deny-review/:task_id/cancel → 同上 (decision='cancelled') * * 事件订阅(M9.5 L2-4): * - SSE: GET /internal/mcp/elicitation/stream?elicitationId= * - Polling: GET /internal/mcp/elicitation/poll?elicitationId= * * 注:MCP host 的"自动 retry"由 SkillFM MCP bridge(P1+ 独立进程)拿到 complete 事件 * 后通过 MCP transport 转发 notifications/elicitation/complete 给 client。本文件 * 只负责 sidecar 侧事件源 + 订阅接口。 */ import { EventEmitter } from 'node:events'; import type { RejectInput } from './types.js'; export type ReviewDecision = 'pending' | 'approved' | 'cancelled' | 'modified'; export interface ReviewRecord { task_id: string; decision: ReviewDecision; created_at: number; decided_at?: number; reject: RejectInput; /** 与 MCP -32042 envelope 内 elicitations[].elicitationId 配对 */ elicitation_id?: string; } /** * MCP 标准 notifications/elicitation/complete payload。 * client 拿到后会自动 retry 原 tool call。 */ export interface ElicitationCompletePayload { jsonrpc: '2.0'; method: 'notifications/elicitation/complete'; params: { elicitationId: string; /** MCP spec 三态 */ action: 'accept' | 'decline' | 'cancel'; /** SkillFM 自定义补充字段 */ skillfm_decision: ReviewDecision; decided_at: number; }; } export declare function buildElicitationCompletePayload(rec: ReviewRecord): ElicitationCompletePayload | null; declare class ReviewStore extends EventEmitter { private store; /** elicitation_id → task_id 反向索引(订阅按 elicitationId 走,broadcast 按 elicitationId)*/ private elicitationIndex; open(input: RejectInput, elicitation_id?: string): ReviewRecord; decide(task_id: string, decision: Exclude): ReviewRecord | null; get(task_id: string): ReviewRecord | null; getByElicitationId(elicitation_id: string): ReviewRecord | null; list(): ReviewRecord[]; /** 测试用:清空 */ reset(): void; } export declare const reviewStore: ReviewStore; export declare function renderReviewPage(rec: ReviewRecord): string; export declare function renderNotFoundPage(taskId: string): string; export {}; //# sourceMappingURL=deny-review.d.ts.map