- 16.4.5:非激活会话的帧**不再丢弃**,按自己的 sessionId 落进该会话桶(新增 store/sessionCache.ts 纯函数 + useAppStore.sessionMessages/flowGraphs);切会话改为「存回/取出」而非清空;流式增量 O(1) 定位桶、 只延长已存在的助手气泡(不凭一帧 delta 凭空造消息) - 16.4.2:图按会话入桶(上限 12 个),Backthink 页取 sess-backthink 的图而不再被用户会话图顶替; 空态区分「实时通道未连接」与「尚未产生链路图」;wire_runtime 的图源白名单注释按裁决口径重写(零行为改动) - 修 16.4.1 的缺口:handlers/session.ts 补 `session_idle` / `session_interrupted`(此前落到未知帧兜底 ⇒ sessionBusy 可能卡 true ⇒ 预约永不落地);忙态**置忙与置闲两侧**统一按 frameIsActive 过滤(只过滤置闲 会让后台会话的忙帧点亮徽标而它自己的 idle 被丢 ⇒ 永久卡忙) - 清理:删除 lib/streamScope.ts(口径已被 16.4.5 推翻)与只剩测试在用的 messageEventApplies - 复核:tsc 0 错 + vite build 成功;messageSync 69 / session 19 项逻辑测试;4 条变异反证
28 lines
1.6 KiB
TypeScript
28 lines
1.6 KiB
TypeScript
import { frameIsActive, frameSessionId, type FrameEvent, type FramePayload, type StoreState } from "./shared";
|
|
|
|
/** 代审帧处理组:approval_notice —— 主代理代审小字(design/11 §4,裁决 13.4.3)。
|
|
* 敏感操作(如 terminal)经代审后后端广播该帧,`explain` 是后端产出的固定文案
|
|
* 「xxx 想要干什么,我审查后批准了 / 拒绝了」,前端原样渲染成聊天流里的一行小字。
|
|
* 命中返回 true,未命中返回 false 交给下一组。 */
|
|
export function handleApprovalEvent(ev: FrameEvent, r: FramePayload, s: StoreState): boolean {
|
|
if (ev.type !== "approval_notice") return false;
|
|
// 小字是单槽状态,只认屏幕上这个会话:别的会话发生的代审不写进当前会话
|
|
// (与 stream_end / 忙态同一判据:shared 的 frameIsActive)。
|
|
if (!frameIsActive(frameSessionId(ev, r), s.activeSessionId)) return true;
|
|
// 没有文案就没有可渲染的小字 —— 丢掉这帧,而不是编造一句。
|
|
const explain = typeof r?.explain === "string" ? r.explain : "";
|
|
if (!explain) return true;
|
|
s.setApprovalNotice({
|
|
explain,
|
|
actor: typeof r?.actor === "string" ? r.actor : "",
|
|
tool: typeof r?.tool === "string" ? r.tool : "",
|
|
op: typeof r?.op === "string" ? r.op : "",
|
|
detail: typeof r?.detail === "string" ? r.detail : "",
|
|
// 后端只在整条代审失败/拒绝时发 allowed=false;缺字段按「已批准」处理,
|
|
// 与后端 RecordApproval 写入的布尔一致。
|
|
allowed: r?.allowed !== false,
|
|
at: typeof r?.at === "string" ? r.at : "",
|
|
});
|
|
return true;
|
|
}
|