跳到正文
曾亮懿 ZengLiangYi Blog

接入 Codex、Trae 与 Copilot:分别核对三种历史格式

按 ChatCrystal 当前适配器检查数据目录、事件提取与快照边界,用真实会话验证三类来源的导入结果。

曾亮懿

曾亮懿

阅读约 4 分钟
目录 展开 收起

同一个导入命令可以接入不同工具,但不能用同一套规则解释它们的历史。Codex 是事件流,Trae 的记录在工作区数据库中,Copilot 则需要区分 JSON 对象和 JSONL 快照。来源被检测到,只说明发现了适配器认识的数据,并不证明所有内容都已保留。

本文核对 ChatCrystal 提交 7642768 的三个适配器。以下是应用对已知存储结构的处理,不是各工具承诺长期稳定的公共导出协议。

先配置服务端的数据目录

来源 默认位置 自定义变量指向
Codex ~/.codex/sessions/ CODEX_SESSIONS_DIR:会话目录
Trae 平台对应的 Trae/User/workspaceStorage/ TRAE_DATA_DIR:User 目录
Copilot 平台对应的 Code/User/ 下的会话目录 COPILOT_DATA_DIR:User 目录

Trae 和 Code 的平台根目录分别使用 Windows 的 %APPDATA%、macOS 的 ~/Library/Application Support、Linux 的 ~/.config。当前 Copilot 适配器默认查找 Code,不代表所有 VS Code 衍生版本都能自动发现。

配置代码 在服务进程启动时加载这些变量。需要自定义时,先为启动服务的进程设置变量;只在已运行服务的客户端导入命令前设置,不会改变服务已经加载的路径。默认目录适用时,无须覆盖。

Codex:事件提取与有限去重

Codex 适配器 递归查找 rollout-*.jsonl,跳过小于 50 字节的文件。它从 session_meta 读取会话 ID、工作目录和 Git 分支,从 event_msg 的用户与助手事件提取正文。

下面是说明字段关系的构造示例,不是真实导入记录:

{
  "type": "event_msg",
  "timestamp": "2026-10-01T10:00:00Z",
  "payload": { "type": "user_message", "message": "为什么这个请求重复执行?" }
}

用户文本中若出现精确标记 ## My request for Codex:\n,代码只保留其后的请求。其他文本不会通过通用规则自动识别为 IDE 上下文。

response_item 中的助手 output_text 也可能成为消息;若其拼接文本与最近一次助手消息完全相同,会跳过这份重复。它不是全会话的语义去重。用户和 developer 的这类消息被跳过;工具调用主要给最近一次助手消息设置使用工具的标记,不能据此声称工具结果完整归档。

标题索引实际位于 ~/.codex/session_index.jsonl,与 sessions/ 并列。当前代码缓存索引,且 CODEX_SESSIONS_DIR 不会把索引路径一起改到自定义目录。导入内容正常但标题缺失时,应把索引位置作为单独问题检查。

Trae:直接内容优先,再提取任务内容

Trae 适配器 要求工作区同时有 workspace.json 与 state.vscdb,从 ItemTable 的 memento/icube-ai-agent-storage 读取 list 中的会话。

助手消息有非空 content 时直接使用,并返回空的 thinking。只有进入 agentTaskContent 的后备路径,才拼接 proposal 与 finish 步骤的 thought,并收集相应推理字段;没有正文片段时还可能使用 guideline thought。因此,“所有推理都会保留”不是准确的描述。

消息按 turnIndex 处理;时间字段不可靠时,代码使用递增的合成时间保持顺序。顺序可用不等于这些时间就是原始发生时刻。导入验收应比较内容、角色和顺序,而不要把毫秒差当作实际耗时。Trae 和 Copilot 的工作区路径也使用简单的 file:/// 前缀剥离与解码,可能丢失 POSIX 根斜杠;不要直接将导入路径当作可用的绝对路径。

Copilot:第一行快照不是补丁重放

Copilot 适配器 扫描工作区的 chatSessions/ 和全局的 globalStorage/emptyWindowChatSessions/,接收 .json、.jsonl,跳过小于 100 字节的文件。

JSON 文件作为一个对象读取;JSONL 只读取第一行,并处理 kind: 0 的快照包装。不是寻找第一条非空记录,也不重放后续补丁。因此,不能把导入结果直接认定为文件末尾时的完整会话状态。第一行为空、无效或不是支持的快照时,需要检查原文件。

用户正文来自 message.text;message.parts 不在该提取路径中。助手响应按 kind 提取文本和 thinking,工具项用于标记;只有工具项、没有正文或 thinking 的响应不会形成助手消息。customTitle 可成为导入标题,助手时间使用请求时间加 1 毫秒用于排序。

用已知会话逐个验收

默认本机连接可运行:

crystal import
crystal --json conversations --source codex --limit 20
crystal --json conversations --source trae --limit 20
crystal --json conversations --source copilot --limit 20

列表 JSON 的记录在 items 中。每类来源选一个实际会话 ID,通过应用详情或 GET /api/conversations/<id> 比较原始用户请求、助手结论、项目和消息顺序;不要用总数增长代替内容检查。本机导入不会可靠地通过 CLI 的 --source 限制扫描,见 Claude Code 导入边界。

再加入缺失目录、坏 JSONL 首行或只有工具项的样本,确认失败和保留规则。自动监听也需单独验证,不能从手动导入成功推导出来。通过这一步后,才继续 生成笔记与检索;数据库来源的定位方法可参照 Cursor 导入指南。

分享:

相关文章

ChatCrystal 入门:从安装到第一条可搜索笔记

按 ChatCrystal 0.6.1 的实际 CLI,依次验证安装、服务、两类模型、导入、摘要与搜索,区分 npm 包和桌面应用的使用入口。

曾亮懿 曾亮懿
阅读约 5 分钟
#ChatCrystal #Node.js #知识管理

导入 Claude Code 对话:路径、解析与验收

按 ChatCrystal 当前适配器检查 Claude Code 历史位置、JSONL 过滤、增量导入和监听限制,避免把导入成功误读为完整保存或自动生成笔记。

曾亮懿 曾亮懿
阅读约 5 分钟
#ChatCrystal #Claude Code #数据解析

Claude Code JSONL 过滤:区分事件、正文块与遗漏

沿 ChatCrystal 的相关性判断、内容提取和标签清理检查 JSONL,解释顶层过滤与嵌套 thinking、工具标记的差别。

曾亮懿 曾亮懿
阅读约 4 分钟
#ChatCrystal #Claude Code #JSONL #数据解析

从文章到代码

到我的 GitHub 看看 ChatCrystal、开发者工具和日常学习记录,欢迎交流实现细节。