diff options
| author | Adam Malczewski <[email protected]> | 2026-05-27 18:35:18 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-05-27 18:35:18 +0900 |
| commit | ca6ee91c5e1167b1929eedbb96c76dfa24e7d026 (patch) | |
| tree | bc23acac2e7caaf2e59eacbc21bfc9b41f3c1458 /packages/core/src/db | |
| parent | da57842686ebfd157396551fc76d0c18f7676335 (diff) | |
| download | dispatch-ca6ee91c5e1167b1929eedbb96c76dfa24e7d026.tar.gz dispatch-ca6ee91c5e1167b1929eedbb96c76dfa24e7d026.zip | |
refactor: ChatMessage.chunks[] union — interleaved thinking, tool batching, error/system chunks
Diffstat (limited to 'packages/core/src/db')
| -rw-r--r-- | packages/core/src/db/index.ts | 1 | ||||
| -rw-r--r-- | packages/core/src/db/messages.ts | 68 |
2 files changed, 47 insertions, 22 deletions
diff --git a/packages/core/src/db/index.ts b/packages/core/src/db/index.ts index 81b474e..e63b266 100644 --- a/packages/core/src/db/index.ts +++ b/packages/core/src/db/index.ts @@ -99,7 +99,6 @@ export function getDatabase(): Database { seq INTEGER NOT NULL, role TEXT NOT NULL, content_json TEXT NOT NULL, - thinking TEXT, created_at INTEGER NOT NULL )`); diff --git a/packages/core/src/db/messages.ts b/packages/core/src/db/messages.ts index 80a1f22..34b69e5 100644 --- a/packages/core/src/db/messages.ts +++ b/packages/core/src/db/messages.ts @@ -1,21 +1,29 @@ +import type { Chunk, MessageRole } from "../types/index.js"; import { getDatabase } from "./index.js"; +/** + * A persisted message row, with `content_json` already parsed into a `Chunk[]`. + * Mirrors the new schema (no `thinking` column — that lived under the old + * `content + toolCalls + toolResults + thinking` model). + */ export interface MessageRow { id: string; tabId: string; seq: number; - role: string; - contentJson: string; - thinking: string | null; + role: MessageRole; + chunks: Chunk[]; createdAt: number; } +/** + * Append a new message to the tab. Caller passes the already-serialized + * chunk list as `contentJson` (i.e. `JSON.stringify(chunks)`). + */ export function appendMessage( tabId: string, id: string, - role: string, + role: MessageRole, contentJson: string, - thinking?: string, ): void { const db = getDatabase(); const maxSeq = db @@ -23,40 +31,58 @@ export function appendMessage( .get({ $tabId: tabId }) as { max_seq: number }; const seq = (maxSeq?.max_seq ?? -1) + 1; db.query( - `INSERT INTO messages (id, tab_id, seq, role, content_json, thinking, created_at) - VALUES ($id, $tabId, $seq, $role, $contentJson, $thinking, $now)`, + `INSERT INTO messages (id, tab_id, seq, role, content_json, created_at) + VALUES ($id, $tabId, $seq, $role, $contentJson, $now)`, ).run({ $id: id, $tabId: tabId, $seq: seq, $role: role, $contentJson: contentJson, - $thinking: thinking ?? null, $now: Date.now(), }); } -export function updateMessage(id: string, contentJson: string, thinking?: string): void { +/** + * Replace the persisted chunks for an existing message. `contentJson` is + * the already-serialized chunk list. + */ +export function updateMessage(id: string, contentJson: string): void { const db = getDatabase(); - db.query( - "UPDATE messages SET content_json = $contentJson, thinking = $thinking WHERE id = $id", - ).run({ $id: id, $contentJson: contentJson, $thinking: thinking ?? null }); + db.query("UPDATE messages SET content_json = $contentJson WHERE id = $id").run({ + $id: id, + $contentJson: contentJson, + }); } +/** + * Read all messages for a tab in seq order. `content_json` is parsed into + * `Chunk[]` here so callers don't have to. If a row's JSON is malformed, + * the message is returned with an empty chunk list rather than throwing. + */ export function getMessagesForTab(tabId: string): MessageRow[] { const db = getDatabase(); const rows = db .query("SELECT * FROM messages WHERE tab_id = $tabId ORDER BY seq ASC") .all({ $tabId: tabId }) as Array<Record<string, unknown>>; - return rows.map((row) => ({ - id: row.id as string, - tabId: row.tab_id as string, - seq: row.seq as number, - role: row.role as string, - contentJson: row.content_json as string, - thinking: row.thinking as string | null, - createdAt: row.created_at as number, - })); + return rows.map((row) => { + const rawJson = row.content_json as string; + let chunks: Chunk[]; + try { + const parsed = JSON.parse(rawJson); + chunks = Array.isArray(parsed) ? (parsed as Chunk[]) : []; + } catch { + chunks = []; + } + return { + id: row.id as string, + tabId: row.tab_id as string, + seq: row.seq as number, + role: row.role as MessageRole, + chunks, + createdAt: row.created_at as number, + }; + }); } export function clearMessagesForTab(tabId: string): void { |
