# dsh-chat-log 中文 | [English](README.md) 把 DSH Session 日志**整理成正常聊天**:流式 chunk 碎片折叠为完整消息,其余内容**一行不丢、逐字保留**。一键下载,或使用 `/chat` 命令——与官方"Session log"ZIP 按钮并存。 ![npm](https://img.shields.io/npm/v/dsh-chat-log) ![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg) ## 为什么 官方 `@deepseek-ai/dsh-session-log-export` 下载的 ZIP 里是原始日志:`session.jsonl`(或 zstd 多帧压缩),其中**超过 8 成行数是 token 级流式增量碎片**(`assistant/chunk`、`reasoning-chunks`、`text-chunks`、`tool-call-chunks`)——想阅读或复用要先在成千上万条碎片行里爬。 `dsh-chat-log` 以日志中的**权威折叠事件**(`user/message`、`assistant/message`、`tool/call`、`tool/result`)为内容来源构建可读的聊天树,其余事件(权限、审批、请求上下文、生命周期等)**逐字保留**在 `events` 里。 > 关于保真度:碎片增量与权威折叠偶有字符级差异(实测发现工具调用参数缺个闭合引号的个案)。本插件**始终以权威折叠为准**,比对结果写入 `report`。 ## 特性对比 | | 官方 `/export` | 本插件 | |---|---|---| | 输出 | 原始日志 ZIP(浏览器下载) | **干净的嵌套聊天 JSON**(`dsh-chat.v1`) | | 流式碎片 | 原样打包(占 80%+ 行数) | **折叠为完整消息** | | 其余内容 | 混杂在压缩包中 | **逐字保留在 `events`**(一个不丢) | | 下载 | 仅 ZIP | **直接下载 `.json`**(与官方同款 HEAD 预检) | | 无界面使用 | ✗ | **`/chat` 命令**(零 token,人命令平面) | | 校验 | — | 碎片↔折叠比对报告 | - **零运行时依赖**,核心是单个纯数据模块(`lib/fold.js`)——不碰 zstd、不碰 zip、无服务器。 - **不删除任何内容**:每条非碎片事件字节级保留;无法校验的碎片 step 会回退为保留原始事件。 - **Token 影响为零**:`/chat` 走人命令平面,结果不进模型历史。 ## 要求 - DSH Web(`dsh web`)profile,Node **≥ 22.15** - `commands` / `sessionPersistence` / `sessions` 服务(官方 profile 自带) ## 安装 ```bash # 从 npm(推荐) dsh plugin --profile web add dsh-chat-log # 从 GitHub dsh plugin --profile web add github:YupegLV/dsh-chat-log # 本地(开发/自托管) dsh plugin --profile web add file:/绝对路径/dsh-chat-log ``` 执行后重启 `dsh web` 生效。 ### ⚠️ 浏览器下载需要打一个 host 补丁(一次性,幂等) "Chat log" 按钮的**浏览器直接下载**依赖 host 下载端点 `/api/session.chat`(挂在 `dsh-host-apiproxy`,第三方插件无法注册自己的 `/api/*` 路由)。安装后执行一次: ```bash node node_modules/dsh-chat-log/scripts/patch-apiproxy.mjs # 或在插件目录: node scripts/patch-apiproxy.mjs ``` 脚本幂等(重复执行安全、自动备份原文件)。**升级 DSH 后需重新执行**(新装的 `dsh-host-apiproxy` 会覆盖补丁)。 > 不打补丁时:按钮点击会静默失败(无状态提示),但 `/chat` 命令(写盘 `dsh-chats/`)**始终可用**。 ## 用法 | 入口 | 说明 | |---|---| | `/chat` | 导出**当前**会话 → `<会话cwd>/dsh-chats/chat--<时间戳>.json`,命令结果回显绝对路径 | | `/chat --id ` | 导出指定会话 | | `/chat --out <目录>` | 自定义输出目录 | | 会话头部 **Chat log** 按钮 | 与官方"Session log"按钮并列;HEAD 预检后浏览器直接下载 `dsh-chat-.json`(需打 host 补丁,见上) | 命令走人命令平面:零 token、不进模型历史,结果以 flow node 渲染。 ## 输出格式(`dsh-chat.v1`) ```jsonc { "schema": "dsh-chat.v1", "session": { "id": "...", "createdAt": 1787625016270, "cwd": "...", "agentPreset": "standard", "title": "..." }, "model": { "provider": "deepseek-official", "model": "...", "reasoningEffort": "max", "maxTokens": 256000 }, "turns": [ { "index": 1, "startedAt": 1787625120770, "user": [ { "time": 1787625120846, "content": [ { "type": "text", "text": "..." } ] } ], "steps": [ { "index": 1, "assistant": { "time": 1787625125842, "reasoning": "完整推理全文", "text": "完整回复文本", "toolCalls": [ { "id": "call_...", "name": "bash", "arguments": "{...完整参数 JSON...}" } ], "usage": { "inputTokens": ..., "outputTokens": ... } }, "tools": [ { "call": { "id": "call_...", "name": "bash", "arguments": "..." }, "result": { "isError": false, "text": "...", "time": ... } } ] } ], "endedAt": 1787625168111 } ], "events": [ /* 除流式碎片外的全部原始事件,逐字、按原顺序保留: session/turn/step 生命周期、request 头与上下文、 权限、审批、沙箱、标题、checkpoint ... */ ] } ``` ### 不丢内容的保证 - `events` = 原始日志中**除流式碎片外**的每条事件,字节级一致、按原顺序保留(导出时校验:数量**与**逐行 identity 都必须一致)。 - 碎片内容已由权威折叠完整承载(每个碎片 step 都校验存在对应 `assistant/message`;缺折叠的 step 会把碎片原样保留进 `events`)。 - 导出附带 `report`:总事件数、折叠的碎片数/step 数、逐字保留的事件数、碎片↔折叠比对结果。 ## 开发与验证 > 插件开发踩坑记录(client bundle id 必须用裸包名、`file:` 是复制安装等)见 **[docs/DEVELOPMENT.md](docs/DEVELOPMENT.md)**。 ```bash # 核心逻辑离线验证(无需 dsh 运行时;输入为解压后的 JSONL) node test/verify.mjs ``` 包结构: ``` lib/fold.js 纯数据核心:JSONL → 聊天树 + 校验报告(零依赖) lib/index.js Host 半:/chat 命令、flush、readRaw、原子写盘 lib/client.js Browser 半:会话头部 "Chat log" 下载按钮 cordis.patch.yml profile patch 层(insert 插件行) scripts/patch-apiproxy.mjs 幂等补丁:注册 /api/session.chat 下载端点 docs/DEVELOPMENT.md 踩坑记录与机制说明 test/verify.mjs CLI 验证套件 ``` ## 已知限制 - 需要 `sessionPersistence` 提供 raw artifact 的后端(JSONL 后端支持;SQLite 后端与官方 ZIP 导出同样不支持)。 - 输出为 pretty-printed JSON,约为原始日志 1.2 倍(含权威折叠与全量 events);截断工具结果可降到约 30%。 - 浏览器直下功能依赖对 `dsh-host-apiproxy` 的幂等补丁(见安装节;`/chat` 命令写盘不依赖补丁)。 ## License MIT