better-dsh 0.2.3-b → 0.2.3-d

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.
Files changed (84) hide show
  1. package/docs/50_test-reports/upstream-dsh-0.1.5-rc.2-local-test-report.md +79 -0
  2. package/docs/upstream-dsh-0.1.5-rc.2-report.md +156 -0
  3. package/eval-description.md +33 -0
  4. package/lib/client/index.js +59 -50
  5. package/lib/index.d.ts +4 -21
  6. package/lib/index.js +37 -77
  7. package/lib/py-sdk-Chvy92MB.js +178 -0
  8. package/lib/py-sdk.d.ts +19 -2
  9. package/lib/py-sdk.js +2 -2
  10. package/package.json +3 -3
  11. package/control-prompt.md +0 -37
  12. package/docs/50_test-reports/v0.1.8d_artifacts/README.md +0 -138
  13. package/docs/50_test-reports/v0.1.8d_artifacts/code-mode-repl-only.observation.md +0 -74
  14. package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +0 -3890
  15. package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +0 -544
  16. package/docs/50_test-reports/v0.1.8d_artifacts/functions.json +0 -592
  17. package/docs/50_test-reports/v0.1.8d_artifacts/skills-catalog.snapshot.md +0 -30
  18. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.output-schemas.json +0 -1236
  19. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.python.txt +0 -592
  20. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.typescript.txt +0 -516
  21. package/docs/50_test-reports/v0.1.8d_artifacts/wire-vs-transcription.diff.md +0 -54
  22. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.lock +0 -7
  23. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.toml +0 -6
  24. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +0 -8
  25. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/main.rs +0 -4
  26. package/docs/50_test-reports/v0.2.0b_artifacts/hashline-probe.md +0 -5
  27. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.lock +0 -7
  28. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.toml +0 -7
  29. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/build.rs +0 -4
  30. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/src/main.rs +0 -13
  31. package/docs/60_exploration-and-research/01-cordis-runtime/bun-compile-cordis-runtime-bootstrap-research.md +0 -536
  32. package/docs/60_exploration-and-research/01-cordis-runtime/cordis-customization-and-override-mechanics.md +0 -418
  33. package/docs/60_exploration-and-research/01-cordis-runtime/cordis-engineering-feasibility.md +0 -155
  34. package/docs/60_exploration-and-research/01-cordis-runtime/cordis-research.md +0 -583
  35. package/docs/60_exploration-and-research/01-cordis-runtime/dsh-cordis-hotplug-mcp-patch-research.md +0 -265
  36. package/docs/60_exploration-and-research/01-cordis-runtime/js-ts-language-fundamentals.md +0 -628
  37. package/docs/60_exploration-and-research/02-dsh/dash-research.md +0 -592
  38. package/docs/60_exploration-and-research/02-dsh/dsh-web-profile-package-map.md +0 -186
  39. package/docs/60_exploration-and-research/02-dsh/dsh-web-ui-slot-system-research.md +0 -310
  40. package/docs/60_exploration-and-research/02-dsh/dsh-webui-backend-data-inventory.md +0 -633
  41. package/docs/60_exploration-and-research/02-dsh/dsh-webui-strip-boundary-research.md +0 -300
  42. package/docs/60_exploration-and-research/02-dsh/dsh-webui-wire-appendix.md +0 -3729
  43. package/docs/60_exploration-and-research/02-dsh/web-frontend-composability-research.md +0 -191
  44. package/docs/60_exploration-and-research/02-dsh/webui-wire-data/capture-live-turn.json +0 -1
  45. package/docs/60_exploration-and-research/02-dsh/webui-wire-data/observed-endpoints.json +0 -224
  46. package/docs/60_exploration-and-research/02-dsh/webui-wire-data/remote-inventory.json +0 -110954
  47. package/docs/60_exploration-and-research/02-dsh/webui-wire-data/served-index-sample.html +0 -47
  48. package/docs/60_exploration-and-research/02-dsh/webui-wire-data/session-events.json +0 -9411
  49. package/docs/60_exploration-and-research/02-dsh/webui-wire-data/ws-frame-examples.json +0 -20
  50. package/docs/60_exploration-and-research/02-dsh-webui/dsh-web-profile-package-map.md +0 -186
  51. package/docs/60_exploration-and-research/02-dsh-webui/dsh-web-ui-slot-system-research.md +0 -310
  52. package/docs/60_exploration-and-research/02-dsh-webui/dsh-webui-backend-data-inventory.md +0 -633
  53. package/docs/60_exploration-and-research/02-dsh-webui/dsh-webui-strip-boundary-research.md +0 -300
  54. package/docs/60_exploration-and-research/02-dsh-webui/dsh-webui-wire-appendix.md +0 -3729
  55. package/docs/60_exploration-and-research/02-dsh-webui/web-frontend-composability-research.md +0 -191
  56. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/capture-live-turn.json +0 -1
  57. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/observed-endpoints.json +0 -224
  58. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/remote-inventory.json +0 -110954
  59. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/served-index-sample.html +0 -47
  60. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/session-events.json +0 -9411
  61. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/ws-frame-examples.json +0 -20
  62. package/docs/60_exploration-and-research/03-mobile-ios/dsh-mobile-spa-ios-input-experience-research.md +0 -160
  63. package/docs/60_exploration-and-research/03-mobile-ios/ios-chat-app-bridge-research.md +0 -324
  64. package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-jsonl-mapping.md +0 -1532
  65. package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-sample/episode-failed.json +0 -46
  66. package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-sample/episode1.json +0 -1124
  67. package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-sample/episode2.json +0 -1240
  68. package/docs/60_exploration-and-research/05-dashr-dev/plugin-development.md +0 -148
  69. package/docs/60_exploration-and-research/05-dashr-dev/upstream-alignment.md +0 -102
  70. package/docs/60_exploration-and-research/README.md +0 -87
  71. package/docs/60_exploration-and-research/bun-compile-cordis-runtime-bootstrap-research.md +0 -348
  72. package/docs/60_exploration-and-research/cordis-research.md +0 -350
  73. package/docs/60_exploration-and-research/dsh-mobile-spa-ios-input-experience-research.md +0 -160
  74. package/docs/60_exploration-and-research/dsh-web-profile-package-map.md +0 -186
  75. package/docs/60_exploration-and-research/dsh-web-ui-slot-system-research.md +0 -310
  76. package/docs/60_exploration-and-research/dsh-webui-strip-boundary-research.md +0 -300
  77. package/docs/60_exploration-and-research/ios-chat-app-bridge-research.md +0 -324
  78. package/docs/60_exploration-and-research/web-frontend-composability-research.md +0 -191
  79. package/docs/superd/00-blueprint.md +0 -331
  80. package/docs/superd/01-component-boundaries.md +0 -261
  81. package/docs/superd/02-dsh-embed-modes.md +0 -151
  82. package/docs/superd/image.png +0 -0
  83. package/lib/py-sdk-BCaOGYz7.d.ts +0 -125
  84. package/lib/py-sdk-CbgYiX8O.js +0 -691
@@ -0,0 +1,79 @@
1
+ # upstream dsh 0.1.5-rc.2 本地对齐实测报告(Dev/Test 1 · 4988 实例)
2
+
3
+ > 日期:2026-09-11(HKT)
4
+ > 执行:对齐轮 S1–S7(runbook:`docs/60_exploration-and-research/05-dashr-dev/upstream-alignment.md`)
5
+ > 目标 tag:`dsh-v0.1.5-rc.2`(npm dist-tag `next`,最高版本;`latest` 停在 rc.1)
6
+ > 前置版本对账报告:`docs/upstream-dsh-0.1.5-rc.2-report.md`(846 commits / 3170 files / ~104k 行)
7
+
8
+ ---
9
+
10
+ ## 一、实测范围与结果表
11
+
12
+ | # | 步骤 | 结果 |
13
+ |---|---|---|
14
+ | S1 | patch 载体 tag 间 diff + dashr 56 个 `@deepseek-ai/*` 引用名对新 tag 包集全数命中 | ✅ |
15
+ | S2 | checkout `dsh-v0.1.5-rc.2` + 三 patch 手工重放(pnpm-workspace.yaml 冲突按新 allowBuilds 手解) | ✅ |
16
+ | S3 | rsync 副本 + stale peerDep 复查(absent)+ **新增 devDeps 手术**(见瑕疵 F2) | ✅ |
17
+ | S4 | `pnpm install`(36s,供应链策略 1543 entries 过)+ `pnpm run build`(234 client artifacts)+ 副本 tsdown/client 半 | ✅ |
18
+ | S5 | 插件契约对齐:**4 处真实语义漂移移植**(见 §三) | ✅ |
19
+ | S6 | `tsc --noEmit` **0 errors**;`vitest --run` **493/493**(37 files,128s) | ✅ |
20
+ | S7 | 4998 实例 systemd-run 冒烟 **8/8 探针全绿**(见 §四) | ✅ |
21
+
22
+ 红线遵守:未 npm publish、未动 prod 3080、未动 Caddyfile。
23
+
24
+ ## 二、环境事实
25
+
26
+ - monorepo:`upstream/deepseek-harness` @ `dsh-v0.1.5-rc.2`(detached),本地 patch 三件套在场(unrun devDep / storeDir+verifyDepsBeforeRun+zeromq / tsdown resolveRepositoryRoot)。
27
+ - allowBuilds 冲突解:采纳上游新集(**fs-ext 移除**——flock 改走 node-addon-system 预编译;新增 `electron-winstaller: false`、`msgpackr-extract: false`),保留本地 `zeromq: true` 与两条 `dsh-subprocess-local`。
28
+ - 副本 `packages/better-dsh/better-dsh/` = canonical 0.2.3-b + devDeps 手术(14 个 `workspace:*`)。
29
+ - 实例:unit `dsh-4988-test`,`DSH_HOME=~/.dsh-test`,`DSH_TRUSTED_HOSTS=test.pc.randomhash.app pc.randomhash.app 192.168.31.130`,`UnsetEnvironment=DISPLAY WAYLAND_DISPLAY`,**端口 4988**(4997–4999 被 superd PoC 占用,见瑕疵 F4)。
30
+ - 残留实验文件未动:`packages/boot/app-boot/bun-registry/`、`bun-internal-bridge.ts`(2026-09-06 bun compile 实验,构建容忍,untracked 不碍 checkout)。
31
+
32
+ ## 三、契约漂移与移植(本轮核心工作)
33
+
34
+ 对 0.1.5-rc.2 的 **4 处真实漂移**全部移植,canonical 已同步(src/test 与副本 diff = 空):
35
+
36
+ 1. **会话事件改名**(Session V3「PTC durable vocabulary」):`tool/code-dispatch(-start)` → `tool/ptc-dispatch(-start)`。`src/index.ts` 2 处 append + 3 处注释;测试 3 文件的字符串断言同步。
37
+ 2. **subagents 统一消息缝**:`followup`/`reportFrom` 两方法合并为 `sendMessage(sender, targetId, content, {signal})`(上行 = targetId 命中 sender 的 `parentSession` 自动走 send-to-parent;`source`/`delivery` 选项 knobs 已删,runtime 自盖章)。移植面:`src/subagents-surface.ts` 接口重述、`src/bridges/index.ts` 两调用点(parent 方向新增 root-agent 本地护栏,语义等价旧 UNAUTHORIZED)、`delegation.spec`/`bridges.spec`/`helpers.ts` 全部 fake 与断言。
38
+ 3. **持久化读路径**:`SessionPersistence.inspect` 消失(接口只剩 create/open/flush/stat/list);读 = `open(id,'read')` → `handle.read(offset?,length?,opts)` + `close()`,元数据 = `stat(id).header.createdAt`。移植面:`src/url-schema/handlers/agent.ts` 的 surface 接口重述 + 3 调用点收敛为 `persistedEventsOf` helper。
39
+ 4. **SessionSeq 品牌化**:裸 `number` 不再可赋值,需 `SessionSeq(n)` 构造(`dsh-session` 导出);`assistant/message` 事件 data 新增必填 `stream: AssistantStreamRecord[]`(V3 in-history stream 内嵌)——测试 fixture 两处补 `stream: []`。
40
+
41
+ 另有两处**行形状查表结论**(runbook S7.5/S7.8,全绿):
42
+ - `connection` 行(web-app cordis.patch.yml)tag 间**逐字节同形**(仅注释位移)——fence 腿整行重述继续有效;
43
+ - `__DSH_TRANSPORT__`/ownsHost 消费点、`data-sidebar-collapsed`(AppFrame.tsx:210 仍在)、`conversation.session.header` 与 `settings.general.item` slot、`apps/web/index.html` viewport meta、`webserver injections.ts` head splice——**全部原样存活**。
44
+
45
+ ## 四、S7 冒烟明细(unit dsh-4988-test)
46
+
47
+ | 探针 | 结果 |
48
+ |---|---|
49
+ | `web --dump-config` → dashr-repl 行 + `DASHR_KERNEL_PYTHON` 注入 | ✅ |
50
+ | fence:trusted Host `/api` = **401**(过栅栏卡认证);evil Host = **403** | ✅ |
51
+ | token 鉴权根页 200 + `__DSH_TRANSPORT__` boot script 在页 | ✅ |
52
+ | boot graph `"id":"better-dsh"` + `/plugins/??better-dsh/client.js&rev=…` | ✅ |
53
+ | client bundle:200,**17824B 与本地逐字节一致**(+84B = 服务端 sourceMappingURL 追加,符合已知行为) | ✅ |
54
+ | mobile 锚点:layout 模块含 `data-sidebar-collapsed` + `SIDEBAR_AUTO_COLLAPSE = 1024` | ✅ |
55
+ | hashline 中央库 `$DSH_HOME/storages/dsh-better-edit/hash-store.sqlite` 在位 | ✅ |
56
+ | 0.1.5 新组合在场:ui-sidebar-right/documentpreview/files、client-resources、api-workspace-files、ui-deliverables 均入 module batch | ✅ |
57
+
58
+ 实例**保持运行**供 user 验收:`http://127.0.0.1:4988/?token=<redacted>`(token 每次重启轮换)。
59
+
60
+ ## 五、发现的瑕疵(定性 + 去向)
61
+
62
+ - **F1(流程/runbook 漂移)**:`packages/node_modules` 在新 tag 安装布局下不再生成 → runbook 的 `../../node_modules/.bin/tsx`(build-client)失效,正确为 `../../../node_modules/.bin/tsx`。→ 已回写 AGENTS.md §二。
63
+ - **F2(工具链坑,重要)**:canonical 的 npm-range optional peerDeps(`>=0.1.2-alpha.1 <0.2.0-0`)在 pnpm 11 严格预发布 semver 下**不匹配 workspace `0.1.5-rc.2`**(元组规则),autoInstallPeers 落到 registry **0.1.2-rc.1**(唯一满足该 range 的 registry 版本)→ 副本 node_modules 双身份,tsc 品牌类型互斥报错。**解法(S3 新增手术)**:副本 package.json devDependencies 注入 14 个 `workspace:*`(dashr 实际 import 的 dsh-* 名单),每次 rsync 后重打。→ 已回写 AGENTS.md §二;canonical 不动(npm 发布语义保持)。
64
+ - **F3(上游观察,非阻塞)**:rc.2 的 `test`/`build:bench` scripts 前置 `build:native-system`;主 `build` 已含(scripts/build.ts:44),无额外步骤。`native/system/packages/linux-x64/bin/glibc/system.node` 已产出。
65
+ - **F4(环境冲突)**:4997(127.0.0.1)、4998、4999(0.0.0.0)被 superd multi-context PoC 占用(`~/workspaces/superd/.scratch/multi-context-poc/poc4-v3-e2e.mjs`,pid 2233871 + 1393092,Sep 10 19:41 起,独立 DSH_HOME)——不可杀(user 的在跑实验),本轮实例改 **4988**。**注意:若 Caddy test.pc.randomhash.app 后端指 4999,域名叫到的将是 superd 实例**——user 域名验收前需先对齐端口或等 PoC 结束(Caddyfile 红线未动)。
66
+ - **F5(上游观察)**:`pnpm peers check` 有 WARN(副本 npm-range peers vs workspace 版本)——F2 的同一根源,运行期无影响(profile symlink 直连 monorepo)。
67
+
68
+ ## 六、流程化产出
69
+
70
+ - 本报告 + AGENTS.md §二 write-back(tag 对齐记录、tsx 路径、devDeps 手术、端口事实)。
71
+ - `.scratch/dsh-v0.1.3-alpha.2-local-patches-backup.patch`(旧 patch 备份,切换前快照)。
72
+
73
+ ## 七、Open items
74
+
75
+ 1. **user 验收**(第一人称):127.0.0.1:4988 实例(域名词见 F4 注意);重点 = dashr-repl 真跑一轮(kernel 三级供给在新 runtime 下)、better-edit 读改写、mobile 手势/zoomGuard 真机。
76
+ 2. canonical 改动(4 文件 src + 6 文件 test)**未 commit**——等 user 指令(上轮有 commit 前 "Wait" 先例)。
77
+ 3. Caddy test.pc → 4999 端口归属与 superd PoC 的冲突排查(user 裁决)。
78
+ 4. 既有遗留:v0.2.5 zoomGuard standalone 双形态 CDP 复验(AGENTS.md 已记)。
79
+ 5. prod(3080)**维持 0.1.3-alpha.2 不动**;升 0.1.5 需另行裁决(对账报告 §六建议先行)。
@@ -0,0 +1,156 @@
1
+ # upstream dsh npm 版本对账:prod 0.1.3-alpha.2 → 0.1.5-rc.2
2
+
3
+ > 生成时间:2026-09-10(本地时区)
4
+ > 数据源:npm registry(`@deepseek-ai/dsh`)元数据 + `upstream/deepseek-harness` git tag 对账
5
+ > 目标:回答「npm 上比 prod 更高的版本是什么、diff 有多大、对 prod 意味着什么」
6
+
7
+ ---
8
+
9
+ ## 〇、一句话结论
10
+
11
+ prod 当前跑 **`@deepseek-ai/dsh@0.1.3-alpha.2`**。npm 上比它高的版本是整条 **0.1.5 线**(`alpha.1 / alpha.2 / rc.1 / rc.2`,**0.1.4 从未发布,直接跳号**)。最高版本是 **`0.1.5-rc.2`**(挂在 `next` dist-tag,而 `latest` 还停在 `0.1.5-rc.1`)。
12
+
13
+ 这条 0.1.5 线是**大版本级聚合**:846 commits、3170 文件、约 10.4 万行新增。核心是 **Session 格式 v3 重写**(会话持久化契约变更,对 prod 是**破坏性升级,不可 drop-in**),外加 Electron 桌面打包、Sidebar/dockkit 重构、文件交付「present」工具、图渲染预览、模型默认值切换(DeepSeek V41 Flash)等一批功能。**升级 prod 前必须按 AGENTS.md §一/§二 走对齐轮,不能只换版本号。**
14
+
15
+ ---
16
+
17
+ ## 一、版本全景
18
+
19
+ npm registry 当前 dist-tags:
20
+
21
+ | dist-tag | 指向版本 |
22
+ |---|---|
23
+ | `latest` | 0.1.5-rc.1 |
24
+ | `next` | **0.1.5-rc.2**(最高) |
25
+ | `alpha` | 0.1.5-alpha.2 |
26
+
27
+ 比 prod(0.1.3-alpha.2)更高的版本,按发布顺序:
28
+
29
+ | 版本 | npm 发布时间 (UTC) | dist-tag |
30
+ |---|---|---|
31
+ | 0.1.5-alpha.1 | 2026-09-08 15:57 | — |
32
+ | 0.1.5-alpha.2 | 2026-09-09 14:41 | `alpha` |
33
+ | 0.1.5-rc.1 | 2026-09-10 03:12 | `latest` |
34
+ | **0.1.5-rc.2** | **2026-09-10 14:57** | `next` |
35
+
36
+ > 注意点:`latest` 并不指向最高版本(rc.1 vs rc.2);「最高版本」= `next` 上的 **0.1.5-rc.2**。0.1.4 未在 npm 出现过。
37
+
38
+ 对应 git tag(本地 `upstream/deepseek-harness`,已 fetch):
39
+
40
+ ```
41
+ dsh-v0.1.3-alpha.2 2026-09-07 19:45 +0800 ← prod 当前
42
+ dsh-v0.1.5-alpha.1 2026-09-08 23:25 +0800
43
+ dsh-v0.1.5-alpha.2 2026-09-09 22:13 +0800
44
+ dsh-v0.1.5-rc.1 2026-09-10 09:36 +0800
45
+ dsh-v0.1.5-rc.2 2026-09-10 21:50 +0800
46
+ ```
47
+
48
+ ---
49
+
50
+ ## 二、diff 规模
51
+
52
+ `dsh-v0.1.3-alpha.2 .. dsh-v0.1.5-rc.2`:
53
+
54
+ | 指标 | 值 |
55
+ |---|---|
56
+ | commits | **846** |
57
+ | 文件 | 3170 changed |
58
+ | 行 | +103,990 / −17,687 |
59
+ | 源码侧(排除 snapshots/tests) | 2474 文件,+68,818 / −13,973 |
60
+
61
+ 分段 commit 分布:
62
+
63
+ | 区间 | commits |
64
+ |---|---|
65
+ | 0.1.3-alpha.2 → 0.1.5-alpha.1 | 563(大头,聚合了 Session V3 与一堆 feature) |
66
+ | 0.1.5-alpha.1 → 0.1.5-alpha.2 | 262 |
67
+ | 0.1.5-alpha.2 → 0.1.5-rc.1 | 17 |
68
+ | 0.1.5-rc.1 → 0.1.5-rc.2 | 4(收尾/backport) |
69
+
70
+ ---
71
+
72
+ ## 三、依赖面变化(对 prod 直接可见)
73
+
74
+ prod 0.1.3-alpha.2 有 **71 个 dependencies**,0.1.5-rc.2 有 **72 个**。差异:
75
+
76
+ 1. **新增运行期包 `@deepseek-ai/dsh-tool-present`**(`packages/fs/tool-present`)——新「present」工具:把 agent 产出的文件以不可变交付卡片(download card)呈现,是文件交付特性的宿主半。
77
+ 2. `apps/cli` devDeps 新增 `@deepseek-ai/dsh-agent-loop`、`@deepseek-ai/dsh-agent-loop-testkit`(内部,不影响 prod 运行面)。
78
+ 3. 新增 client 包 `ui-deliverables`(`PresentRow` / `PresentedFileCard` / `present-open`),属 web shell 交付卡片 UI。
79
+ 4. 其余全部 `@deepseek-ai/*` 依赖整体从 `^0.1.3-alpha.2` 抬到 `^0.1.5-rc.2`(同版本号齐步,无个别漂移)。
80
+ 5. 底层 `cordis` / `schemastery` / `commander` / `js-yaml` 等版本**未变**(`cordis ^4.0.2`、`schemastery ^3.18.2` 等,与 0.1.3-alpha.2 相同)。
81
+
82
+ ---
83
+
84
+ ## 四、主要变更主题(按 prod 相关度排序)
85
+
86
+ ### 1. Session 格式 v3 重写(⚠ 破坏性,最高风险)
87
+ `session-log-v3` 工作线,是本次最大的变更块。要点:
88
+
89
+ - 会话身份 **V2 → V3 迁移**(`feat(session): add identity V2-to-V3 migration and writer skeleton`)。
90
+ - system prompt 表示为 **surface node zero**(`refactor(session): represent the system prompt as surface node zero`)。
91
+ - **canonical envelopes**、PTC durable vocabulary、in-history system prompt 表示、JSONL 跨进程写所有权(lease)。
92
+ - 大量 `session.v3.jsonl` 快照与 V2/V3 迁移覆盖面单测。
93
+
94
+ > **对 prod 的含义**:会话持久化契约改变。上一轮(0.1.3-alpha.2 对齐)已实测:上游 tag diff 会打到 `session-persistence-omp.ts` / `replay.ts` / store 的 handle+lease 契约(见 2026-09-08 对齐报告)。**0.1.5 的 V3 比 0.1.3 的 V2 更进一步,破坏面更大**,`better-dsh` / `omp-web` 这类桥接会话数据的插件必须重新对齐,不能 drop-in。
95
+
96
+ ### 2. Electron 桌面打包(对 3080 web 无直接作用)
97
+ Windows/macOS/Linux 构建、mac 签名+公证、Windows 签名、auto-update、IPC 性能优化。纯桌面宿主线,与本机 `dsh web`(3080)部署无关,但意味着上游发布面从此多一个桌面产物。
98
+
99
+ ### 3. Sidebar / dockkit 重构
100
+ - `dockkit` 可逆停靠引擎、pointer 交互。
101
+ - 全局 sidebar panel、tab 导航、live tab 标题 + 文件类型图标、末 tab 关闭规则、响应式右栏、全屏 shell。
102
+ - session-log 控制移入 header「更多」菜单。
103
+
104
+ ### 4. 文件交付「present」工具 + 文档预览
105
+ - 新 `dsh-tool-present` 包:不可变文件交付下载卡片、artifact 卡原生文件动作、workspace 文件操作。
106
+ - 可扩展文档预览、文本预览分页 tab、文件类型图标集、`ui-deliverables` client 卡。
107
+ - `feat(fs)`:bounded byte-range reads(fs-local / fs-e2b)、dual-face 文件 API。
108
+
109
+ ### 5. 图表 / Markdown 预览
110
+ Chat 代码块内预览 Mermaid / Graphviz / SVG / HTML fence,适配应用主题。
111
+
112
+ ### 6. LLM 模型默认值切换(⚠ 影响 prod 行为)
113
+ - Chat Completions 默认切到 **DeepSeek V41 Flash**(`feat(llm): default Chat Completions to DeepSeek V41 Flash`)。
114
+ - 保留 V4 模型、恢复 V4 Flash Vision Exp catalog 条目。
115
+ > prod 若升级,默认模型会跟着变;需确认是否期望。
116
+
117
+ ### 7. Feedback 对话框
118
+ `/feedback` 与 Dislike 统一为一个带分类的对话框 + toast。
119
+
120
+ ### 8. Subagent catalog
121
+ 记录并观察 parent-owned child catalog(子代理目录)。
122
+
123
+ ### 9. native system / node-addon-system
124
+ 包族改名 `node-addon-system`,预编译 Node-API flock、Landlock capability 子路径。**新增原生依赖面,升级安装需留意 prod 机上的原生构建/预编译匹配**(本机已有一处 zeromq allowBuilds 特例,见 AGENTS.md §二)。
125
+
126
+ ### 10. minimal profile 行为调整
127
+ - `str_replace_editor` 从 minimal profiles 移除。
128
+ - persistent bash 输出与 one-shot shell 契约对齐。
129
+ > 只影响 minimal profile,不影响 prod `web` profile 的默认工具集。
130
+
131
+ ### 11. 其它
132
+ - CLI:从 shipped 模板创建 profile。
133
+ - skills:Playwright 视频录制 GIF。
134
+ - 内部 CI/审查自动化(weighted PR approval、review owner 排名等)——与 prod 运行无关。
135
+
136
+ ---
137
+
138
+ ## 五、对 prod 升级的风险评估(简要)
139
+
140
+ | 风险项 | 级别 | 说明 |
141
+ |---|---|---|
142
+ | Session V3 格式迁移 | 🔴 高 | 会话持久化契约变更;`better-dsh`/`omp-web` 会话桥接面需重新对齐,先例(0.1.3 V2)已证实非 drop-in |
143
+ | 模型默认切 V41 Flash | 🟠 中 | 默认行为变化,需 user 确认是否接受 |
144
+ | 新原生依赖(node-addon-system) | 🟡 中低 | 安装面原生构建/预编译匹配;本机 pnpm strictDepBuilds/allowBuilds 需复核 |
145
+ | 新工具 `dsh-tool-present` | 🟡 中低 | 新工具进入 agent 运行时,需确认与现有工具/插件无 id 冲突 |
146
+ | Sidebar/dockkit UI 重构 | 🟢 低(功能面) | 纯增量 UI,但 better-dsh 的 mobile 手势/侧栏 patch 需复测是否仍对齐 |
147
+ | Electron 桌面 | ⚪ 无关 | 不影响 web 部署 |
148
+
149
+ ---
150
+
151
+ ## 六、建议
152
+
153
+ 1. 本次**只做对账、不做升级**:0.1.5 是聚合大版本,且含 Session V3 破坏性契约变更,不能当「换版本号」处理。
154
+ 2. 若后续要升级,按 AGENTS.md §一/§二走 **Dev/Test 1(4999 源码级)对齐轮**:切 `dsh-v0.1.5-rc.2` → 重放三处本地 patch(storeDir / unrun devDep / resolveRepositoryRoot)→ install/build → 插件契约对齐(重点 `session-persistence-omp.ts`/`replay.ts`/store 的 V3 handle+lease)→ tsc/单测 → 4999 第一人称实测 → 报告落 `docs/50_test-reports/` → user 确认 → 才动 prod 3080。
155
+ 3. 升级目标版本**首选 `0.1.5-rc.2`(`next`)而非 `latest`(rc.1)**,因为 rc.2 才是最高版本;但 rc 阶段仍建议等上游正式 stable 后再定。
156
+ 4. 升级前单独确认模型默认值(V41 Flash)是否要在 prod 生效。
@@ -0,0 +1,33 @@
1
+ Run one Python cell on a session-persistent scripting pad. One `eval` call = one cell; the pad's state persists across calls and turns — variables, imports, and definitions from earlier cells stay alive.
2
+
3
+ Work incrementally: imports → define → test → use, each its own cell. Re-run setup only after `reset` or a crash.
4
+
5
+ ## Arguments
6
+
7
+ - `cell` (required): one Python program body. Top-level `await` works; top-level `return` is a SyntaxError — the cell runs in module scope (REPL semantics, not a function body).
8
+ - `description` (required): a short summary of what the cell does — shown as the call's title in the UI.
9
+ - `timeout` (optional): wall-clock budget in seconds; the cell is interrupted (then force-stopped) when exceeded. Omit for the runtime default.
10
+ - `reset` (optional): restart the pad EMPTY first — earlier state is discarded.
11
+
12
+ ## Direct calls vs cells
13
+
14
+ Payload-shaped work (one long read, one edit, one command) → direct tool call. Logic-shaped work (loops, conditions, fan-out, composing many tool results into one step) → an `eval` cell. Only what the cell prints or returns comes back — curate it.
15
+
16
+ Delegation: `agent` is the unified agent-spawn entry; `subagent` is its native alias — both delegate through the same runtime, so call either.
17
+
18
+ ## Calling tools from a cell
19
+
20
+ Every session tool is callable from a cell as `await tool.<name>(args)` with ONE positional argument: `args` is the tool's parameter object written as a Python dict literal, same field names (`true`/`false`/`null` become `True`/`False`/`None`). A failed call raises `ToolCallError` with `.toolName` naming the tool. Tool names that are not plain identifiers (e.g. contain hyphens) have no `tool.<name>` member — call those as direct tool calls.
21
+
22
+ ```python
23
+ print(await tool.read({"path": "docs/README.md", "limit": 5}))
24
+
25
+ r = await tool.bash({"command": "ls -la src/", "description": "List source directory"})
26
+ print(r["stdout"]["text"])
27
+
28
+ import asyncio
29
+ matches, files = await asyncio.gather(
30
+ tool.grep({"pattern": "TODO", "path": "src"}),
31
+ tool.glob({"pattern": "**/*.ts", "path": "src"}),
32
+ )
33
+ ```
@@ -185,14 +185,12 @@ function FailoverRow({ catalog, loadConfig, save, t }) {
185
185
 
186
186
  //#endregion
187
187
  //#region src/mobile/gesture.ts
188
- /**
189
- * Resolved defaults — the `1706b81` constants (120 / viewport÷4 / 40 / 1.3 /
190
- * 768) plus the one addition, the velocity gate. A slow text-selection drag
191
- * runs ~0.13 px/ms; 0.15 px/ms filters those while any comfortable sweep
192
- * (0.4 px/ms and up) passes.
188
+ /** Resolved defaults — the `1706b81` constants (120 / viewport÷4 / 40 / 1.3)
189
+ * plus the one addition, the velocity gate. A slow text-selection drag runs
190
+ * ~0.13 px/ms; 0.15 px/ms filters those while any comfortable sweep (0.4
191
+ * px/ms and up) passes.
193
192
  */
194
193
  const DEFAULT_SWIPE_THRESHOLDS = {
195
- breakpoint: 768,
196
194
  swipeDistancePx: 40,
197
195
  dominanceRatio: 1.3,
198
196
  leftEdgeBandPx: 120,
@@ -200,16 +198,6 @@ const DEFAULT_SWIPE_THRESHOLDS = {
200
198
  swipeVelocityPxPerMs: .15
201
199
  };
202
200
  /**
203
- * Whether one completed gesture's viewport is in the gesture band.
204
- *
205
- * @param viewportWidth - viewport width at gesture time (px).
206
- * @param thresholds - resolved recognition thresholds (`.breakpoint`).
207
- * @returns `true` when `viewportWidth` is strictly below the breakpoint.
208
- */
209
- function isNarrowViewport(viewportWidth, thresholds) {
210
- return viewportWidth < thresholds.breakpoint;
211
- }
212
- /**
213
201
  * Whether a pointerdown may START a gesture — the source's pointerdown
214
202
  * gate, verbatim: with both panels closed, only the left band (X120) or
215
203
  * the right three quarters of the screen admit; with a panel open, any
@@ -275,7 +263,6 @@ function resolveMobileConfig(pageConfig) {
275
263
  const v = (value, fallback) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : fallback;
276
264
  return {
277
265
  enabled: true,
278
- breakpoint: n(pageConfig.breakpoint, DEFAULT_SWIPE_THRESHOLDS.breakpoint),
279
266
  swipeDistancePx: n(pageConfig.swipeDistancePx, DEFAULT_SWIPE_THRESHOLDS.swipeDistancePx),
280
267
  dominanceRatio: n(pageConfig.dominanceRatio, DEFAULT_SWIPE_THRESHOLDS.dominanceRatio),
281
268
  leftEdgeBandPx: n(pageConfig.leftEdgeBandPx, DEFAULT_SWIPE_THRESHOLDS.leftEdgeBandPx),
@@ -291,19 +278,32 @@ function readLeftCollapsed() {
291
278
  return document.querySelector("[data-sidebar-collapsed]") !== null;
292
279
  }
293
280
  /**
294
- * Better Sidebar's right-panel state, live off the body attribute the
295
- * plugin itself publishes (collapsed = closed). Read SYNCHRONOUSLY in the
296
- * handlers — a cached mirror lags the panel's own DOM write by a render,
297
- * and a close-swipe issued right after an open-swipe would misroute.
281
+ * The OFFICIAL right sidebar's state (0.1.5 ui-sidebar-right), read from
282
+ * AppFrame's TWO presentation facets, synchronously (a cached mirror lags
283
+ * the panel's own DOM write by a render, and a close-swipe issued right
284
+ * after an open-swipe would misroute):
285
+ *
286
+ * - `[data-rightbar-collapsed]` — the reserved GRID TRACK facet (present =
287
+ * zero-width right column). On phones (<768) the panel presents FULLSCREEN
288
+ * WITHOUT a track (`autoFullscreen` in SidebarRight), so this attribute
289
+ * alone misreads a panel that covers the whole frame as "closed" — the
290
+ * 2026-09-11 field bug: every close-swipe misrouted to open-left.
291
+ * - `[data-rightbar-fullscreen]` — the overlay facet (present = fullscreen
292
+ * presentation active, open by definition).
293
+ *
294
+ * Open = track reserved OR fullscreen overlay. On hosts before 0.1.5 both
295
+ * attributes never appear: closed, permanently — left gestures unaffected.
298
296
  */
299
297
  function readRightOpen() {
300
- return !document.body.hasAttribute("data-dsh-sidebar-collapsed");
298
+ const fullscreen = document.querySelector("[data-rightbar-fullscreen]") !== null;
299
+ const trackless = document.querySelector("[data-rightbar-collapsed]") !== null;
300
+ return fullscreen || !trackless;
301
301
  }
302
302
  /**
303
303
  * Whether a session is current — the plugin-side stand-in for the source's
304
- * `detailsSession !== undefined` guard (the right panel opens in a session
305
- * only). Better Sidebar's own shipped CSS keys off the same slot selector,
306
- * so it is load-bearing beyond this feature.
304
+ * `detailsSession !== undefined` guard (the right panel is a
305
+ * session-scoped surface; without a session its expand button is not
306
+ * rendered, so opening would be a no-op anyway).
307
307
  */
308
308
  function readSessionLive() {
309
309
  return document.querySelector("[data-slot=\"conversation.session.header\"]") !== null;
@@ -316,32 +316,38 @@ function readPanelState() {
316
316
  };
317
317
  }
318
318
  /**
319
- * Toggle Better Sidebar's right panel through its persistent DOM: the
320
- * plugin exposes no JS toggle on its client service (its open/close
321
- * reducer is store-internal), so the swipe reaches it the same way the
322
- * source did — clicking the LAST button of its always-rendered
323
- * `[data-dsh-toggle-cluster]` (the bottom-panel button precedes it and is
324
- * absent below the plugin's 768px narrow breakpoint). Absent cluster or
325
- * buttons: a no-op, never a crash.
319
+ * Drive the OFFICIAL right sidebar through its own controls (0.1.5
320
+ * ui-sidebar-right): opening clicks `[data-sidebar-right-expand]` (the
321
+ * conversation header corner button — the panel's own documented "way
322
+ * into a hidden panel", rendered exactly while collapsed with a session);
323
+ * closing clicks `[data-sidebar-right-toggle]` (the dock chrome toggle).
324
+ * The store action behind them (`setExpanded`/`toggleExpanded`) is
325
+ * slot-store-internal — cross-plugin imports are the hard boundary, so
326
+ * the native buttons ARE the sanctioned entry. Absent button (pre-0.1.5
327
+ * host, no session, or already in the target state): a no-op, never a
328
+ * crash.
326
329
  */
327
- function toggleBetterSidebar() {
328
- const buttons = document.querySelector("[data-dsh-toggle-cluster]")?.querySelectorAll("button");
329
- (buttons?.[buttons.length - 1])?.click();
330
+ function openRightPanel() {
331
+ document.querySelector("[data-sidebar-right-expand]")?.click();
332
+ }
333
+ function closeRightPanel() {
334
+ document.querySelector("[data-sidebar-right-toggle]")?.click();
330
335
  }
331
336
  /**
332
- * The narrow-viewport CSS: zero-width sidebar track under the breakpoint,
333
- * keyed to AppFrame's semantic attribute (survives class-hash churn).
334
- * Rendered with the breakpoint baked in (media queries cannot read JS
335
- * config); the tag carries the plugin-owned dataset so the loader's
336
- * style-claim machinery removes it on unload, like module CSS.
337
+ * The responsive CSS: zero-width sidebar track whenever upstream's layout
338
+ * has collapsed the sidebar, keyed PURELY to AppFrame's semantic
339
+ * attribute (survives class-hash churn). No width media query of our own
340
+ * (2026-09-11 ruling): upstream owns the auto-collapse threshold (1024
341
+ * today), and this rule simply takes the 56px rail they leave behind to
342
+ * zero. If upstream renames the attribute the rule stops matching and
343
+ * their native rail renders (benign degradation). The tag carries the
344
+ * plugin-owned dataset so the loader's style-claim machinery removes it
345
+ * on unload, like module CSS.
337
346
  */
338
- function mobileCss(breakpointPx) {
339
- const wide = Math.max(1, Math.floor(breakpointPx) - .02);
347
+ function mobileCss() {
340
348
  return [
341
- `@media (max-width: ${String(wide)}px) {`,
342
- ` [data-sidebar-collapsed] {`,
343
- ` grid-template-columns: 0px minmax(0, 1fr) 0px !important;`,
344
- ` }`,
349
+ `[data-sidebar-collapsed] {`,
350
+ ` grid-template-columns: 0px minmax(0, 1fr) 0px !important;`,
345
351
  `}`
346
352
  ].join("\n");
347
353
  }
@@ -361,7 +367,7 @@ function setupMobileLayout(ctx) {
361
367
  const tag = document.createElement("style");
362
368
  tag.dataset.plugin = "better-dsh";
363
369
  tag.dataset.pluginCss = styleTagId;
364
- tag.textContent = mobileCss(config.breakpoint);
370
+ tag.textContent = mobileCss();
365
371
  document.head.append(tag);
366
372
  const offLayout = ctx.inject(["layout"], (layoutCtx) => {
367
373
  const layout = layoutCtx.get("layout");
@@ -370,8 +376,10 @@ function setupMobileLayout(ctx) {
370
376
  const onPointerDown = (event) => {
371
377
  start = void 0;
372
378
  const viewport = window.innerWidth;
373
- if (!isNarrowViewport(viewport, config)) return;
374
- if (!admitsSwipeStart(event.clientX, viewport, readPanelState(), config)) return;
379
+ const coarsePointer = window.matchMedia?.("(pointer: coarse)").matches === true;
380
+ const panels = readPanelState();
381
+ if (!coarsePointer && !panels.leftCollapsed && !panels.rightOpen) return;
382
+ if (!admitsSwipeStart(event.clientX, viewport, panels, config)) return;
375
383
  start = {
376
384
  x: event.clientX,
377
385
  y: event.clientY,
@@ -389,7 +397,8 @@ function setupMobileLayout(ctx) {
389
397
  if (action === null) return;
390
398
  start = void 0;
391
399
  if (action === "open-left" || action === "close-left") layout.toggleSidebar();
392
- else toggleBetterSidebar();
400
+ else if (action === "open-right") openRightPanel();
401
+ else closeRightPanel();
393
402
  };
394
403
  const onPointerEnd = () => {
395
404
  start = void 0;
package/lib/index.d.ts CHANGED
@@ -1,9 +1,8 @@
1
- import { t as DASHRSdkSchema } from "./py-sdk-BCaOGYz7.js";
2
1
  import { Context, Service } from "@deepseek-ai/cordis";
3
2
  import z from "@deepseek-ai/schemastery";
4
3
  import { ToolDefinition, ToolExecutionInput, ToolRunContext, ToolRuntime } from "@deepseek-ai/dsh-tools";
5
4
  import { ContentBlock, HarnessError } from "@deepseek-ai/dsh-llm";
6
- import { ScopeKey, Scoped } from "@deepseek-ai/dsh-scope";
5
+ import { Scoped } from "@deepseek-ai/dsh-scope";
7
6
  import { Agent } from "@deepseek-ai/dsh-agent";
8
7
 
9
8
  //#region src/vendored/types.d.ts
@@ -549,7 +548,6 @@ interface WebTrustConfig {
549
548
  trustedPageAuthorities?: readonly string[];
550
549
  mobile?: {
551
550
  enabled?: boolean;
552
- breakpoint?: number;
553
551
  swipeDistancePx?: number;
554
552
  dominanceRatio?: number;
555
553
  leftEdgeBandPx?: number;
@@ -617,10 +615,6 @@ declare const MASKED_TOOL_NAMES: ReadonlySet<string>;
617
615
  * bridges that read captured definitions.
618
616
  */
619
617
  declare const WIRE_MASKED_NAMES: ReadonlySet<string>;
620
- /** The `dashr:control-prompt` section order: the FIRST section in the 100–199 tool-guidance band, so the cell paradigm is taught before the Tool Catalog renders its signatures. */
621
- declare const CONTROL_SECTION_ORDER = 100;
622
- /** The `dashr:tool-catalog` section order: the 100–199 tool-guidance band's SDK position, matching upstream `tools:sdk`. */
623
- declare const SDK_SECTION_ORDER = 150;
624
618
  /**
625
619
  * The `dashr:escalation-guidance` CONTEXT order: sits inside the runtime-context snapshot
626
620
  * band between upstream `approval:policy` (115) and `subagent:delegation` (120) — the
@@ -671,7 +665,7 @@ declare module '@deepseek-ai/cordis' {
671
665
  /**
672
666
  * Allow a listener to replace content in the DURABLE LOG COPY of one
673
667
  * `eval` sub-dispatch outcome before the bridge appends its
674
- * `tool/code-dispatch` event. `next()` keeps the content unchanged; a
668
+ * `tool/ptc-dispatch` event. `next()` keeps the content unchanged; a
675
669
  * listener may return replacement blocks (e.g. the spill policy's preview
676
670
  * + locator for an oversized text result). Scope-filtered dispatch
677
671
  * (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that
@@ -714,7 +708,7 @@ interface RunCellBridgeOptions {
714
708
  * in the module doc. Sub-calls ride the registry's exported staged scheduler
715
709
  * (`prepare`/`dispatch`/`finalize`/`finish`) under the native concurrency
716
710
  * contract; each sub-dispatch is logged for reconstruction
717
- * (`tool/code-dispatch-start` / `tool/code-dispatch`) while only the outer
711
+ * (`tool/ptc-dispatch-start` / `tool/ptc-dispatch`) while only the outer
718
712
  * curated result enters model history.
719
713
  * @param registry - the host tool registry (sub-calls go through its staged
720
714
  * scheduler, bindings cover its registered tools).
@@ -722,17 +716,6 @@ interface RunCellBridgeOptions {
722
716
  * @returns the registry-ready definition.
723
717
  */
724
718
  declare function createRunCellTool(registry: ToolRuntime, options: RunCellBridgeOptions): ToolDefinition;
725
- /**
726
- * Collect one calling scope's bridge-declaration schemas through the
727
- * registry's public projection APIs: `schemas(scope)` for the model-facing
728
- * view (scoped tools join, restrictions apply — the wire mask is a
729
- * registry-level restriction installed at session-start, so every masked
730
- * name is ALREADY absent from this projection; no second name filter
731
- * exists to drift), `get(name, scope)` for the canonical output schema,
732
- * snapshotted so a live definition cannot mutate under the render. `eval`
733
- * itself is excluded — it is the transport, not a binding.
734
- */
735
- declare function collectSdkSchemas(registry: ToolRuntime, scope?: ScopeKey): DASHRSdkSchema[];
736
719
  declare function apply(ctx: Context, config: Config): void;
737
720
  declare const _default: {
738
721
  name: string;
@@ -741,4 +724,4 @@ declare const _default: {
741
724
  apply: typeof apply;
742
725
  };
743
726
  //#endregion
744
- export { CONTROL_SECTION_ORDER, Config, DASHRRunFailedError, DashrRuntime, ESCALATION_GUIDANCE_ORDER, EVAL_NAME, MASKED_TOOL_NAMES, ReplDispatchLog, ReplRuntime, RunCellBridgeOptions, type Config$1 as RuntimeConfig, SDK_SECTION_ORDER, WIRE_MASKED_NAMES, apply, collectSdkSchemas, createRunCellTool, _default as default, inject, name, resolveMaxParallelSubCalls };
727
+ export { Config, DASHRRunFailedError, DashrRuntime, ESCALATION_GUIDANCE_ORDER, EVAL_NAME, MASKED_TOOL_NAMES, ReplDispatchLog, ReplRuntime, RunCellBridgeOptions, type Config$1 as RuntimeConfig, WIRE_MASKED_NAMES, apply, createRunCellTool, _default as default, inject, name, resolveMaxParallelSubCalls };