dsh-openwrite 0.2.22 → 0.2.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  <p align="center">在 DeepSeek Harness 中规划、写作、审稿和管理长篇小说。</p>
11
11
 
12
12
  <p align="center">
13
- <a href="package.json"><img src="https://img.shields.io/badge/dsh-0.1.2--rc.1-2563eb" alt="dsh 0.1.2-rc.1"></a>
13
+ <a href="package.json"><img src="https://img.shields.io/badge/dsh-0.2.1--rc.2-2563eb" alt="dsh 0.2.1-rc.2"></a>
14
14
  <a href="package.json"><img src="https://img.shields.io/badge/Node-%E2%89%A522.19-15803d" alt="Node >= 22.19"></a>
15
15
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-0f766e" alt="Apache-2.0"></a>
16
16
  <a href="https://dsh-plugin.org/plugins/lipu-jpg/openwrite"><img src="https://dsh-plugin.org/badges/listed.svg" alt="Listed on dsh-plugin.org"></a>
@@ -29,12 +29,12 @@
29
29
 
30
30
  ## 快速安装
31
31
 
32
- **0.2.21 标准插件包**兼容精确 dsh 版本 **0.1.2-rc.1 / 0.1.5-alpha.1 / 0.2.0-rc.2**。三个版本均已完成 Web 工作台渲染与 DoG 数据读取验证,Windows Electron 桌面端启动/恢复链路尚未实机复测。可下载版本、各平台验收结果和 SHA-256 以 [GitHub Release](https://github.com/LiPu-jpg/Openwrite/releases/latest) 附件为准;验收方法见 [发布验收](docs/RELEASE_ACCEPTANCE.md)。默认使用 npm `latest` 渠道;商城所需的精确预览版兼容性、验证范围和安装限制见 [DSH STORE 接入](docs/DSH_STORE.md)。
32
+ **0.2.23 标准插件包**兼容精确 dsh 版本 **0.1.2-rc.1 / 0.1.5-alpha.1 / 0.2.0-rc.2 / 0.2.1-rc.2**。四个版本均已完成 Web 工作台渲染与 DoG 数据读取验证,Windows Electron 桌面端启动/恢复链路尚未实机复测。可下载版本、各平台验收结果和 SHA-256 以 [GitHub Release](https://github.com/LiPu-jpg/Openwrite/releases/latest) 附件为准;验收方法见 [发布验收](docs/RELEASE_ACCEPTANCE.md)。默认使用 npm `latest` 渠道;商城所需的精确预览版兼容性、验证范围和安装限制见 [DSH STORE 接入](docs/DSH_STORE.md)。
33
33
 
34
34
  npm 包和对应 GitHub Release 使用同一份验收产物。也可安装精确版本的 Release 包:
35
35
 
36
36
  ```sh
37
- dsh plugin --profile web add -w https://github.com/LiPu-jpg/Openwrite/releases/download/v0.2.21/dsh-openwrite-0.2.21.tgz
37
+ dsh plugin --profile web add -w https://github.com/LiPu-jpg/Openwrite/releases/download/v0.2.23/dsh-openwrite-0.2.23.tgz
38
38
  dsh web
39
39
  ```
40
40
 
@@ -64,6 +64,10 @@ dsh web
64
64
 
65
65
  ### dsh 0.2 桌面端升级
66
66
 
67
+ 本地 `0.2.24` 候选包(Core 5.8.11)修复 [#88–#95](docs/ISSUES_88_95.md):删章验收账本、结算降级、长文本流式生成、后台写章进度、统一字数门限、草稿发现与恢复及诊断/路由语义。该候选尚未发布;npm `latest` 与正式 Release 仍以已发布版本为准。
68
+
69
+ `0.2.23` 修复 [#83](https://github.com/LiPu-jpg/Openwrite/issues/83)/[#84](https://github.com/LiPu-jpg/Openwrite/issues/84)/[#85](https://github.com/LiPu-jpg/Openwrite/issues/85):根包与全部内嵌子包的兼容声明加入精确宿主 `0.2.1-rc.2`,安装和激活不再被宿主版本闸门拒绝,无需版本豁免或手工编辑 `compatibility.json`。已在 `0.2.1-rc.2` 完成 Web 客户端验收(启动、OpenWrite 入口、工作台三页签、DoG 面板与其他插件共存),`0.1.2-rc.1`、`0.2.0-rc.2` 回归通过;Windows Electron 桌面端未实机复测。npm `latest` 已更新到 0.2.23,GitHub Release 已发布,完整验收见 [发布验收](docs/RELEASE_ACCEPTANCE.md#023)。升级后停止并重新启动 dsh,再刷新浏览器页面。
70
+
67
71
  `0.2.21` 修复 [#79](https://github.com/LiPu-jpg/Openwrite/issues/79) 的 Windows Desktop 目录选择:宿主接口失败后使用桌面提供的系统文件夹对话框,覆盖侧栏进入与工作台内目录选择。Core 保持 5.8.10。排查与手填路径方式见 [安装指南](docs/INSTALL.md#windows-desktop-目录选择)。
68
72
 
69
73
  `0.2.20` 捆绑 Core 5.8.10,修复 [#76](https://github.com/LiPu-jpg/Openwrite/issues/76) 的草稿恢复、任务状态、编辑和审稿契约,并补充 [#65](https://github.com/LiPu-jpg/Openwrite/issues/65) 的英文使用支持。行为与范围见 [修复说明](docs/ISSUE_76_REPAIRS.md)。正式可下载版本以 npm `latest` 和 GitHub Release 为准。
@@ -86,7 +90,7 @@ dsh web
86
90
 
87
91
  `0.2.11` 修复 [#45](https://github.com/LiPu-jpg/Openwrite/issues/45),适配精确宿主版本 `0.2.0-rc.2`:工作台兼容新的 turn-tail list 槽位,DoG 调试面板使用新的 `sessionStatus`;根包和所有子包的兼容声明同步更新。已验证 0.2.0-rc.2 的 Web 客户端启动、OpenWrite 入口、DoG 面板及其他插件共存;Windows Electron 桌面端恢复链路尚未实机复测。
88
92
 
89
- **`dsh-openwrite@0.2.10` 不包含这项修复,请升级到 `0.2.21` 的 GitHub Release 包。** 不要通过给旧子包授权来代替升级:`dsh-openwrite` 的版本豁免不会覆盖 `@dsh-novel/studio-panel@<ver>` 和 `@dsh-external/dsh-dog@<ver>`,而旧客户端在 0.2.0-rc.2 上激活失败可能触发桌面端的 profile 恢复。
93
+ **`dsh-openwrite@0.2.10` 不包含这项修复,请升级到 `0.2.23` 或更高的已验收版本。** 不要通过给旧子包授权来代替升级:`dsh-openwrite` 的版本豁免不会覆盖 `@dsh-novel/studio-panel@<ver>` 和 `@dsh-external/dsh-dog@<ver>`,而旧客户端在 0.2 宿主上激活失败可能触发桌面端的 profile 恢复。
90
94
 
91
95
  若已发生恢复,先关闭桌面端并备份当前 profile,再从自己的 `cordis.patch.yml.bak-*` 备份恢复 patch,同时恢复原 `package.json` 的 `dsh.profile.bundles` 列表。安装包和作品目录通常仍在;不要用出厂模板覆盖其他插件配置。详细排查见 [安装指南](docs/INSTALL.md#dsh-02-客户端兼容排查)。
92
96
 
package/docs/DSH_STORE.md CHANGED
@@ -23,7 +23,7 @@ OpenWrite 是一个完整的小说创作插件套件。商城安装目标是仓
23
23
 
24
24
  alpha 浏览器验收进一步发现 persona 配置由 `text` 改成了必填 `prefix`;预设使用 YAML 锚点将同一份身份文本提供给两个字段,并以两版实际 Config / apply 验证身份只注册一次。
25
25
 
26
- 默认宿主仍是 `0.1.2-rc.1`。商城当前滚动窗口还包含 alpha,所以额外验证 `0.1.5-alpha.1`,并保留 `0.1.3-alpha.1`、`0.1.3-alpha.2` 为未知。这不自动升级用户宿主,也不承诺整个 alpha 范围都兼容。
26
+ 构建基线仍是 `0.1.2-rc.1`。兼容声明覆盖精确版本 `0.1.2-rc.1`、`0.1.5-alpha.1`、`0.2.0-rc.2`、`0.2.1-rc.2`,并分别保留已完成的 Web 客户端验收;`0.1.3-alpha.1`、`0.1.3-alpha.2` 保持未知。这不自动升级用户宿主,也不承诺整个 alpha 或 0.2 范围都兼容。`0.2.23` 已发布到 npm `latest` 与 GitHub Release,完整平台矩阵、源码安装和四份宿主客户端报告见[发布验收](RELEASE_ACCEPTANCE.md#023);本机另复验了 `0.2.1-rc.2` 的安装闸门、客户端激活、预设选择、工作台入口与三页签、DoG 面板及其他插件共存。
27
27
 
28
28
  2026-09-09,从官方 npm Registry 直接安装 `@deepseek-ai/dsh@0.1.5-alpha.1` 时,上游范围依赖选中了正在发布的 alpha.2,其中 `@deepseek-ai/dsh-tool-pwsh-persistent@^0.1.5-alpha.2` 当时缺失,安装失败(ETARGET)。兼容测试使用 npm 的 `--before=2026-09-09T00:00:00Z` 解析 alpha.1 发布时的依赖,并保留解析锁。没有修改官方包源码或用 replacements/overrides 冒充官方组件。此证据仅适用于报告中的宿主依赖图,不代表后续浮动依赖安装也通过。
29
29
 
package/docs/INSTALL.md CHANGED
@@ -127,6 +127,8 @@ bridge 的高级 `mode: external` / `baseUrl` 配置继续支持外部 Core,
127
127
 
128
128
  `dsh-openwrite@0.2.10` 的旧工作台按 0.1 接口构建,不能通过版本豁免获得 0.2.0-rc.2 的客户端兼容性。根包豁免不覆盖内嵌子包:`@dsh-novel/studio-panel@<ver>`、`@dsh-external/dsh-dog@<ver>` 各自经过宿主版本检查。优先升级到包含 #45 修复的包;修复后的精确 `0.2.0-rc.2` 声明覆盖根包和所有子包,不需要手工编辑 `compatibility.json`。
129
129
 
130
+ `dsh-openwrite@0.2.23` 起,根包和全部内嵌子包的声明同时覆盖精确宿主 `0.2.1-rc.2`,安装和激活不需要版本豁免。宿主判断的是 `package.json` 的 `peerDependencies`(`@deepseek-ai/dsh-*`),不是 `dsh.compatibility` 字段;因此只改 `dsh.compatibility` 字符串并不能让 0.2.22 在 0.2.1-rc.2 上加载。若安装日志出现 `plugin does not support the DSH version in use`,请直接升级到 `0.2.23` 或更高的已验收版本,不要手工改版本号或给旧子包授权。本版已在 `0.2.1-rc.2` 完成 Web 启动、OpenWrite 入口、工作台三页签、DoG 面板与其他插件共存的验证;`0.1.2-rc.1`、`0.2.0-rc.2` 回归通过,Windows Electron 桌面端仍未实机复测。
131
+
130
132
  本修复同时处理 `conversation.chat.turnTail` 从 chain 到 list 的变化,以及 `uiSession.pendingInteractions` 到 `uiSession.sessionStatus` 的变化。客户端初始化或延迟槽位注册失败时,插件回滚对应注册并在浏览器控制台输出 `[OpenWrite/Studio]` / `[OpenWrite/DoG]` 和原始异常,避免让这类插件初始化异常升级为宿主 web boot 失败。此修复不更改桌面端自身的 profile 恢复策略。
131
133
 
132
134
  如果旧版本已经触发桌面端恢复,关闭桌面端后备份整个 profile,找到恢复前的 `cordis.patch.yml.bak-*`,恢复 patch 和原 `package.json` 中的 `dsh.profile.bundles`。这两项需一起核对,才能重新加载其他插件。保留已安装依赖和作品目录,不要用空 profile 替换完整配置。
@@ -135,8 +137,9 @@ bridge 的高级 `mode: external` / `baseUrl` 配置继续支持外部 Core,
135
137
 
136
138
  ```sh
137
139
  npm run test:client-boot
140
+ node scripts/client-boot-smoke.mjs --host-cli=/absolute/path/to/dsh-0.2.1-rc.2/node_modules/@deepseek-ai/dsh/lib/bin.js
138
141
  node scripts/client-boot-smoke.mjs --host-cli=/absolute/path/to/dsh-0.2.0-rc.2/node_modules/@deepseek-ai/dsh/lib/bin.js
139
- node scripts/client-boot-smoke.mjs dsh-openwrite-<version>.tgz --host-cli=/absolute/path/to/dsh-0.2.0-rc.2/node_modules/@deepseek-ai/dsh/lib/bin.js
142
+ node scripts/client-boot-smoke.mjs dsh-openwrite-<version>.tgz --host-cli=/absolute/path/to/dsh-0.2.1-rc.2/node_modules/@deepseek-ai/dsh/lib/bin.js
140
143
  ```
141
144
 
142
145
  脚本需要 Playwright Chromium,创建临时 Web profile,检查无豁免版本闸门、两个客户端加载、真实预设选择、会话导航、三个工作台页签出现和创作视图激活、DoG 面板及其他插件共存,后端就绪与未初始化响应由测试夹具提供,不准备 Python 环境、不调用模型;实际安装与后端动作由独立发布验收覆盖。它验证 Web 客户端兼容性;Windows Electron 的原生启动和恢复流程仍须在对应平台完成发布验收。
@@ -0,0 +1,40 @@
1
+ # Core 5.8.11:写作与恢复修复
2
+
3
+ 本地候选修复 #88–#95;不代表已发布到 npm 或 GitHub Release。测试使用假模型和隔离目录,不调用付费模型。
4
+
5
+ | Issue | 行为 |
6
+ | --- | --- |
7
+ | #88 | 删章在项目写锁内清除验收 head、递增 revision、保存删除 operation;未完成旧 operation 不再允许 resume。 |
8
+ | #89 | 账本有 head 而文件不存在时返回 `missing` 和 `CHAPTER_FILE_MISSING` warning,不阻断事实门禁;原文恢复后自动回到 current。 |
9
+ | #90 | 结算格式错误最多重试两次,收紧提示且保留全部正文。耗尽后保存带降级标记的摘要,reconcile task 返回 `completed`、`degraded: true`。网络、认证等异常仍返回实际失败。 |
10
+ | #91 | 写作 Agent、修订、语料分析/打包与结算使用 `OW_AGENT_STREAM`(默认 1);流式请求使用读空闲超时,保留已接收的短片段。`OW_LLM_TIMEOUT` 可覆盖超时,默认 300 秒,默认 SDK 重试一次。 |
11
+ | #92 | HTTP `POST /api/write` 提交 `chapter_write` 后立即返回 `task_id`。任务详情保留原有 `phase`,另提供 context/plan/draft/fact_extract/settle/validate/commit 的 `stage`、`run_id_v2`。后台任务保留原始工具调用追踪。锁每 15 秒更新心跳,死进程锁在下一次获取时回收。 |
12
+ | #93 | 上下文、writer 和 reviewer 共用 `chapter_word_bounds`(目标 -20%/+50%)和 `count_writing_units`。4200/5000 单位无需补写;真正超限先尝试两次唯一文本锚定修改,再允许一次整章调整。 |
13
+ | #94 | 删章派生数据移入 `data/chapter_deletions/<operation_id>/`,备份地址指向归档。未提交草稿有列表和显式恢复接口;恢复使用原 run id、逐字节复制,不生成新正文。 |
14
+ | #95 | 任务写入 `finished_at`,读端兼容旧 `completed_at` 并返回 `duration_ms`。导出预检使用阅读顺序的缺章判定;诊断默认只显示近 24 小时的历史事件,历史数量单独返回,成功任务重置失败连续计数。未知 API 路由返回 404 `ROUTE_NOT_FOUND`,方法错误返回 405 `METHOD_NOT_ALLOWED` 和 `Allow`。 |
15
+
16
+ ## 草稿恢复
17
+
18
+ 1. `GET /api/manuscript/drafts` 返回 chapter_id、run_id_v2、draft_path、draft_artifact、word_count、created_at、draft_revision 和 restorable。
19
+ 2. `POST /api/manuscript/drafts/restore` 传入 `run_id_v2`、`confirm: true`。覆盖已有正文还必须传入当前正文的 `expected_revision`;缺失正文传空字符串。
20
+ 3. 响应返回 `operation` 和 `requires_reconcile: true`。原始草稿已经写回正文;运行 acceptance reconcile 后才会宣告事实 current。恢复正文这一步不调用模型。
21
+
22
+ 同步 Python 应用方法 `write_next_chapter()` 保持可用。HTTP 写作的结果通过 `/api/tasks/<task_id>` 读取,错误中的 `details` 包含已落盘草稿路径。取消或流中断也保留可发现的正文片段。
23
+
24
+ 诊断支持 GET/POST `/api/diagnostics` 的 `since`(ISO 时间)与 `window_hours`;CLI 为 `openwrite diagnose --window 24 --since <ISO>`。缺章、当前设定冲突等仍存在的状态问题持续报告;时间窗口只淘汰已发生的任务、运行和传输事件。
25
+
26
+ ## 验证范围
27
+
28
+ 回归覆盖五轮删章/重建、缺失文件恢复、三次非 mapping 降级、原字节/CRLF 草稿恢复、取消与流中断保稿、后台进度、错误恢复路径、HTTP 404/405、过期诊断及统一字数门限。没有将真实服务商连续 20 次请求或 Windows Electron 实机验收标记为通过。
29
+
30
+ ## dsh 工具入口
31
+
32
+ `novel_manuscript_edit_action(action="drafts")` 列出未提交草稿;`action="restore_draft"` 传 `run_id_v2`、`confirm: true`,覆盖已有正文时用 `revision` 传当前正文 SHA。工具将其映射到 Core 的 `expected_revision`。恢复属于本地写入操作;不会按生成任务执行。随后使用现有验收调和工具处理返回的 operation。
33
+
34
+ #86、#87 的精确宿主 `0.2.1-rc.2` 声明已经包含在 0.2.23,本候选继续保留该兼容范围。
35
+
36
+ 插件验证:`npm run check:plugin` 通过(构建、doctor、36 项生命周期检查、预设与双 profile、bridge/panel smoke、14 项 epoch、298 项组件);`npm run test:managed` 23 项通过,跨仓库 contracts 通过。
37
+
38
+ 核心全量 pytest:1409 passed、32 skipped;新 wheel 另做打包内容与针对性回归检查。候选版本为插件 0.2.24 / Core 5.8.11,未发布。
39
+
40
+ 新 wheel 解包后隔离导入并执行针对性回归:11 passed。源码草稿 PR:[#96](https://github.com/LiPu-jpg/Openwrite/pull/96)。
@@ -6,6 +6,18 @@
6
6
 
7
7
  新建作品的验收请求最多等待 60 秒(原为 15 秒),保留成功耗时和失败诊断;不重试写请求,超时仍失败。此调整容纳慢速运行器,不代表初始化耗时问题已被修复。
8
8
 
9
+ ## 0.2.23
10
+
11
+ [GitHub Release](https://github.com/LiPu-jpg/Openwrite/releases/tag/v0.2.23) 与 npm `dsh-openwrite@0.2.23` 已发布,npm `latest` 已更新到 0.2.23。使用[主分支完整 CI](https://github.com/LiPu-jpg/Openwrite/actions/runs/39219394324) 验收的原始产物,来源提交 `341408b80075fe4cc429f30a3327bcbdf2e69903`,npm 包 SHA-256 为 `8eb13e3de31b2144f1d5a57094abff38951c0329058520c96331aed03c735470`。8 份安装/源码报告与 4 份宿主客户端报告(含精确 `0.2.1-rc.2`)全部通过;GitHub 四份附件逐一与 CI 原文件比对一致,官方 npm registry 无认证下载包的字节与 SHA-256 也一致。
12
+
13
+ 修复 [#83](https://github.com/LiPu-jpg/Openwrite/issues/83)/[#84](https://github.com/LiPu-jpg/Openwrite/issues/84)/[#85](https://github.com/LiPu-jpg/Openwrite/issues/85):根包与全部内嵌子包的 `peerDependencies`、`dsh.compatibility.dsh` 和 `dshReleases` 加入精确宿主 `0.2.1-rc.2`。宿主版本闸门读取的是 dsh peer 范围,因此只修改展示用的 `dsh.compatibility` 不能让旧包通过;本版四个包同步声明后,安装与激活均不需要版本豁免。发布矩阵新增 `0.2.1-rc.2` 客户端契约,并与 `0.1.2-rc.1`、`0.1.5-alpha.1`、`0.2.0-rc.2` 一起通过。
14
+
15
+ 本机 macOS arm64 / Node v24.15 另使用官方 registry 的精确 `@deepseek-ai/dsh@0.2.1-rc.2` 完成安装级复验:tarball 经 pnpm 安装进隔离 profile,宿主启动不再出现 `incompatible with dsh` / `skipping profile bundle`;浏览器中两个客户端入口激活,OpenWrite 入口和作品启动器可用。真实模型调用为 0。Windows Electron 桌面端原生启动与恢复仍须对应平台实机验收,本版未计为通过。
16
+
17
+ ## 0.2.22
18
+
19
+ [GitHub Release](https://github.com/LiPu-jpg/Openwrite/releases/tag/v0.2.22) 与 npm `dsh-openwrite@0.2.22` 已发布,npm `latest` 已更新到 0.2.22。使用[主分支完整 CI](https://github.com/LiPu-jpg/Openwrite/actions/runs/39084916927) 验收的原始产物,来源提交 `58209eabbaf0be1f54f562eab4bb5ca12a46bc57`,npm 包 SHA-256 为 `2f20f5e2326707d65119d549b08382dd2e83af481ac60e6ac6f1ee668b446683`。8 份安装报告与 3 份宿主客户端报告全部通过;GitHub 四份附件逐一与 CI 原文件比对一致,官方 npm registry 无认证下载包的字节与 SHA-256 也一致。修复 [#81](https://github.com/LiPu-jpg/Openwrite/issues/81)(bundle patch 覆写核心 connection 行与其他 bundle 冲突导致整机无法启动;DoG 调试通道改由插件自托管于 Web 载体)与 [#82](https://github.com/LiPu-jpg/Openwrite/issues/82)(受限网络下运行时下载必然超时、依赖索引不可换源)。两个 issue 的报告者均已随 issue 关闭获得修复说明。
20
+
9
21
  ## 0.2.21
10
22
 
11
23
  [GitHub Release](https://github.com/LiPu-jpg/Openwrite/releases/tag/v0.2.21) 与 npm `dsh-openwrite@0.2.21` 已发布,npm `latest` 已更新到 0.2.21。使用[主分支完整 CI](https://github.com/LiPu-jpg/Openwrite/actions/runs/38444848871) 验收的原始产物,来源提交 `4e5f88aac8b14c2402c509b2282810cc85840129`,npm 包 SHA-256 为 `b53e3638308185b5890207bc01806641a966620915b99102f5cb35c462b1daee`。8 份安装报告与 3 份宿主客户端报告全部通过;GitHub 四份附件逐一与 CI 原文件比对一致,官方 npm registry 无认证下载包的字节与 SHA-256 也一致。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-openwrite",
3
- "version": "0.2.22",
3
+ "version": "0.2.24",
4
4
  "description": "OpenWrite 长篇小说领域后端接入 DeepSeek Harness:统一创作 Agent 预设 + 原生创作工作台",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -54,7 +54,7 @@
54
54
  "displayName": "小说创作(OpenWrite)",
55
55
  "pluginType": "suite",
56
56
  "compatibility": {
57
- "dsh": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2",
57
+ "dsh": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2 || 0.2.1-rc.2",
58
58
  "profiles": [
59
59
  "web",
60
60
  "desktop"
@@ -64,7 +64,8 @@
64
64
  "0.1.3-alpha.1": "unknown",
65
65
  "0.1.3-alpha.2": "unknown",
66
66
  "0.1.5-alpha.1": "compatible",
67
- "0.2.0-rc.2": "compatible"
67
+ "0.2.0-rc.2": "compatible",
68
+ "0.2.1-rc.2": "compatible"
68
69
  }
69
70
  }
70
71
  },
@@ -113,9 +114,9 @@
113
114
  },
114
115
  "peerDependencies": {
115
116
  "@deepseek-ai/cordis": "4.0.2 || ~4.0.4",
116
- "@deepseek-ai/dsh-home-paths": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2",
117
- "@deepseek-ai/dsh-settings": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2",
118
- "@deepseek-ai/dsh-tools": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2"
117
+ "@deepseek-ai/dsh-home-paths": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2 || 0.2.1-rc.2",
118
+ "@deepseek-ai/dsh-settings": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2 || 0.2.1-rc.2",
119
+ "@deepseek-ai/dsh-tools": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2 || 0.2.1-rc.2"
119
120
  },
120
121
  "bin": {
121
122
  "openwrite-maintenance": "scripts/maintenance.mjs"
@@ -37,6 +37,7 @@ const WRITABLE_PATHS = new Set([
37
37
  'document/change-plan',
38
38
  'structured/change-plan',
39
39
  'manuscript-editing',
40
+ 'manuscript/drafts/restore',
40
41
  'manuscript/acceptance/baseline',
41
42
  'manuscript/acceptance/external',
42
43
  'manuscript/acceptance/reconcile',
@@ -84,7 +85,7 @@ function resourceForPath(path) {
84
85
  return 'tasks';
85
86
  if (path.startsWith('/api/project-archives'))
86
87
  return 'workspace';
87
- if (path.startsWith('/api/document') || path.startsWith('/api/write') || path.startsWith('/api/manuscript/acceptance'))
88
+ if (path.startsWith('/api/document') || path.startsWith('/api/write') || path.startsWith('/api/manuscript/'))
88
89
  return 'manuscript';
89
90
  if (path.startsWith('/api/outline'))
90
91
  return 'outline';
@@ -18,7 +18,7 @@ const readActions = {
18
18
  novel_chapter_run_action: ['list', 'get'],
19
19
  novel_rolling_plan_action: ['list', 'get'],
20
20
  novel_narrative_forecast_action: ['list', 'get'],
21
- novel_manuscript_edit_action: ['versions', 'version', 'compare', 'annotations'],
21
+ novel_manuscript_edit_action: ['drafts', 'versions', 'version', 'compare', 'annotations'],
22
22
  novel_source_action: ['status_v2', 'profile_v2'],
23
23
  novel_reference_library_action: ['list', 'status', 'profile'],
24
24
  novel_runtime_skill_action: ['list', 'diagnose', 'resolve'],
@@ -2117,7 +2117,8 @@ export function registerNovelTools(ctx, clientFactory, options) {
2117
2117
  }));
2118
2118
  ctx.tools.register(defineTool({
2119
2119
  name: 'novel_manuscript_edit_action',
2120
- description: 'Chapter version snapshots and annotations. Actions: "versions" (chapter_id), "version" (chapter_id + ' +
2120
+ description: 'Chapter snapshots, annotations and saved drafts. Actions: "drafts" (list recoverable uncommitted prose), ' +
2121
+ '"restore_draft" (run_id_v2 + revision + confirm: true; copy the exact saved bytes without generation, then reconcile facts). Other actions: "versions" (chapter_id), "version" (chapter_id + ' +
2121
2122
  'version_id — returns the snapshot content), "checkpoint" (chapter_id, optional label — save a snapshot), ' +
2122
2123
  '"compare" (chapter_id + version_id — preview current-to-snapshot differences without writing), ' +
2123
2124
  '"restore" (chapter_id + version_id + revision — REVERTS the chapter to a snapshot; revision-gated and ' +
@@ -2125,8 +2126,9 @@ export function registerNovelTools(ctx, clientFactory, options) {
2125
2126
  'revision + quote + note, optional start_hint/end_hint and color amber|rose|sky|lime|violet), ' +
2126
2127
  '"resolve_annotation" (chapter_id + annotation_id).',
2127
2128
  parameters: {
2128
- action: { type: 'string', required: true, enum: ['versions', 'version', 'compare', 'checkpoint', 'restore', 'annotations', 'annotate', 'resolve_annotation'], description: 'The manuscript-editing operation.' },
2129
- chapter_id: { type: 'string', required: true, description: 'Chapter id (ch_<digits>).' },
2129
+ action: { type: 'string', required: true, enum: ['drafts', 'restore_draft', 'versions', 'version', 'compare', 'checkpoint', 'restore', 'annotations', 'annotate', 'resolve_annotation'], description: 'The manuscript-editing operation.' },
2130
+ chapter_id: { type: 'string', description: 'Chapter id (ch_<digits>), required except for drafts/restore_draft.' },
2131
+ run_id_v2: { type: 'string', description: 'Saved run id from drafts (restore_draft).' },
2130
2132
  version_id: { type: 'string', description: 'Snapshot id (version/restore).' },
2131
2133
  label: { type: 'string', description: 'Snapshot label (checkpoint).' },
2132
2134
  revision: { type: 'string', description: 'Current chapter revision (restore/annotate).' },
@@ -2140,10 +2142,19 @@ export function registerNovelTools(ctx, clientFactory, options) {
2140
2142
  },
2141
2143
  output: { schema: JSON_OUTPUT_SCHEMA, render: (_args, value) => renderJson(value) },
2142
2144
  timeoutMs,
2143
- isConcurrencySafe: (args) => args.action === 'versions' || args.action === 'version' || args.action === 'compare' || args.action === 'annotations',
2145
+ isConcurrencySafe: (args) => args.action === 'drafts' || args.action === 'versions' || args.action === 'version' || args.action === 'compare' || args.action === 'annotations',
2144
2146
  async execute(args, exec) {
2145
2147
  const client = clientFor(exec);
2146
- if (!CHAPTER_ID_PATTERN.test(args.chapter_id))
2148
+ if (args.action === 'drafts')
2149
+ return await client.getJson('/api/manuscript/drafts', {}, exec.signal);
2150
+ if (args.action === 'restore_draft') {
2151
+ if (!args.run_id_v2)
2152
+ throw new Error('run_id_v2 is required; list drafts first');
2153
+ return await client.postJson('/api/manuscript/drafts/restore', {
2154
+ run_id_v2: args.run_id_v2, expected_revision: args.revision ?? '', confirm: args.confirm === true,
2155
+ }, exec.signal);
2156
+ }
2157
+ if (!args.chapter_id || !CHAPTER_ID_PATTERN.test(args.chapter_id))
2147
2158
  throw new Error(`chapter_id must match ch_<digits>, got "${args.chapter_id}"`);
2148
2159
  const body = { action: args.action, chapter_id: args.chapter_id };
2149
2160
  for (const key of ['version_id', 'label', 'revision', 'confirm', 'quote', 'note', 'start_hint', 'end_hint', 'color', 'annotation_id']) {
@@ -28,11 +28,12 @@
28
28
  "patch": "./cordis.patch.yml"
29
29
  },
30
30
  "compatibility": {
31
- "dsh": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2",
31
+ "dsh": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2 || 0.2.1-rc.2",
32
32
  "dshReleases": {
33
33
  "0.1.2-rc.1": "compatible",
34
34
  "0.1.5-alpha.1": "compatible",
35
- "0.2.0-rc.2": "compatible"
35
+ "0.2.0-rc.2": "compatible",
36
+ "0.2.1-rc.2": "compatible"
36
37
  }
37
38
  }
38
39
  },
@@ -44,9 +45,9 @@
44
45
  },
45
46
  "peerDependencies": {
46
47
  "@deepseek-ai/cordis": "4.0.2 || ~4.0.4",
47
- "@deepseek-ai/dsh-host-webserver": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2",
48
- "@deepseek-ai/dsh-tools": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2",
49
- "@deepseek-ai/dsh-workspace": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2"
48
+ "@deepseek-ai/dsh-host-webserver": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2 || 0.2.1-rc.2",
49
+ "@deepseek-ai/dsh-tools": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2 || 0.2.1-rc.2",
50
+ "@deepseek-ai/dsh-workspace": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.2.0-rc.2 || 0.2.1-rc.2"
50
51
  },
51
52
  "peerDependenciesMeta": {
52
53
  "@deepseek-ai/dsh-host-webserver": {