feat(web): 前端 P0 收尾(多路忙态收口 / 握手 history 落 store / 清理幽灵键)
This commit is contained in:
1 parent
e852e60af9
commit
012e9f3ad4
10 files changed
+365
-31
No files matched your search
@@ -18,6 +18,7 @@ import { now, uid } from "../lib/util";
|
||||
import {
|
||||
currentGraph,
|
||||
dropMessage,
|
||||
mergeHistory,
|
||||
mergeMessage,
|
||||
patchAssistantTail,
|
||||
patchMessage,
|
||||
@@ -144,6 +145,13 @@ export interface AppStore extends TurnSlice {
|
||||
* renders twice (design/16 §4.3 dedup). A message without a session id (a local
|
||||
* optimistic bubble) belongs to the active session. */
|
||||
appendOrUpdateMessage: (msg: ChatMessage) => void;
|
||||
/** Merge one handshake `history` replay page (contract §3.2) into the session the
|
||||
* frame names — up to 50 already-persisted rows, once per (re)connect. Dedup by
|
||||
* id and adopt a local optimistic bubble only on an exact key (`clientMsgId` for
|
||||
* users / `turnId` for assistants), never by the content/time heuristic: this is
|
||||
* the reconnect catch-up path, so a wrong adopt would rewrite a streaming bubble
|
||||
* with an old reply. */
|
||||
mergeHistoryPage: (sessionId: string, msgs: ChatMessage[]) => void;
|
||||
/** Patch one already-rendered message in place by id — the `message_edited` WS
|
||||
* path. With `sessionId` the patch is confined to that session's bucket; without
|
||||
* one the id is searched across the active list and every bucket (ids are
|
||||
@@ -280,6 +288,14 @@ export const useAppStore = create<AppStore>()(
|
||||
)
|
||||
),
|
||||
|
||||
mergeHistoryPage: (sessionId, list) =>
|
||||
set((s) => {
|
||||
if (!list.length) return s;
|
||||
return writeSession(s, sessionId || s.activeSessionId, (cur) =>
|
||||
mergeHistory(cur, list)
|
||||
);
|
||||
}),
|
||||
|
||||
updateMessageById: (id, patch, sessionId) =>
|
||||
set((s) =>
|
||||
writeSessionById(s, sessionId, (list) => patchMessage(list, id, patch))
|
||||
|
||||
Reference in new issue
Block a user