dsh-openwrite 0.2.23 → 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 +3 -1
- package/docs/DSH_STORE.md +1 -1
- package/docs/ISSUES_88_95.md +40 -0
- package/docs/RELEASE_ACCEPTANCE.md +4 -4
- package/package.json +1 -1
- package/packages/openwrite-bridge/lib/domain.js +2 -1
- package/packages/openwrite-bridge/lib/tool-policy.js +1 -1
- package/packages/openwrite-bridge/lib/tools.js +16 -5
- package/packages/studio-panel/lib/client.js +479 -479
- package/release/{openwrite-5.8.10-py3-none-any.whl → openwrite-5.8.11-py3-none-any.whl} +0 -0
- package/release/runtime-manifest.json +5 -5
- package/release/source.json +3 -3
package/README.md
CHANGED
|
@@ -64,7 +64,9 @@ dsh web
|
|
|
64
64
|
|
|
65
65
|
### dsh 0.2 桌面端升级
|
|
66
66
|
|
|
67
|
-
`0.2.
|
|
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,再刷新浏览器页面。
|
|
68
70
|
|
|
69
71
|
`0.2.21` 修复 [#79](https://github.com/LiPu-jpg/Openwrite/issues/79) 的 Windows Desktop 目录选择:宿主接口失败后使用桌面提供的系统文件夹对话框,覆盖侧栏进入与工作台内目录选择。Core 保持 5.8.10。排查与手填路径方式见 [安装指南](docs/INSTALL.md#windows-desktop-目录选择)。
|
|
70
72
|
|
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`。兼容声明覆盖精确版本 `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`
|
|
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
|
|
|
@@ -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,13 +6,13 @@
|
|
|
6
6
|
|
|
7
7
|
新建作品的验收请求最多等待 60 秒(原为 15 秒),保留成功耗时和失败诊断;不重试写请求,超时仍失败。此调整容纳慢速运行器,不代表初始化耗时问题已被修复。
|
|
8
8
|
|
|
9
|
-
## 0.2.23
|
|
9
|
+
## 0.2.23
|
|
10
10
|
|
|
11
|
-
|
|
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
12
|
|
|
13
|
-
|
|
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
14
|
|
|
15
|
-
|
|
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
16
|
|
|
17
17
|
## 0.2.22
|
|
18
18
|
|
package/package.json
CHANGED
|
@@ -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/
|
|
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
|
|
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',
|
|
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 (
|
|
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']) {
|