/
Alex_Ural
/
opencode
Обзор
Документация
Войти
/
Alex_Ural
/
opencode
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
packages/tui/src/util/transcript.ts
112 строк
3 KB
Dax
refactor(server): canonicalize service API (#31049)
07 июн 2026, 06:27
Не верифицирован
07 июн 2026, 06:27
fe0c4f8
Код
Авторство
О чём код?
import type { AssistantMessage, Part, Provider, UserMessage } from "@opencode-ai/sdk/v2" import { Locale } from "./locale" import * as Model from "./model" export type TranscriptOptions = { thinking: boolean toolDetails: boolean assistantMetadata: boolean providers?: Provider[] } export type SessionInfo = { id: string title: string time: { created: number updated: number } } export type MessageWithParts = { info: UserMessage | AssistantMessage parts: Part[] } export function formatTranscript( session: SessionInfo, messages: MessageWithParts[], options: TranscriptOptions, ): string { const providers = Model.index(options.providers) let transcript = `# ${session.title}\n\n` transcript += `**Session ID:** ${session.id}\n` transcript += `**Created:** ${new Date(session.time.created).toLocaleString()}\n` transcript += `**Updated:** ${new Date(session.time.updated).toLocaleString()}\n\n` transcript += `---\n\n` for (const msg of messages) { transcript += formatMessage(msg.info, msg.parts, options, providers) transcript += `---\n\n` } return transcript } export function formatMessage( msg: UserMessage | AssistantMessage, parts: Part[], options: TranscriptOptions, providers?: Provider[] | ReadonlyMap<string, Provider>, ): string { let result = "" if (msg.role === "user") { result += `## User\n\n` } else { result += formatAssistantHeader(msg, options.assistantMetadata, providers ?? options.providers) } for (const part of parts) { result += formatPart(part, options) } return result } export function formatAssistantHeader( msg: AssistantMessage, includeMetadata: boolean, providers?: Provider[] | ReadonlyMap<string, Provider>, ): string { if (!includeMetadata) { return `## Assistant\n\n` } const duration = msg.time.completed && msg.time.created ? ((msg.time.completed - msg.time.created) / 1000).toFixed(1) + "s" : "" const modelName = Model.name(providers, msg.providerID, msg.modelID) return `## Assistant (${Locale.titlecase(msg.agent)} · ${modelName}${duration ? ` · ${duration}` : ""})\n\n` } export function formatPart(part: Part, options: TranscriptOptions): string { if (part.type === "text" && !part.synthetic) { return `${part.text}\n\n` } if (part.type === "reasoning") { if (options.thinking) { return `_Thinking:_\n\n${part.text}\n\n` } return "" } if (part.type === "tool") { let result = `**Tool: ${part.tool}**\n` if (options.toolDetails && part.state.input) { result += `\n**Input:**\n\`\`\`json\n${JSON.stringify(part.state.input, null, 2)}\n\`\`\`\n` } if (options.toolDetails && part.state.status === "completed" && part.state.output) { result += `\n**Output:**\n\`\`\`\n${part.state.output}\n\`\`\`\n` } if (options.toolDetails && part.state.status === "error" && part.state.error) { result += `\n**Error:**\n\`\`\`\n${part.state.error}\n\`\`\`\n` } result += `\n` return result } return "" }