Back to home

danglong0313

dsh-history-sync

将codex和claude项目历史同步到dsh

Stars
0
Language
TypeScript
Created
Aug 15, 2026
Updated
Aug 16, 2026

Introduction

@danglong0313/dsh-history-sync

npm version license

把本机 Codex 与 Claude Code 历史任务以只读镜像的形式单向导入 DeepSeek Harness(DSH)。插件只调用公开接口:Codex 使用 codex app-server 的 stdio 协议,Claude 使用官方 Claude Agent SDK;它不会读取、修改或重写两者的私有历史 JSONL。

功能概览

  • 单向、只读镜像 Codex 与 Claude Code 的用户/助手对话,不写回来源。
  • 默认预览、默认不自动同步、默认只扫描最近 30 天。
  • 设置 → 插件 → 插件配置 → History Sync 中直接配置和启用自动同步。
  • 自动按原工作目录创建或复用 DSH Workspace,在左侧项目栏分组显示。
  • 使用内容指纹、追加水位和 generation 处理重复同步、增量追加及上游历史重写。
  • 过滤 system/developer、reasoning、工具调用、审批、命令输出和 Claude 控制标签,避免把协议消息当作真实聊天。

兼容性

  • 已验证 DSH:0.1.0-rc.6
  • Node.js:^22.19.0>=24
  • Claude Agent SDK:插件固定携带 0.3.233
  • Codex:需要支持稳定 thread/listthread/read 的当前官方 Codex;Windows 下可自动发现 Codex Desktop 内置程序

DSH 仍处于预发布阶段,Session 格式不保证跨预发布版本兼容。升级 DSH 后,请先在隔离 profile 中重新执行预览和安装验证。

安装与卸载

dsh plugin --profile web add @danglong0313/dsh-history-sync
dsh --profile web --dump-config

第二条命令应显示固定 ID 为 history-sync、包名为 @danglong0313/dsh-history-sync 的配置层。dsh plugin 会维护 profile 的 package.jsondsh.profile.bundles;不要手工编辑它们。

升级到最新版:

dsh plugin --profile web update @danglong0313/dsh-history-sync

卸载:

dsh plugin --profile web remove @danglong0313/dsh-history-sync

在 DSH 设置中配置

安装并启动 DSH 后,打开:

设置 → 插件 → 插件配置 → History Sync

这里可以直接选择 Codex/Claude 来源、最近天数、单次任务上限、工作目录过滤、项目分组、允许实际导入和自动同步。点击“保存并应用”后无需重启 DSH;开启“自动同步”会同时退出预览模式、立即启动一次同步,并在同步完成后自动刷新左侧项目栏。

界面配置作为插件自有覆盖层保存在 stateDirectory/settings.json;同步游标和去重状态仍单独保存在 stateDirectory/state.json。两者都不会写入 cordis.patch.yml,也不会包含消息正文或密钥。卸载插件不会自动删除这些运行数据。

首次预览与手动同步

默认 previewOnly: trueautoSync: false。启动 Web profile,在任意 DSH 任务里执行:

/history-sync preview

预览只报告发现、选择、新建、增量和新 generation 的数量,不创建 DSH Session,也不写同步状态。确认范围后,推荐在上述 History Sync 配置卡中开启“允许实际导入”,再执行:

/history-sync run

不带参数的 /history-sync 等同于预览。自动同步默认关闭;先完成预览,再在配置卡中开启“自动同步”。插件会立即同步一次,随后按 syncIntervalMinutes 做幂等增量同步;导入的 Session 会按原工作目录出现在左侧项目/会话列表中,无需再输入命令。

高级配置与完整 patch 覆盖

普通设置请优先使用界面。部署级参数(Codex 命令、协议分页、超时、状态目录和消息纳入策略)仍可通过 profile patch 配置。DSH patch 对同一 ID 的 config 是整项替换,不是深度合并,因此覆盖时必须重述完整配置:

- id: history-sync
  name: '@danglong0313/dsh-history-sync'
  config:
    codexEnabled: true
    claudeEnabled: true
    autoSync: false
    syncIntervalMinutes: 60
    importDays: 30
    maxSessionsPerSync: 50
    workspaceRoots: []
    groupByWorkspace: true
    readOnly: true
    previewOnly: true
    stateDirectory: !!js dshHomePath('history-sync')
    codexCommand: auto
    codexArgs:
      - app-server
    codexPageSize: 100
    codexRequestTimeoutMs: 30000
    codexShutdownTimeoutMs: 3000
    codexSourceKinds:
      - cli
      - vscode
      - appServer
    claudePageSize: 100
    claudeIncludeSystemMessages: false
    claudeIncludeWorktrees: true
    claudeIncludeProgrammatic: true

字段说明:

  • codexEnabled / claudeEnabled:启用对应来源,至少开启一个。
  • importDays:只考虑最近 N 天,默认 30,不会无限扫描全部历史。
  • maxSessionsPerSync:两种来源合并排序后,单次最多处理的任务数。
  • workspaceRoots:可选绝对目录列表;任务工作目录必须等于或位于其中一个目录下。
  • groupByWorkspace:为现存的原工作目录创建或复用 DSH Workspace,并把镜像 Session 加入对应项目分组。
  • readOnly:v1 必须为 true;配置为 false 会在插件加载时失败。
  • previewOnly:为 true 时拒绝实际导入。
  • stateDirectory:插件自有界面设置、同步游标、fingerprint、pending 写前记录和 generation 状态目录;消息正文不写入这里。
  • codexSourceKinds 默认只纳入交互式主任务(clivscodeappServer)。execsubAgent*unknown 容易包含自动化、子代理提示词或协议消息,只有明确需要时才应手动加入。
  • codexCommand: auto:先使用 DSH_HISTORY_SYNC_CODEX,再查找 PATH;Windows 下还会通过 AppX 注册信息自动定位 Codex Desktop 内置的官方 codex.exe。由于 WindowsApps ACL 会阻止普通 DSH 子进程直接启动该路径,插件会把同一官方二进制缓存到 stateDirectory/codex-bin 后运行;也可改为官方可执行文件的绝对路径。
  • 其余 Codex/Claude 字段控制官方客户端分页、超时和纳入的公开来源类型。

默认只镜像用户可见的用户文本和助手文本。Codex 的 system/developer 消息、reasoning、工具调用、审批和命令输出不会伪装成聊天消息;Claude 的 system、thinking、tool use/result,以及以 <command-name><local-command-stdout><ide_opened_file> 等 XML 风格控制标签开头的记录也会跳过。不完整且尚无助手回复的上游 turn 会等到完成后再导入。

界面只暴露日常、安全的字段;保存时会原子写入并立即校验。错误配置会明确拒绝,例如两个来源均关闭、相对工作目录、关闭只读模式,或在仍为预览模式时开启自动同步。

幂等与历史重写

每个标准化 turn 都有内容 fingerprint。重复运行不会重复追加相同消息;上游仅追加完整 turn 时,插件会继续写入同一个 DSH Session。若上游历史缩短、压缩、回退或已有内容改变,插件不会重写 DSH 的追加日志,而是创建新的 import generation,并保留旧 generation。

来源、上游任务 ID、原始工作目录、来源更新时间/修订、导入时间、导入版本、generation 与 fingerprint 保存在 stateDirectory/state.json。这些元数据不会伪装成可见聊天消息,也不会写入 cordis.patch.yml

隐私与安全

导入会在 DSH 持久化中产生第二份历史副本。 原任务可能包含源码、命令输出、.env 内容、凭据或其他敏感信息;启用前请检查 DSH 的存储位置、访问权限、备份和保留策略。删除 Codex/Claude 原任务不会自动删除 DSH 副本,反之亦然。

插件不会把密钥写入 patch 或同步状态,不记录消息正文到插件日志,也不会修改 Codex、Claude 的原始历史。同步状态本身仍包含上游任务 ID和原始工作目录,应按敏感运行数据保护。

常见问题

设置中没有 History Sync

确认安装的是 0.2.0 或更高版本,然后完全重启 DSH。使用下列命令确认 profile 已包含插件:

dsh --profile web --dump-config

spawn codex ENOENT 或 Codex 无法启动

默认 codexCommand: auto 会先检查 DSH_HISTORY_SYNC_CODEX 和 PATH,再自动发现 Windows Codex Desktop。WindowsApps 中的程序无法被普通子进程直接启动时,插件会把同一官方二进制缓存到 stateDirectory/codex-bin 后运行。仍失败时,可以把 codexCommand 配置为官方 codex.exe 的绝对路径。

会话出现在“未分组”

只有来源工作目录存在且 groupByWorkspace: true 时,插件才能创建或复用对应 Workspace。工作目录已经删除、不可访问或来源没有提供目录时,会话仍会导入,但可能显示在“未分组”。

卸载后历史副本还在

卸载只移除插件包,不会删除已经导入的 DSH Session,也不会删除 stateDirectory 中的设置和同步状态。请先确认备份和保留需求,再从 DSH 和文件系统中分别清理不再需要的数据。

限制

  • 这是单向历史镜像,不是双向同步,也不能从 DSH 无损恢复 Codex/Claude 的模型、工具进程、审批、沙箱或运行状态。
  • DSH rc.6 没有公开的 Session 级“禁止继续对话”锁。镜像会明确标注只读并且永不写回上游,但用户仍可能在 DSH 中从该副本继续新对话;这些新内容仅属于 DSH。
  • v1 在 turn 边界增量导入。尚未完成的最后一个 turn 后续发生变化时,会被视为重写并创建新 generation。
  • Codex provider 使用稳定的 thread/listthread/read(includeTurns: true);不会启用实验性的分页 turn/item API。
  • Claude provider 使用 listSessions() 和分页的 getSessionMessages();当前不需要调用 getSessionInfo()

开发验证

npm run typecheck
npm test
npm run build
npm pack --dry-run

测试只使用合成的 Codex App Server 与 Claude SDK 数据,不包含真实历史、私人绝对路径或凭据。

版本说明

0.2.0

  • 新增 DSH 内置“插件配置”页面。
  • 支持从界面开启自动同步,并在完成后刷新左侧项目栏。
  • 增加插件自有、原子写入的安全配置覆盖层。
  • 保留 0.1.1 的 Windows Codex Desktop 自动发现与官方二进制缓存机制。

参与开发

欢迎通过 Issues 报告可复现问题。提交日志或测试数据前请先移除源码、绝对私人路径、Token、Cookie、API Key 和真实历史正文。

License

MIT