1import { DatabaseSync } from 'node:sqlite' 2import { homedir } from 'os' 3import { join } from 'path' 5export const ocDbPath = join(homedir(), '.local/share/opencode/opencode.db') 7let db: InstanceType<typeof DatabaseSync> | null = null 8export const getOcDb = () => db ||= new DatabaseSync(ocDbPath, { open: true, readOnly: true }) 10export const getOcSession = (sessionId: string) => getOcDb().prepare('SELECT * FROM session WHERE id = ?').get(sessionId) as Record<string, unknown> | undefined 12export const getOcMessages = (sessionId: string) => { 13 const rows = getOcDb().prepare('SELECT id, data FROM message WHERE session_id = ? ORDER BY time_created').all(sessionId) as Record<string, any>[] 14 return rows.map(r => ({ id: r.id, ...JSON.parse(r.data) })) 17export const getOcParts = (sessionId: string, { withTime = false } = {}) => { 18 const cols = withTime ? 'message_id, time_created, data' : 'message_id, data' 19 const rows = getOcDb().prepare(`SELECT ${cols} FROM part WHERE session_id = ? ORDER BY time_created`).all(sessionId) as Record<string, any>[] 20 return rows.map(r => { 21 const parsed: Record<string, unknown> = { messageId: r.message_id, ...JSON.parse(r.data) } 22 if (withTime) parsed.dbTime = r.time_created 27export const groupPartsByMsg = (parts: Record<string, any>[]) => { 28 const partsByMsg: Record<string, Record<string, unknown>[]> = {} 29 for (const p of parts) { 30 partsByMsg[p.messageId] ||= [] 31 partsByMsg[p.messageId].push(p) 36export const loadOcSessionData = (sessionId: string, { withTime = false } = {}) => { 37 const session = getOcSession(sessionId) 38 if (!session) return null 39 const messages = getOcMessages(sessionId) 40 const parts = getOcParts(sessionId, { withTime }) 41 const partsByMsg = groupPartsByMsg(parts) 42 return { session, messages, partsByMsg } 45export const truncateStr = (s: string | undefined, len: number) => s && s.length > len ? s.slice(0, len - 1) + '…' : s