/**
 * ============================================================
 *  src/plugins/transcript.ts —— Claude Code 风格的 JSONL transcript 写入
 * ------------------------------------------------------------
 *  插件 hook（如 stop-hook.sh）通过 stdin 收到 `transcript_path` 后
 *  会 grep / jq 这份 JSONL 文件来还原对话。schema 必须与 Anthropic
 *  Claude Code 真实 transcript 对齐：每行一个 JSON 对象，形如
 *    { type, uuid, session_id, timestamp, message: { role, content: [...parts] } }
 *  content 为 typed parts 数组：text / tool_use / tool_result。
 *
 *  设计要点：
 *   - OpenAI 风格的 assistant.tool_calls 在这里被拍平成 content 数组
 *     里的 tool_use parts（Claude Code 的真实格式）
 *   - tool role 消息被包装成 type:'user' + tool_result part（上游惯例）
 *   - 同步 appendFileSync —— spawn 的 hook 子进程要立刻看到最新内容
 *   - 任何写入异常都被吞掉只 warn —— transcript 失败绝不能拖垮 agent
 *   - 零依赖（只用 node 内置）
 *
 *  存储位置：~/.minimal-agent/transcripts/<sessionId>.jsonl
 * ============================================================
 */
import { appendFileSync, mkdirSync } from 'node:fs';
import { homedir } from 'node:os';
import { join } from 'node:path';
import { randomUUID } from 'node:crypto';
// 模块级状态：当前会话的 handle（lazy 初始化）
let current = null;
function transcriptDir() {
    return join(homedir(), '.minimal-agent', 'transcripts');
}
function generateSessionId() {
    return `${Date.now().toString(36)}-${randomUUID().slice(0, 8)}`;
}
function ensureHandle(sessionId) {
    // 如果指定了 sessionId 且与当前不同 → 切到新文件
    if (sessionId && current && current.sessionId === sessionId) {
        return current;
    }
    if (!sessionId && current) {
        return current;
    }
    const sid = sessionId ?? generateSessionId();
    const dir = transcriptDir();
    try {
        mkdirSync(dir, { recursive: true });
    }
    catch (err) {
        console.warn(`[transcript] mkdir failed: ${err instanceof Error ? err.message : String(err)}`);
    }
    const handle = {
        sessionId: sid,
        path: join(dir, `${sid}.jsonl`),
    };
    current = handle;
    return handle;
}
function writeLine(line) {
    try {
        const handle = ensureHandle();
        appendFileSync(handle.path, `${JSON.stringify(line)}\n`, 'utf8');
    }
    catch (err) {
        console.warn(`[transcript] write failed: ${err instanceof Error ? err.message : String(err)}`);
    }
}
function nowIso() {
    return new Date().toISOString();
}
/**
 * 初始化 transcript：在 ~/.minimal-agent/transcripts/ 下打开 <sessionId>.jsonl。
 * 如果未提供 sessionId，用时间戳 + 随机后缀生成。
 * 多次调用同一 sessionId 会复用同一文件（append）。
 */
export function initTranscript(sessionId) {
    // 显式 init：即便 current 已存在也允许切换到指定 sessionId
    if (sessionId) {
        const dir = transcriptDir();
        try {
            mkdirSync(dir, { recursive: true });
        }
        catch (err) {
            console.warn(`[transcript] mkdir failed: ${err instanceof Error ? err.message : String(err)}`);
        }
        current = {
            sessionId,
            path: join(dir, `${sessionId}.jsonl`),
        };
        return current;
    }
    return ensureHandle();
}
/** 获取当前会话的 transcript 路径。未 init 时 lazy 初始化。 */
export function getCurrentTranscriptPath() {
    return ensureHandle().path;
}
/** 追加一条 user 消息。 */
export function appendUserMessage(content) {
    const handle = ensureHandle();
    writeLine({
        type: 'user',
        uuid: randomUUID(),
        session_id: handle.sessionId,
        timestamp: nowIso(),
        message: {
            role: 'user',
            content: [{ type: 'text', text: content }],
        },
    });
}
/** 追加一条 assistant 消息。tool_calls 转成 content 数组里的 tool_use parts。 */
export function appendAssistantMessage(message) {
    const handle = ensureHandle();
    const parts = [];
    // 文本部分：null / 空字符串都跳过
    if (typeof message.content === 'string' && message.content.length > 0) {
        parts.push({ type: 'text', text: message.content });
    }
    // tool_calls 拍平成 tool_use parts
    if (Array.isArray(message.tool_calls)) {
        for (const tc of message.tool_calls) {
            let input;
            try {
                input = JSON.parse(tc.function.arguments);
            }
            catch {
                input = { _raw: tc.function.arguments };
            }
            parts.push({
                type: 'tool_use',
                id: tc.id,
                name: tc.function.name,
                input,
            });
        }
    }
    writeLine({
        type: 'assistant',
        uuid: randomUUID(),
        session_id: handle.sessionId,
        timestamp: nowIso(),
        message: {
            role: 'assistant',
            content: parts,
        },
    });
}
/** 追加一条 tool 执行结果（来自 tool role 消息）。 */
export function appendToolResult(toolCallId, _toolName, ok, content) {
    const handle = ensureHandle();
    writeLine({
        type: 'user',
        uuid: randomUUID(),
        session_id: handle.sessionId,
        timestamp: nowIso(),
        message: {
            role: 'user',
            content: [
                {
                    type: 'tool_result',
                    tool_use_id: toolCallId,
                    content,
                    is_error: !ok,
                },
            ],
        },
    });
}
/** 重置当前 handle（用于测试 / /new 清屏后开新 session）。 */
export function resetTranscript() {
    current = null;
}
