跳到正文
曾亮懿 ZengLiangYi Blog

AI 对话管理方案:四种存储路径与迁移验收

比较 Claude Code、Cursor、Copilot、Trae 的固定适配器输入,区分原始副本、可读导出与知识库,并用合成清单验证身份和信息保留。

曾亮懿

曾亮懿

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

对话管理方案的价值取决于你要保留什么、如何找回,以及换工具之后能否核对结果。原稿给四个工具排过“可迁移性”与“搜索能力”的等级;没有当前版本和同一样本,不能沿用这些排名。这里保留四方比较,用固定适配器输入和可执行验收替代主观评分。

先明确比较哪一层

原始副本保留上游存储证据;可读导出便于查看;导入的统一会话便于跨来源检索;摘要知识库适合复用,但有选择与生成带来的信息变化。四层可同时使用,摘要不能代替原始备份。

比较时记录工具版本、操作系统、数据来源、读取或导出方式和日期。内置浏览、会话恢复、内容检索、跨项目搜索与语义检索是不同能力,不能都填成“有/无搜索”。Claude Code 官方工作流提供会话恢复与选择器;VS Code 会话文档提供 JSON 导出。文档功能也不证明某种导出文件自动兼容本项目适配器。

四个入口各有保留成本

以下比较限于 ChatCrystal 固定提交能读取的形状,不能据此断言四个工具当前全部版本的 UI、云端保存方式或性能。

来源 固定适配器入口 迁移时需要证明的事情
Claude Code Claude adapter的项目 JSONL 副本可重新读取;消息块、工具和思考的取舍已记录
Cursor Cursor adapter的 workspace 索引与 global bubbles 两处样本属于同一工作范围;孤立会话和版本变化可解释
Copilot Copilot adapter的工作区/空窗口位置,JSONL 首快照或旧 JSON 不把后续补丁当完整最新快照;时间和响应块保留范围有证据
Trae Trae adapter的 SQLite KV 与嵌套任务内容 sessionId 定位、内容优先级与构造时间没有被误当原始时间

JSONL 可用文本工具查看,仍需理解版本与记录含义。SQLite 可以查询,仍需一致副本、实际表/键和 JSON 解码。两种容器都可能包含敏感项目内容;在你自己的迁移样本中先确认保留与分享范围。这些是实际数据处理步骤,不是格式优劣或厂商生态排名。

给四个候选方案同一份验收清单

先在可控样本中标记来源、会话 ID、项目、消息顺序、正文、工具标志和思考内容,再比较迁移输出。若只统计“两条消息”,可能漏掉同 ID 跨来源碰撞、正文错配或思考丢失。原始时间、父引用、附件和完整工具轨迹也需单独增加到真实验收中。

下面只为四个来源构造相同的教学清单,不读取它们的真实存储,不运行其客户端或 ChatCrystal,不形成实际产品评分。保存 lesson.mjs,用 Node 24+ 运行,无 npm 依赖。

import assert from 'node:assert/strict';
const sources = ['claude-code', 'cursor', 'copilot', 'trae'];
const expected = sources.map((source) => ({
  source,
  id: 'shared-7',
  project: 'fixture-project',
  messages: [
    { id: 'u1', role: 'user', content: 'fixture question', thinking: null, hasToolUse: false },
    {
      id: 'a1',
      role: 'assistant',
      content: 'fixture answer',
      thinking: 'fixture thought',
      hasToolUse: true,
    },
  ],
}));
function audit(actual) {
  const key = (item) => item.source + ':' + item.id;
  const found = new Map();
  const issues = [];
  for (const item of actual) {
    const id = key(item);
    if (found.has(id)) issues.push(id + ':duplicate');
    found.set(id, item);
  }
  for (const reference of expected) {
    const id = key(reference);
    const item = found.get(id);
    if (!item) {
      issues.push(id + ':missing');
      continue;
    }
    if (item.project !== reference.project) issues.push(id + ':project');
    if (item.messages.length !== reference.messages.length) issues.push(id + ':message-count');
    reference.messages.forEach((message, index) => {
      for (const field of ['id', 'role', 'content', 'thinking', 'hasToolUse']) {
        if (item.messages[index]?.[field] !== message[field])
          issues.push(id + ':' + index + ':' + field);
      }
    });
    found.delete(id);
  }
  for (const id of found.keys()) issues.push(id + ':unexpected');
  return issues;
}
const intact = structuredClone(expected);
assert.deepEqual(audit(intact), []);
const lossy = structuredClone(expected);
lossy[0].messages[1].thinking = null;
assert.ok(audit(lossy).includes('claude-code:shared-7:1:thinking'));
const missing = expected.filter((item) => item.source !== 'cursor');
assert.ok(audit(missing).includes('cursor:shared-7:missing'));
const reordered = structuredClone(expected);
reordered[2].messages.reverse();
assert.ok(audit(reordered).includes('copilot:shared-7:0:role'));
assert.ok(
  audit([...intact, structuredClone(intact[0])]).includes('claude-code:shared-7:duplicate')
);
console.log('four-source fixture acceptance passes; no product runtime is compared');

完整清单通过;删除 thinking、移除 Cursor 会话、交换 Copilot 消息、重复同一来源 ID 都产生具体问题。共同 id=shared-7 不导致跨来源合并,因为匹配键包含 source。

删去字段循环里的 thinking,思考丢失断言失败;把匹配键改为只有 id,完整清单检查失败。恢复后通过。这是选定字段验收器的行为,不证明真实工具导出完整,也不证明 ChatCrystal 现有本地导入解决了所有跨来源 ID 冲突。

根据任务选择组合,而不是只选格式

保留调试证据时,优先取得可核对的原始副本并记录一致性条件;供人复查时,再制作可读导出;需要跨来源查找时,检验统一会话中的身份和字段;需要经验复用时,再验收摘要、引用和检索命中。根据目的组合这些步骤,保留回到来源的路径。

ChatCrystal 通过 SourceAdapter统一部分输出,摘要、Embedding 和搜索另有各自失败边界。它不是上游格式无损转换的证明。未知版本、来源遗漏与空结果需要作为待核查状态,而非统一记为“导入成功”。

一次比较应留下样本预期、实际保留与遗漏、失败案例及恢复步骤。搜索对比则预先定义任务与期望结果,再测本机耗时和相关性;本文没有实际速度、质量、成本或工具优劣数据。继续阅读格式定位和导入身份与哈希可以把清单落实到具体链路。

分享:

相关文章

AI 对话格式差异:事件、快照与跨库消息定位

对照五个固定适配器,区分 JSONL 容器、事件语义与 SQLite 键布局,用两个内存数据库观察消息索引、孤立数据和未知版本。

曾亮懿 曾亮懿
阅读约 4 分钟
#ChatCrystal #Node.js #SQLite

sql.js WASM 持久化:内存、导出、外键与保存点

对照 ChatCrystal 的数据库生命周期,运行 sql.js 1.14.2 样本,区分 SQL 提交、二进制导出、文件写入、外键恢复和嵌套回滚。

曾亮懿 曾亮懿
阅读约 5 分钟
#ChatCrystal #Node.js #SQLite

Vectra 索引内部:元数据文件、取消更新与实例缓存

核对 Vectra 0.15.0 的真实查询和存储路径,在临时索引中观察外部元数据、取消后的文件残留,以及不同实例的缓存状态。

曾亮懿 曾亮懿
阅读约 4 分钟
#ChatCrystal #Node.js #SQLite

从文章到代码

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