/**
* 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