- 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 条变异反证
37 lines
1.7 KiB
TypeScript
37 lines
1.7 KiB
TypeScript
import { useAppStore } from "../../../store/useAppStore";
|
|
|
|
/** dispatchFrame 处理的单个下行帧(信封形状,与 lib/ws.ts 导出的 dispatchFrame 签名一致)。 */
|
|
export interface FrameEvent {
|
|
type: string;
|
|
sessionId?: string;
|
|
data: unknown;
|
|
}
|
|
|
|
/** toRecord(ev.data) 解析后的帧 payload(与 lib/wsParse.ts#toRecord 的返回形状一致)。 */
|
|
export type FramePayload = Record<string, unknown> | null;
|
|
|
|
/** dispatchFrame 入口处取到的 store 快照类型,按参数传给各帧处理组。 */
|
|
export type StoreState = ReturnType<typeof useAppStore.getState>;
|
|
|
|
/** 一帧所属的会话 id:payload 里带的优先(结构化流帧在回合边界由 loop 注入),
|
|
* 其次帧壳的;两者都没有时返回 undefined,调用方据此落回「当前激活会话」。
|
|
*
|
|
* 裁决 16.4.5 后这里返回的 id 决定**写进哪个会话的消息桶**(而不是决定丢弃)。 */
|
|
export function frameSessionId(ev: FrameEvent, r: FramePayload): string | undefined {
|
|
if (r && typeof r.sessionId === "string" && r.sessionId) return r.sessionId;
|
|
return ev.sessionId || undefined;
|
|
}
|
|
|
|
/** 这帧是不是屏幕上这个会话的?只用于**单槽全局状态**的判定(忙态 / 上下文 /
|
|
* 思考累积器)—— 消息内容本身按各自的会话桶写入,不再受此限制。
|
|
*
|
|
* 激活会话尚未解析(列表没加载出来,仍是 "")时返回 true,沿用旧行为:不因为
|
|
* 会话 id 还没对上就把主人正看着的流丢掉。 */
|
|
export function frameIsActive(
|
|
sessionId: string | undefined,
|
|
activeSessionId: string
|
|
): boolean {
|
|
if (!sessionId || !activeSessionId) return true;
|
|
return sessionId === activeSessionId;
|
|
}
|