目录 展开 收起
对话管理方案的价值取决于你要保留什么、如何找回,以及换工具之后能否核对结果。原稿给四个工具排过“可迁移性”与“搜索能力”的等级;没有当前版本和同一样本,不能沿用这些排名。这里保留四方比较,用固定适配器输入和可执行验收替代主观评分。
先明确比较哪一层
原始副本保留上游存储证据;可读导出便于查看;导入的统一会话便于跨来源检索;摘要知识库适合复用,但有选择与生成带来的信息变化。四层可同时使用,摘要不能代替原始备份。
比较时记录工具版本、操作系统、数据来源、读取或导出方式和日期。内置浏览、会话恢复、内容检索、跨项目搜索与语义检索是不同能力,不能都填成“有/无搜索”。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 和搜索另有各自失败边界。它不是上游格式无损转换的证明。未知版本、来源遗漏与空结果需要作为待核查状态,而非统一记为“导入成功”。
一次比较应留下样本预期、实际保留与遗漏、失败案例及恢复步骤。搜索对比则预先定义任务与期望结果,再测本机耗时和相关性;本文没有实际速度、质量、成本或工具优劣数据。继续阅读格式定位和导入身份与哈希可以把清单落实到具体链路。