feat(web): 前端与后端同步一批(帧壳 turnId / 并行六态与两级分桶 / documents 渲染 / System 键名 / 主人档案分组)
- 帧壳 `turnId` 在 socket 层不再被丢(`lib/ws.ts` 的 dispatchFrame 补 turnId/seq)—— 按路分桶的前提 - 并行帧组接入:`turn_begin` / `steer_ack` / `pending_ack` / `pending_drain` / `pending_full` / `chat_duplicate` ⇒ 六态 + 灰态 + `(sessionId, turnId)` 两级分桶;`appendChunk` 不再永远写尾气泡 - 多路忙态:`session_interrupted` 不再无条件当空闲(看 mode/activeTurns);`stream_end` 不再只按会话过滤 - `documents` 渲染(含 status/chars/truncated 与**逐字中文 reason**);`turnId` 历史行分组小标 - `System.tsx` 键名改正(真键 HOST/PORT/ADMIN_USERNAME/ADMIN_PASSWORD,避免照抄静默失效) - 主人档案**按平台分组** + 平台下拉 + 账号候选;**写盘仍展平数组**(后端契约不变) - 验证:tsc --noEmit ✅、npm run build ✅、22 个前端测试文件全通过(本次新增 3 文件 108 条断言) - 未做(如实):握手 history handler 与断线补拉、上行 interrupt 按钮、proactive_message/subagent_result 等帧落点、文档上传入口与图片预检、voice 管线、System 的 env 读端点
This commit is contained in:
1 parent
6a545badbd
commit
eaada3af5d
34 files changed
+2457
-223
No files matched your search
@@ -48,7 +48,17 @@ export function handleMessageEvent(ev: FrameEvent, r: FramePayload, s: StoreStat
|
||||
// dedups by id and adopts the local optimistic bubble (uid → backend id), so
|
||||
// both the originating and remote browsers converge on one message.
|
||||
const msg = parsePersistedMessage(r?.message);
|
||||
if (msg) s.appendOrUpdateMessage(msg);
|
||||
if (msg) {
|
||||
s.appendOrUpdateMessage(msg);
|
||||
// `turn_begin` 可能早于用户行落库到达(那时 messageIds 在列表里还没有落点,
|
||||
// 绑定只记在 turnBindings 里):这里补一次落地,让气泡及时进灰态。
|
||||
s.rebindSessionTurns(msg.sessionId ?? s.activeSessionId);
|
||||
// 灰态的**兜底**收口(规范草案 §1.2):该 `turnId` 的助手回复落库同样收口,
|
||||
// 它与 `turn.end` 顺序不定,任一到即收。
|
||||
if (msg.role === "assistant" && msg.turnId) {
|
||||
s.clearGrey(msg.turnId, msg.sessionId ?? s.activeSessionId);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case "message_edited": {
|
||||
|
||||
Reference in new issue
Block a user