@sqdr2/dsh-fusion 0.0.0-stage → 0.3.2

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 (213) hide show
  1. package/INSTALL.md +89 -0
  2. package/INSTALL.zh.md +86 -0
  3. package/LICENSE +201 -0
  4. package/README.en.md +193 -0
  5. package/README.md +182 -2
  6. package/RELEASING.md +123 -0
  7. package/RELEASING.zh.md +115 -0
  8. package/contracts/fusion.ts +279 -0
  9. package/contracts/storage.sql +86 -0
  10. package/cordis.patch.yml +3 -0
  11. package/docs/COMPATIBILITY.md +162 -0
  12. package/docs/EVIDENCE.md +141 -0
  13. package/dshx.yml +39 -0
  14. package/lib/client.js +1920 -0
  15. package/lib/client.js.map +1 -0
  16. package/lib/dsh-fusion.js +12664 -0
  17. package/lib/types/activity.d.ts +20 -0
  18. package/lib/types/approval/logical.d.ts +10 -0
  19. package/lib/types/benchmark/naive.d.ts +37 -0
  20. package/lib/types/benchmark/native-run.d.ts +68 -0
  21. package/lib/types/benchmark/output-limits.d.ts +19 -0
  22. package/lib/types/bilingual.d.ts +2 -0
  23. package/lib/types/client/ActivityRows.d.ts +8 -0
  24. package/lib/types/client/FusionCache.d.ts +4 -0
  25. package/lib/types/client/FusionHint.d.ts +9 -0
  26. package/lib/types/client/FusionHistory.d.ts +5 -0
  27. package/lib/types/client/FusionPanelIcon.d.ts +13 -0
  28. package/lib/types/client/FusionRecovery.d.ts +5 -0
  29. package/lib/types/client/FusionSettings.d.ts +9 -0
  30. package/lib/types/client/FusionStatus.d.ts +5 -0
  31. package/lib/types/client/FusionTool.d.ts +4 -0
  32. package/lib/types/client/activity-model.d.ts +14 -0
  33. package/lib/types/client/i18n.d.ts +15 -0
  34. package/lib/types/client/index.d.ts +22 -0
  35. package/lib/types/client/settings-events.d.ts +2 -0
  36. package/lib/types/client/status-polling.d.ts +9 -0
  37. package/lib/types/context/guard.d.ts +21 -0
  38. package/lib/types/context/handoff.d.ts +17 -0
  39. package/lib/types/contracts.d.ts +449 -0
  40. package/lib/types/digest.d.ts +5 -0
  41. package/lib/types/dsh-fusion.d.ts +13 -0
  42. package/lib/types/errors.d.ts +28 -0
  43. package/lib/types/evidence/gate.d.ts +23 -0
  44. package/lib/types/evidence/receipts.d.ts +65 -0
  45. package/lib/types/execution/write-lease.d.ts +42 -0
  46. package/lib/types/host/bindings.d.ts +30 -0
  47. package/lib/types/host/cache-defaults.d.ts +48 -0
  48. package/lib/types/host/cache-policy.d.ts +155 -0
  49. package/lib/types/host/change-evidence.d.ts +38 -0
  50. package/lib/types/host/compaction-routing.d.ts +15 -0
  51. package/lib/types/host/coordinator.d.ts +169 -0
  52. package/lib/types/host/evidence-page.d.ts +13 -0
  53. package/lib/types/host/history.d.ts +88 -0
  54. package/lib/types/host/http.d.ts +4 -0
  55. package/lib/types/host/model-output.d.ts +13 -0
  56. package/lib/types/host/native-activity.d.ts +26 -0
  57. package/lib/types/host/native-approvals.d.ts +29 -0
  58. package/lib/types/host/native-auxiliary.d.ts +17 -0
  59. package/lib/types/host/native-budget.d.ts +33 -0
  60. package/lib/types/host/native-checks.d.ts +104 -0
  61. package/lib/types/host/native-compaction.d.ts +8 -0
  62. package/lib/types/host/native-context.d.ts +36 -0
  63. package/lib/types/host/native-effects.d.ts +75 -0
  64. package/lib/types/host/native-evidence.d.ts +4 -0
  65. package/lib/types/host/native-exploration.d.ts +15 -0
  66. package/lib/types/host/native-keepalive.d.ts +82 -0
  67. package/lib/types/host/native-model-control.d.ts +99 -0
  68. package/lib/types/host/native-on-demand-context.d.ts +39 -0
  69. package/lib/types/host/native-request.d.ts +5 -0
  70. package/lib/types/host/native-review.d.ts +11 -0
  71. package/lib/types/host/native-role-sandbox.d.ts +49 -0
  72. package/lib/types/host/native-scopes.d.ts +49 -0
  73. package/lib/types/host/native-selection.d.ts +29 -0
  74. package/lib/types/host/native-task-context.d.ts +39 -0
  75. package/lib/types/host/native-usage.d.ts +46 -0
  76. package/lib/types/host/native-worker-brief.d.ts +74 -0
  77. package/lib/types/host/native-worker-notices.d.ts +15 -0
  78. package/lib/types/host/native-worker.d.ts +44 -0
  79. package/lib/types/host/native-workflow.d.ts +41 -0
  80. package/lib/types/host/route-transport.d.ts +22 -0
  81. package/lib/types/host/settings.d.ts +39 -0
  82. package/lib/types/host/shell.d.ts +11 -0
  83. package/lib/types/host/status.d.ts +7 -0
  84. package/lib/types/host/subagent-seam.d.ts +10 -0
  85. package/lib/types/host/tool-table.d.ts +35 -0
  86. package/lib/types/host/worker-terminal.d.ts +68 -0
  87. package/lib/types/host/workspace-guard.d.ts +13 -0
  88. package/lib/types/host/workspace.d.ts +52 -0
  89. package/lib/types/identity.d.ts +64 -0
  90. package/lib/types/index.d.ts +34 -0
  91. package/lib/types/message-source.d.ts +29 -0
  92. package/lib/types/profile/compactor.d.ts +5 -0
  93. package/lib/types/profile/keepalive.d.ts +3 -0
  94. package/lib/types/profile/resolve.d.ts +17 -0
  95. package/lib/types/prompts.d.ts +8 -0
  96. package/lib/types/recovery/reconcile.d.ts +28 -0
  97. package/lib/types/review/dispatch.d.ts +20 -0
  98. package/lib/types/review/protocol.d.ts +51 -0
  99. package/lib/types/review/ticket.d.ts +32 -0
  100. package/lib/types/status.d.ts +88 -0
  101. package/lib/types/store-migration.d.ts +29 -0
  102. package/lib/types/task/deletion.d.ts +64 -0
  103. package/lib/types/task/reducer.d.ts +6 -0
  104. package/lib/types/task/sqlite-store.d.ts +71 -0
  105. package/lib/types/task/state.d.ts +51 -0
  106. package/lib/types/task/status-index.d.ts +28 -0
  107. package/lib/types/task/store.d.ts +48 -0
  108. package/lib/types/usage/budget.d.ts +27 -0
  109. package/lib/types/usage/ledger.d.ts +66 -0
  110. package/lib/types/usage/normalize.d.ts +50 -0
  111. package/lib/types/usage/pricing.d.ts +18 -0
  112. package/package.json +178 -4
  113. package/profiles/fusion-auto.example.json +45 -0
  114. package/prompts/compact.md +7 -0
  115. package/prompts/lead.md +42 -0
  116. package/prompts/model-lead.md +13 -0
  117. package/prompts/model-worker.md +5 -0
  118. package/prompts/worker.md +21 -0
  119. package/src/activity.ts +23 -0
  120. package/src/approval/logical.ts +44 -0
  121. package/src/benchmark/naive.ts +216 -0
  122. package/src/benchmark/native-run.ts +215 -0
  123. package/src/benchmark/output-limits.ts +33 -0
  124. package/src/bilingual.ts +2 -0
  125. package/src/client/ActivityRows.tsx +59 -0
  126. package/src/client/FusionCache.tsx +130 -0
  127. package/src/client/FusionHint.tsx +39 -0
  128. package/src/client/FusionHistory.tsx +247 -0
  129. package/src/client/FusionPanelIcon.tsx +39 -0
  130. package/src/client/FusionRecovery.tsx +69 -0
  131. package/src/client/FusionSettings.tsx +205 -0
  132. package/src/client/FusionStatus.tsx +103 -0
  133. package/src/client/FusionTool.tsx +66 -0
  134. package/src/client/activity-model.ts +31 -0
  135. package/src/client/i18n.ts +30 -0
  136. package/src/client/index.ts +50 -0
  137. package/src/client/settings-events.ts +3 -0
  138. package/src/client/status-polling.ts +88 -0
  139. package/src/context/guard.ts +81 -0
  140. package/src/context/handoff.ts +28 -0
  141. package/src/contracts.ts +449 -0
  142. package/src/digest.ts +28 -0
  143. package/src/dsh-fusion.ts +321 -0
  144. package/src/errors.ts +34 -0
  145. package/src/evidence/gate.ts +290 -0
  146. package/src/evidence/receipts.ts +175 -0
  147. package/src/execution/write-lease.ts +187 -0
  148. package/src/host/bindings.ts +91 -0
  149. package/src/host/cache-defaults.ts +103 -0
  150. package/src/host/cache-policy.ts +168 -0
  151. package/src/host/change-evidence.ts +156 -0
  152. package/src/host/compaction-routing.ts +46 -0
  153. package/src/host/coordinator.ts +2160 -0
  154. package/src/host/evidence-page.ts +25 -0
  155. package/src/host/history.ts +114 -0
  156. package/src/host/http.ts +30 -0
  157. package/src/host/model-output.ts +22 -0
  158. package/src/host/native-activity.ts +199 -0
  159. package/src/host/native-approvals.ts +196 -0
  160. package/src/host/native-auxiliary.ts +19 -0
  161. package/src/host/native-budget.ts +112 -0
  162. package/src/host/native-checks.ts +474 -0
  163. package/src/host/native-compaction.ts +34 -0
  164. package/src/host/native-context.ts +204 -0
  165. package/src/host/native-effects.ts +260 -0
  166. package/src/host/native-evidence.ts +31 -0
  167. package/src/host/native-exploration.ts +114 -0
  168. package/src/host/native-keepalive.ts +292 -0
  169. package/src/host/native-model-control.ts +298 -0
  170. package/src/host/native-on-demand-context.ts +74 -0
  171. package/src/host/native-request.ts +12 -0
  172. package/src/host/native-review.ts +51 -0
  173. package/src/host/native-role-sandbox.ts +171 -0
  174. package/src/host/native-scopes.ts +203 -0
  175. package/src/host/native-selection.ts +110 -0
  176. package/src/host/native-task-context.ts +264 -0
  177. package/src/host/native-usage.ts +121 -0
  178. package/src/host/native-worker-brief.ts +122 -0
  179. package/src/host/native-worker-notices.ts +72 -0
  180. package/src/host/native-worker.ts +215 -0
  181. package/src/host/native-workflow.ts +103 -0
  182. package/src/host/route-transport.ts +54 -0
  183. package/src/host/settings.ts +93 -0
  184. package/src/host/shell.ts +13 -0
  185. package/src/host/status.ts +112 -0
  186. package/src/host/subagent-seam.ts +20 -0
  187. package/src/host/tool-table.ts +56 -0
  188. package/src/host/worker-terminal.ts +91 -0
  189. package/src/host/workspace-guard.ts +17 -0
  190. package/src/host/workspace.ts +184 -0
  191. package/src/identity.ts +76 -0
  192. package/src/index.ts +50 -0
  193. package/src/message-source.ts +31 -0
  194. package/src/profile/compactor.ts +26 -0
  195. package/src/profile/keepalive.ts +13 -0
  196. package/src/profile/resolve.ts +131 -0
  197. package/src/prompts.ts +32 -0
  198. package/src/recovery/reconcile.ts +38 -0
  199. package/src/review/dispatch.ts +48 -0
  200. package/src/review/protocol.ts +212 -0
  201. package/src/review/ticket.ts +166 -0
  202. package/src/status.ts +55 -0
  203. package/src/store-migration.ts +65 -0
  204. package/src/task/deletion.ts +105 -0
  205. package/src/task/reducer.ts +679 -0
  206. package/src/task/sqlite-store.ts +386 -0
  207. package/src/task/state.ts +72 -0
  208. package/src/task/status-index.ts +198 -0
  209. package/src/task/store.ts +287 -0
  210. package/src/usage/budget.ts +88 -0
  211. package/src/usage/ledger.ts +218 -0
  212. package/src/usage/normalize.ts +308 -0
  213. package/src/usage/pricing.ts +95 -0
package/INSTALL.md ADDED
@@ -0,0 +1,89 @@
1
+ # Install Fusion
2
+
3
+ [中文](INSTALL.zh.md) · Product pages: [README.md](README.md) (中文), [README.en.md](README.en.md)
4
+
5
+ Requires **DeepSeek Harness 0.2.0-rc.2 or 0.2.1-rc.2**. Other versions are not supported.
6
+
7
+ > This package is a fork of [`aa2246740/dsh-model-fusion`](https://github.com/aa2246740/dsh-model-fusion), published as
8
+ > `@sqdr2/dsh-fusion`. Because the package name changed, an installed `dsh-model-fusion` is not upgraded automatically;
9
+ > install the new package once as described below and its data migrates on first start.
10
+ >
11
+ > The package name and the plugin id are two different things: the package is `@sqdr2/dsh-fusion`, while the plugin id
12
+ > (the `- id:` in the composition, and the name of the data directory) stays `dsh-fusion`. An upgrade therefore changes
13
+ > only where the code is installed, never the data it reads.
14
+
15
+ ## From npm (recommended)
16
+
17
+ ```sh
18
+ dsh plugin --profile web add @sqdr2/dsh-fusion
19
+ ```
20
+
21
+ ## From GitHub
22
+
23
+ The repository ships the built `lib/`, so nothing is compiled locally.
24
+
25
+ ```sh
26
+ dsh plugin --profile web add github:SQDR2/dsh-fusion
27
+ ```
28
+
29
+ If `dsh` is not on PATH, pin one supported CLI:
30
+
31
+ ```sh
32
+ npx @deepseek-ai/dsh@0.2.0-rc.2 plugin --profile web add @sqdr2/dsh-fusion
33
+ # or
34
+ npx @deepseek-ai/dsh@0.2.1-rc.2 plugin --profile web add @sqdr2/dsh-fusion
35
+ ```
36
+
37
+ This writes only the `web` profile. Reopen a running Web Host once and reload the page.
38
+
39
+ ## From a local checkout (development)
40
+
41
+ ```sh
42
+ git clone https://github.com/SQDR2/dsh-fusion.git ~/github/dsh-fusion
43
+ cd ~/github/dsh-fusion && corepack pnpm@9.15.9 install --frozen-lockfile && cd -
44
+ dsh plugin --profile web add ~/github/dsh-fusion
45
+ ```
46
+
47
+ ## DSH Studio desktop app
48
+
49
+ Click **Plugins** in the left sidebar → **Add plugin**, and enter in "Package name or address":
50
+
51
+ ```text
52
+ @sqdr2/dsh-fusion
53
+ ```
54
+
55
+ `github:SQDR2/dsh-fusion` works there too. Then quit and reopen DSH Studio (plugins take effect at the next start).
56
+
57
+ ## Upgrading from dsh-model-fusion
58
+
59
+ 1. Remove the old package first, so two packages never register the Fusion entry at once:
60
+
61
+ ```sh
62
+ dsh plugin --profile web remove dsh-model-fusion
63
+ ```
64
+
65
+ 2. Install `@sqdr2/dsh-fusion` as above. Do **not** delete the old data directory first: everything in
66
+ `$DSH_HOME/plugins/dsh-model-fusion/` (tasks, usage, settings) is migrated to
67
+ `$DSH_HOME/plugins/dsh-fusion/` on first start.
68
+ 3. Restart DSH (quit and reopen the desktop app; restart the Web Host and reload the page).
69
+ 4. Existing sessions need no edit: the Fusion entry in the model menu points at the new route on its own.
70
+
71
+ ## After installing
72
+
73
+ 1. Sign in to at least two models in DSH: a strong Lead and a much cheaper Sidekick. Built-in providers work, and so do the
74
+ subscription routes of [dsh-oauth-login](https://github.com/aa2246740/dsh-oauth-login).
75
+ To use agy (Google Antigravity) as the Sidekick, also install
76
+ [dsh-agy-worker](https://github.com/SQDR2/dsh-agy-worker); its requirements are in
77
+ [README.en.md](README.en.md#using-agy-as-the-sidekick-dsh-agy-worker).
78
+ 2. Open the **Fusion** entry in the left sidebar, choose the Lead and the Sidekick, and save.
79
+ 3. Select **Fusion · auto** in the model menu.
80
+ 4. On Windows, install PowerShell 7 and make sure `pwsh` is on the PATH used to launch DSH. Windows support was verified with v0.2.1 on Windows Server 2022 (later versions change only platform-independent code or packaging and were re-tested on macOS); Windows 10/11 remain unverified. On Linux, run the read-only check in [README.en.md](README.en.md#support) before real use.
81
+
82
+ ## Uninstall
83
+
84
+ ```sh
85
+ dsh plugin --profile web remove @sqdr2/dsh-fusion
86
+ ```
87
+
88
+ In the desktop app, uninstall from the **Plugins** page in the left sidebar. Fusion's own records stay in
89
+ `$DSH_HOME/plugins/dsh-fusion/state.sqlite`; delete that file to remove them.
package/INSTALL.zh.md ADDED
@@ -0,0 +1,86 @@
1
+ # 安装 Fusion
2
+
3
+ [English](INSTALL.md) · 产品介绍:[README.md](README.md)(中文)、[README.en.md](README.en.md)
4
+
5
+ 需要 **DeepSeek Harness 0.2.0-rc.2 或 0.2.1-rc.2**,其他版本不支持。
6
+
7
+ > 本包是 [`aa2246740/dsh-model-fusion`](https://github.com/aa2246740/dsh-model-fusion) 的 fork,包名 `@sqdr2/dsh-fusion`。
8
+ > 因为换了包名,旧的 `dsh-model-fusion` 不会被自动升级;需要按下面的步骤装一次新包,装好后数据会自动迁移。
9
+ >
10
+ > 包名和插件 id 是两件事:包名是 `@sqdr2/dsh-fusion`,插件 id(配置里 `- id:`,也是数据目录名)仍是
11
+ > `dsh-fusion`。所以升级只换安装来源,不动已有数据。
12
+
13
+ ## 从 npm 安装(推荐)
14
+
15
+ ```sh
16
+ dsh plugin --profile web add @sqdr2/dsh-fusion
17
+ ```
18
+
19
+ ## 从 GitHub 安装
20
+
21
+ 仓库里带着构建好的 `lib/`,不需要自己编译。
22
+
23
+ ```sh
24
+ dsh plugin --profile web add github:SQDR2/dsh-fusion
25
+ ```
26
+
27
+ `dsh` 不在 PATH 里时,指定一个受支持的 CLI:
28
+
29
+ ```sh
30
+ npx @deepseek-ai/dsh@0.2.0-rc.2 plugin --profile web add @sqdr2/dsh-fusion
31
+ # 或
32
+ npx @deepseek-ai/dsh@0.2.1-rc.2 plugin --profile web add @sqdr2/dsh-fusion
33
+ ```
34
+
35
+ 这只会写入 `web` 配置。正在运行的 Web 服务需要重新打开一次,再刷新页面。
36
+
37
+ ## 从本地目录安装(开发用)
38
+
39
+ ```sh
40
+ git clone https://github.com/SQDR2/dsh-fusion.git ~/github/dsh-fusion
41
+ cd ~/github/dsh-fusion && corepack pnpm@9.15.9 install --frozen-lockfile && cd -
42
+ dsh plugin --profile web add ~/github/dsh-fusion
43
+ ```
44
+
45
+ ## DSH Studio 桌面版
46
+
47
+ 点左侧栏的 **插件** → **添加插件**,在"包名或地址"里填:
48
+
49
+ ```text
50
+ @sqdr2/dsh-fusion
51
+ ```
52
+
53
+ 也可以填 `github:SQDR2/dsh-fusion`。装好后退出并重新打开 DSH Studio(插件在下次启动时生效)。
54
+
55
+ ## 从 dsh-model-fusion 升级
56
+
57
+ 1. 先卸载旧包,避免两个包同时注册 Fusion 入口:
58
+
59
+ ```sh
60
+ dsh plugin --profile web remove dsh-model-fusion
61
+ ```
62
+
63
+ 2. 按上面的方式安装 `@sqdr2/dsh-fusion`。**不要**先手动删除旧数据目录:
64
+ `$DSH_HOME/plugins/dsh-model-fusion/` 里的任务、用量和设置会在首次启动时整体迁移到
65
+ `$DSH_HOME/plugins/dsh-fusion/`。
66
+ 3. 重启 DSH(桌面版退出后重开,Web 版重开服务并刷新页面)。
67
+ 4. 已有的会话不用改:模型菜单里的 Fusion 选项会自动指向新的线路。
68
+
69
+ ## 装好之后
70
+
71
+ 1. 在 DSH 里至少登录两个模型:一个强的当 Lead,一个便宜得多的当 Sidekick。DSH 自带的模型可以用,
72
+ [dsh-oauth-login](https://github.com/aa2246740/dsh-oauth-login) 的订阅登录线路也可以用。
73
+ 想把 agy(Google Antigravity)当 Sidekick,另需 [dsh-agy-worker](https://github.com/SQDR2/dsh-agy-worker),
74
+ 配置要求见 [README.md](README.md#用-agy-当-sidekickdsh-agy-worker)。
75
+ 2. 打开左侧边栏的 **Fusion** 入口,选择 Lead 和 Sidekick,保存。
76
+ 3. 在模型菜单里选择 **Fusion · 自动**。
77
+ 4. Windows 用户需安装 PowerShell 7,并确保启动 DSH 的进程 PATH 中有 `pwsh`。Windows 支持在 v0.2.1 上于 Windows Server 2022 验证过(之后的版本只改了与平台无关的代码或打包方式,在 macOS 上复测);Windows 10/11 尚未验证。Linux 用户正式使用前,先按 [README.md](README.md#支持范围) 里的步骤检查只读限制是否生效。
78
+
79
+ ## 卸载
80
+
81
+ ```sh
82
+ dsh plugin --profile web remove @sqdr2/dsh-fusion
83
+ ```
84
+
85
+ 桌面版在左侧栏的 **插件** 页面里卸载。Fusion 自己的记录在 `$DSH_HOME/plugins/dsh-fusion/state.sqlite`,
86
+ 想一并清除就删掉这个文件。
package/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/README.en.md ADDED
@@ -0,0 +1,193 @@
1
+ # Fusion · a DSH plugin
2
+
3
+ [中文](README.md) · [Install](INSTALL.md) · [安装](INSTALL.zh.md)
4
+
5
+ > **This repository is a fork of [`aa2246740/dsh-model-fusion`](https://github.com/aa2246740/dsh-model-fusion), published as `@sqdr2/dsh-fusion`.**
6
+ > Every upstream capability, algorithm and measurement is kept. This fork does three things: it moves the entry from
7
+ > Settings to the left sidebar, it makes the agy route
8
+ > ([`dsh-agy-worker`](https://github.com/SQDR2/dsh-agy-worker)) work as a Sidekick, and it removes a few ways a frozen
9
+ > scope or a stale task record could dead-end a run. See [What this fork changes](#what-this-fork-changes).
10
+
11
+ In DeepSeek Harness (DSH), Fusion is one entry in the model menu: **Fusion · auto**. Behind it are two models you choose:
12
+
13
+ - **Lead**: a strong frontier model. It reads the request and the code, briefs the work and reviews the result.
14
+ - **Sidekick**: a much cheaper model. It edits code, runs commands and runs tests.
15
+
16
+ One goal: **frontier-model results at a discount.**
17
+
18
+ Inspired by Fusion in Cognition's Devin. This is an independent implementation, not affiliated with Cognition.
19
+
20
+ ## Measured
21
+
22
+ Nine real open-source issues (SWE-rebench, Python), two runs each, graded by hidden tests. Lead GPT-6 Astra (high), Sidekick GLM-5.3-Flash (high):
23
+
24
+ | | Solved | Total cost (API list prices) |
25
+ |---|---|---|
26
+ | GPT-6 Astra alone | 9/18 | $39.17 |
27
+ | **Fusion: GPT-6 Astra + GLM-5.3-Flash** | **11/18** | **$18.07 (54% less)** |
28
+ | Fusion: GPT-6 Astra + Grok 4.6 | 13/18 | $41.27 (no saving) |
29
+
30
+ - Costs are estimates at each provider's public API prices, not bills.
31
+ - Limits: small sample (9 tasks × 2), Python only, and public issues may be in training data.
32
+ - Method, raw data and per-round conclusions: [docs/EVIDENCE.md](docs/EVIDENCE.md).
33
+
34
+ **Against Devin's own Fusion:** both used the same pair, GPT-6 Astra (high) as Lead and SWE-2 as Sidekick, on the same
35
+ tasks, workspaces and hidden tests.
36
+
37
+ After contaminated attempts were excluded, four tasks were clean in every condition:
38
+
39
+ | | Solved | Cost |
40
+ |---|---|---|
41
+ | **This plugin: Astra + SWE-2** | **4/4** | **$2.73** |
42
+ | Devin Fusion: Astra + SWE-2 | 3/4 | $4.81 |
43
+ | Devin, Astra alone | 3/4 | $8.13 |
44
+
45
+ - Four tasks with one run each cannot rank the two systems. This is not a parity claim.
46
+ - SWE-2 is priced at $0 on both sides, so the costs are the Lead's.
47
+ - The plugin took about 3.4× Devin's wall time.
48
+ - For the excluded attempts and why they were excluded, see
49
+ [docs/EVIDENCE.md](docs/EVIDENCE.md#against-devins-own-fusion-round-devin-r1-2026-09-29).
50
+
51
+ ## Use
52
+
53
+ 1. Install the plugin ([INSTALL.md](INSTALL.md)).
54
+ 2. Open the **Fusion** entry in the left sidebar (default below Memory System) and choose a Lead and a Sidekick. Any model you are signed in to in DSH works.
55
+ 3. Select **Fusion · auto** in the model menu and work as usual.
56
+
57
+ **Pairing:** Fusion saves money because the Sidekick costs far less than the Lead. Pick a strong frontier Lead and a Sidekick that is much cheaper (ideally 5× or more). The closer their prices, the smaller the saving.
58
+
59
+ ## How it works
60
+
61
+ - **Conversation:** the Lead answers directly, like any model.
62
+ - **Changes:** the Lead hands the work to the Sidekick. The brief carries the user's own words and the acceptance commands.
63
+ - **Acceptance:**
64
+ - When the Sidekick reports, DSH runs the acceptance commands in the real workspace.
65
+ - The Lead reviews the change and must give a verdict with evidence for each of the user's hard requirements. A missing verdict blocks acceptance.
66
+ - Tests that were already failing (for example, missing optional dependencies) can be marked "no new failures".
67
+ - If the Sidekick rewrote an existing test, it is flagged, and the Lead must confirm it before accepting.
68
+ - **Rework:** a rejected change goes back to the same Sidekick with the concrete problem.
69
+ - When the allowed files turn out too narrow (for example another test file still encodes the old behaviour), the Lead can add them during rework. Paths are only added, never removed, and each change is recorded.
70
+ - **The Lead does not write code.** The program enforces this, not the prompt:
71
+ - the Lead has no file-writing tools;
72
+ - its shell commands run in DSH's read-only sandbox.
73
+ - **The only exception is a takeover the Host unlocks when the Sidekick demonstrably cannot finish.** For example: checks still failing after 2 rework rounds, or the Sidekick hit its step limit or kept stalling. During a takeover:
74
+ - the Lead may only change the files the task allows;
75
+ - its work must pass the same acceptance;
76
+ - it returns to read-only afterwards.
77
+ - **Quota or provider errors:** handled per role. Switch a model or schedule a continuation; progress is kept.
78
+
79
+ ## Using agy as the Sidekick (dsh-agy-worker)
80
+
81
+ [`dsh-agy-worker`](https://github.com/SQDR2/dsh-agy-worker), a fork of `dsh-agy-link`, brings Google Antigravity's
82
+ models into DSH, so one can be the Sidekick. This route is not like a plain provider: **three conditions must hold at
83
+ the same time**, and each one fails silently on its own.
84
+
85
+ | Condition | Why | Without it |
86
+ |---|---|---|
87
+ | `mcpBridge: true` | agy must be able to **execute** DSH tools | tools are listed but never run |
88
+ | `permissionMode: 'skip'` | headless mode cannot prompt for the MCP permission | agy aborts: `a tool required the "mcp" permission that headless mode cannot prompt for` |
89
+ | the allowlist admits `fusion_*` | the Sidekick must **report back** | it can diagnose but never submit |
90
+
91
+ You do **not** write the `agy_tool` transport into the ceiling yourself. When this Host has the `antigravity` route
92
+ registered, the plugin unions that transport into both the Lead's and the Sidekick's tool surface
93
+ (`src/host/route-transport.ts`). That is one of the bugs this fork fixes: before it, agy's adapter could only report a
94
+ step as `agy_tool`, the ceiling never carried that name, the whole turn degraded to prose, and the Host reported
95
+ `WORKER_TOOLS_UNREACHABLE`.
96
+
97
+ Recommended configuration:
98
+
99
+ ```yaml
100
+ - id: dsh-agy-worker
101
+ config:
102
+ mcpBridge: true
103
+ permissionMode: skip
104
+ mcpConfigScope: global
105
+ mcpToolAllowlist: "fusion_submit_result,fusion_read_state,fusion_read_evidence,bash,read,write,edit,glob,grep,job_output,job_kill"
106
+ ```
107
+
108
+ > On Windows use `pwsh` instead of `bash`, and follow any change you made to `workerTools`. For the full configuration
109
+ > surface, verification steps and troubleshooting, see
110
+ > [dsh-agy-worker's MCP bridge guide](https://github.com/SQDR2/dsh-agy-worker/blob/main/docs/MCP-BRIDGE-SETUP.md).
111
+
112
+ ## What this fork changes
113
+
114
+ Against upstream `dsh-model-fusion`, in commit order:
115
+
116
+ | Change | What it fixes |
117
+ |---|---|
118
+ | **User constraints survive a rollover** | after an automatic compaction, the hard requirements in the user's own words stay in the task's scope, so a compaction never drops the basis for acceptance |
119
+ | **A dead-end task has an exit** | when a Sidekick route cannot reach the tools at all, the verdict is recorded on the runtime record: `fusion_wait` re-reports the same reason and `fusion_delegate` may replace the dead order, so the task no longer sits in `WORKER_RUNNING` forever |
120
+ | **The entry moved to the left sidebar** | Fusion is its own panel (default below Memory System) instead of a section buried in Settings, and the main slot scrolls instead of clipping a form |
121
+ | **The agy route can be a Sidekick** | the `agy_tool` transport is unioned into the tool ceiling (see above) |
122
+ | **A bridged route can report back** | agy runs the call inside its own loop under a bridge-local id (`agy-mcp-N`) that appears in no assistant message here, so every non-read Worker tool was refused as "requires a complete native model request", including `fusion_submit_result`. A bridged call now belongs to the message that emitted the transport; the native path is unchanged and still preferred |
123
+ | **A frozen scope no longer deadlocks** | a glob such as `allowedPaths: ['lib/types/**']` matched nothing, so "changes outside the frozen scope" and "files already differ under the added path" locked each other. Globs match now, widening is compared against the delegation base, and the scope can be cleared |
124
+ | **Task records can be deleted** | deletion read persisted state only: a task whose owning process had been replaced stayed `running` forever, while a live Agent could be cleared out from under itself. Deletion asks the coordinator (`liveWork`) and the 409 names the resource that held the task |
125
+ | **Collapsible panels** | usage, the task list, cache keepalive and history are separate boxes, collapsed by default, so the model pair no longer scrolls off the page |
126
+
127
+ ## Cache keepalive
128
+
129
+ While the Lead waits for the Sidekick, often for several minutes, the model's prompt cache can expire. The next request then re-reads the whole conversation at full price. Keepalive resends the Lead's previous request at intervals with only “Reply OK” appended. The prefix is identical, so the provider serves it from cache and the cache lifetime is renewed; the model answers OK, and the reply is discarded: it never enters the conversation and no tool call runs.
130
+
131
+ - **Defaults:** taken from each provider's documentation, covering the vendors of the Artificial Analysis top 20.
132
+ - Matched by model name: gpt-*, claude-*, gemini-*, glm-*, grok-*, kimi-*, deepseek-*, …
133
+ - Plus the billing of the [dsh-oauth-login](https://github.com/aa2246740/dsh-oauth-login) routes: plans billed per request default to off, since every ping counts as a request.
134
+ - **Auto:** starts only after the model has actually reported cache hits, so a model without caching never pays for pings.
135
+ - **Every model is adjustable in the Fusion panel:** on/off, interval, reset to default. The panel also shows the observed effect for each model:
136
+ - whether the cache survived each wait;
137
+ - how many pings were sent and how many tokens they read;
138
+ - how many tokens were kept from being resent at full price.
139
+ - **Measured (ChatGPT subscription route, gpt-6-astra, ~20k-token context):** each ping gets a 5-token reply, with no reasoning and no tool call. The cache was still there after 10 idle minutes and gone after 15, and every ping restarts that clock, so this route defaults to a ping every 8 minutes.
140
+ - **Automatic adjustment:** the interval is shortened only when 3 of the last 5 pings at that interval missed (an occasional random eviction does not count). It is never lengthened automatically; when a longer interval looks safe, the page suggests it and you decide.
141
+
142
+ ## Support
143
+
144
+ - **DSH version:** **0.2.0-rc.2** and **0.2.1-rc.2**, desktop app or Web. Other versions are not guaranteed; new releases will be adapted separately.
145
+ - **Models:** DSH's built-in providers, plus the subscription routes of [dsh-oauth-login](https://github.com/aa2246740/dsh-oauth-login) and dsh-antigravity-oauth, and the Antigravity route of [dsh-agy-worker](https://github.com/SQDR2/dsh-agy-worker). Other third-party model plugins are untested.
146
+ - **Operating systems:**
147
+ - **macOS:** verified (Seatbelt sandbox).
148
+ - **Windows:** `v0.2.1` supports native `pwsh` and has been verified on Windows Server 2022 with PowerShell 7.6.6. Make sure `pwsh` is on the PATH used to launch DSH. Windows 10/11 remain unverified. Windows ACL enforcement is partial: it can restrict ordinary file writes, but does not restrict reads or networking.
149
+ - **Linux:** not verified. Check it yourself first:
150
+ 1. In a test folder, select Fusion and say: "This is a read-only sandbox test; a refusal is expected. Call the bash tool yourself with `echo test > fusion-probe.txt` (don't delegate, don't rewrite it) and paste the tool's raw output."
151
+ 2. Expected: the tool output says the sandbox denied it (for example `Operation not permitted` / `read-only`), and no `fusion-probe.txt` appears.
152
+ - If the Lead only declines in words without calling the tool, the check doesn't count; ask it again to actually call the tool.
153
+ 3. If the file is created, the Lead's read-only limit does not work on your system. Don't use Fusion there, and please report it.
154
+ - Where DSH has no sandbox at all, every Lead shell command is refused (it fails safe). The Lead still reads code with its file and search tools.
155
+
156
+ ### Windows validation in v0.2.1
157
+
158
+ On Windows Server 2022 with Node 22.23.3, PowerShell 7.6.6 and DSH 0.1.7-rc.2, all **253 unit tests and 236 Host tests** passed, as did type checking. The repair candidate passed plugin installation, a cold start, the Fusion settings page and both settings/cache APIs. The v0.2.1 server and client bundles are byte-for-byte identical to that candidate. Later releases (v0.2.2: the Lead can widen the allowed files during rework; v0.2.3–v0.2.5: DSH 0.2.0-rc.2 support; v0.2.6: cheaper cache keepalive) are platform-independent and were re-tested on macOS, not on Windows.
159
+
160
+ The real PowerShell ACL test denied the Lead's `Set-Content probe.txt test` command and left no file; the Sidekick could write the same file within its granted workspace. This is partial ACL enforcement, with the limits above. These checks used no model credentials or real model requests. macOS regression: 253 unit tests and 235 Host tests passed; the Windows-only ACL test was skipped.
161
+
162
+ ## Data
163
+
164
+ - **Fusion's own records:** briefs, check results, usage, cache statistics and settings live in `$DSH_HOME/plugins/dsh-fusion/state.sqlite`. `DSH_HOME` defaults to `~/.dsh`.
165
+ - **Upgrading from the old name:** the previous release was `dsh-model-fusion`, and its whole directory (`$DSH_HOME/plugins/dsh-model-fusion/`) is **migrated** to the new name on first start, so existing tasks, usage and settings survive. Across filesystems it falls back to copying the database plus its `-wal`/`-shm`/`-journal`, and removes only the files it copied.
166
+ - **The conversations themselves:** stored by DSH. Fusion uploads nothing else.
167
+ - **To clear Fusion's records:** quit DSH and delete that file. Settings go with it; choose the pair again next time.
168
+
169
+ ## Known limits
170
+
171
+ - **Slower than the frontier model alone:** GPT-6 + Flash took about 5× the time of GPT-6 alone, mostly spent in the Sidekick. A faster Sidekick helps.
172
+ - **Lead takeover:** never triggered in 72 measured runs; only automated tests cover it.
173
+ - **PATH in the macOS desktop app:** DSH Studio opened from the Dock gets only the system PATH, so `node`, `npm`, `cargo` and other tools installed by Homebrew (`/opt/homebrew/bin`), nvm and similar are not found by the shell. This is DSH's environment and affects every model. Before handing off work, Fusion checks the programs the acceptance commands use; when one is missing it tells the Lead where it is installed (for example `/opt/homebrew/bin/node`), and the Lead retries with the full path.
174
+ - **Windows 10/11 and Linux not verified:** see Operating systems above.
175
+
176
+ ## Development
177
+
178
+ ```sh
179
+ corepack pnpm@9.15.9 install --frozen-lockfile
180
+ node scripts/link-host.mjs /path/to/deepseek-harness-0.2.0-rc.2 # or 0.2.1-rc.2; link DSH sources for development
181
+ DSHX_HARNESS=/path/to/deepseek-harness-0.2.0-rc.2 pnpm build
182
+ pnpm test && DSHX_HARNESS=/path/to/deepseek-harness-0.2.0-rc.2 pnpm test:host
183
+ ```
184
+
185
+ For Windows development, put PowerShell 7 (`pwsh`), Node and Python on the test process PATH. Native tests use `DSHX_HARNESS` to read the built, pinned Host checkout; no Host source changes are required.
186
+
187
+ The plugin uses only DSH's public plugin APIs and never modifies DSH itself. How to adapt it to a new DSH release: [docs/COMPATIBILITY.md](docs/COMPATIBILITY.md).
188
+
189
+ How to cut a release (bump the version, rebuild `lib/`, push a tag, let CI publish over OIDC): [RELEASING.md](RELEASING.md).
190
+
191
+ ## License
192
+
193
+ Apache-2.0. Forked from [`aa2246740/dsh-model-fusion`](https://github.com/aa2246740/dsh-model-fusion), also under Apache-2.0.