| 992 | }, |
| 993 | optimistic: { |
| 994 | add(input: { sessionID: string; message: Message; parts: Part[] }) { |
| 995 | const parts = input.parts |
| 996 | .filter((part) => !!part?.id && !SKIP_PARTS.has(part.type)) |
| 997 | .sort((a, b) => cmp(a.id, b.id)) |
| 998 | const load = messageLoads.get(input.sessionID) |
| 999 | if (load?.clearedMessageParts.has(input.message.id)) { |
| 1000 | const touched = load.touchedParts.get(input.message.id) ?? new Set<string>() |
| 1001 | parts.forEach((part) => touched.add(part.id)) |
| 1002 | load.touchedParts.set(input.message.id, touched) |
| 1003 | } |
| 1004 | if (load) { |
| 1005 | load.removedMessages.delete(input.message.id) |
| 1006 | load.optimisticParts.set(input.message.id, new Set(parts.map((part) => part.id))) |
| 1007 | } |
| 1008 | const items = optimistic.get(input.sessionID) |
| 1009 | const removedMessagesForSession = removedMessages.get(input.sessionID) |
| 1010 | removedMessagesForSession?.delete(input.message.id) |
| 1011 | if (removedMessagesForSession?.size === 0) removedMessages.delete(input.sessionID) |
| 1012 | if (items) items.set(input.message.id, { ...input, parts, confirmedParts: [] }) |
| 1013 | if (!items) |
| 1014 | optimistic.set(input.sessionID, new Map([[input.message.id, { ...input, parts, confirmedParts: [] }]])) |
| 1015 | setData("message", input.sessionID, (messages = []) => merge(messages, [input.message])) |
| 1016 | setData( |
| 1017 | "part_text_accum_delta", |
| 1018 | produce((draft) => { |
| 1019 | for (const part of [...(data.part[input.message.id] ?? []), ...parts]) { |
| 1020 | delete draft[part.id] |
| 1021 | deltaBases.delete(part.id) |
| 1022 | } |
| 1023 | }), |
| 1024 | ) |
| 1025 | setData("part", input.message.id, parts) |
| 1026 | }, |
| 1027 | remove(input: { sessionID: string; messageID: string }) { |
| 1028 | const item = optimistic.get(input.sessionID)?.get(input.messageID) |
| 1029 | if (!item) return |