File size: 1,836 Bytes
eb1202c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | import type { Message, Part, Session } from "@opencode-ai/sdk/v2/client"
// Matches the exact `{ info, messages: [{ info, parts }] }` structure produced by `opencode export` CLI
export type SessionExportData = {
info: Session
messages: {
info: Message
parts: Part[]
}[]
}
export type SessionExportClient = {
session: {
get: (input: { sessionID: string }) => Promise<{ data?: Session | null }>
messages: (input: { sessionID: string }) => Promise<{ data?: SessionExportData["messages"] | null }>
}
}
export async function fetchSessionExport(input: {
sessionID: string
client: SessionExportClient
}): Promise<SessionExportData> {
const [sessionRes, messagesRes] = await Promise.all([
input.client.session.get({ sessionID: input.sessionID }),
input.client.session.messages({ sessionID: input.sessionID }),
])
if (!sessionRes?.data) {
throw new Error(`Session not found: ${input.sessionID}`)
}
if (!messagesRes?.data) {
throw new Error(`Failed to load messages for session: ${input.sessionID}`)
}
return {
info: sessionRes.data,
messages: messagesRes.data,
}
}
export function sessionExportFilename(session: { id: string; title?: string; slug?: string }) {
const name = session.title || session.slug || session.id
const clean = name
.toLowerCase()
.replace(/[^a-z0-9_-]+/gi, "-")
.replace(/^-+|-+$/g, "")
return `${clean || session.id}.json`
}
export function downloadSessionExport(filename: string, data: unknown) {
const json = JSON.stringify(data, null, 2)
const blob = new Blob([json], { type: "application/json" })
const url = URL.createObjectURL(blob)
const a = document.createElement("a")
a.href = url
a.download = filename
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
URL.revokeObjectURL(url)
}
|