@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.
- package/INSTALL.md +89 -0
- package/INSTALL.zh.md +86 -0
- package/LICENSE +201 -0
- package/README.en.md +193 -0
- package/README.md +182 -2
- package/RELEASING.md +123 -0
- package/RELEASING.zh.md +115 -0
- package/contracts/fusion.ts +279 -0
- package/contracts/storage.sql +86 -0
- package/cordis.patch.yml +3 -0
- package/docs/COMPATIBILITY.md +162 -0
- package/docs/EVIDENCE.md +141 -0
- package/dshx.yml +39 -0
- package/lib/client.js +1920 -0
- package/lib/client.js.map +1 -0
- package/lib/dsh-fusion.js +12664 -0
- package/lib/types/activity.d.ts +20 -0
- package/lib/types/approval/logical.d.ts +10 -0
- package/lib/types/benchmark/naive.d.ts +37 -0
- package/lib/types/benchmark/native-run.d.ts +68 -0
- package/lib/types/benchmark/output-limits.d.ts +19 -0
- package/lib/types/bilingual.d.ts +2 -0
- package/lib/types/client/ActivityRows.d.ts +8 -0
- package/lib/types/client/FusionCache.d.ts +4 -0
- package/lib/types/client/FusionHint.d.ts +9 -0
- package/lib/types/client/FusionHistory.d.ts +5 -0
- package/lib/types/client/FusionPanelIcon.d.ts +13 -0
- package/lib/types/client/FusionRecovery.d.ts +5 -0
- package/lib/types/client/FusionSettings.d.ts +9 -0
- package/lib/types/client/FusionStatus.d.ts +5 -0
- package/lib/types/client/FusionTool.d.ts +4 -0
- package/lib/types/client/activity-model.d.ts +14 -0
- package/lib/types/client/i18n.d.ts +15 -0
- package/lib/types/client/index.d.ts +22 -0
- package/lib/types/client/settings-events.d.ts +2 -0
- package/lib/types/client/status-polling.d.ts +9 -0
- package/lib/types/context/guard.d.ts +21 -0
- package/lib/types/context/handoff.d.ts +17 -0
- package/lib/types/contracts.d.ts +449 -0
- package/lib/types/digest.d.ts +5 -0
- package/lib/types/dsh-fusion.d.ts +13 -0
- package/lib/types/errors.d.ts +28 -0
- package/lib/types/evidence/gate.d.ts +23 -0
- package/lib/types/evidence/receipts.d.ts +65 -0
- package/lib/types/execution/write-lease.d.ts +42 -0
- package/lib/types/host/bindings.d.ts +30 -0
- package/lib/types/host/cache-defaults.d.ts +48 -0
- package/lib/types/host/cache-policy.d.ts +155 -0
- package/lib/types/host/change-evidence.d.ts +38 -0
- package/lib/types/host/compaction-routing.d.ts +15 -0
- package/lib/types/host/coordinator.d.ts +169 -0
- package/lib/types/host/evidence-page.d.ts +13 -0
- package/lib/types/host/history.d.ts +88 -0
- package/lib/types/host/http.d.ts +4 -0
- package/lib/types/host/model-output.d.ts +13 -0
- package/lib/types/host/native-activity.d.ts +26 -0
- package/lib/types/host/native-approvals.d.ts +29 -0
- package/lib/types/host/native-auxiliary.d.ts +17 -0
- package/lib/types/host/native-budget.d.ts +33 -0
- package/lib/types/host/native-checks.d.ts +104 -0
- package/lib/types/host/native-compaction.d.ts +8 -0
- package/lib/types/host/native-context.d.ts +36 -0
- package/lib/types/host/native-effects.d.ts +75 -0
- package/lib/types/host/native-evidence.d.ts +4 -0
- package/lib/types/host/native-exploration.d.ts +15 -0
- package/lib/types/host/native-keepalive.d.ts +82 -0
- package/lib/types/host/native-model-control.d.ts +99 -0
- package/lib/types/host/native-on-demand-context.d.ts +39 -0
- package/lib/types/host/native-request.d.ts +5 -0
- package/lib/types/host/native-review.d.ts +11 -0
- package/lib/types/host/native-role-sandbox.d.ts +49 -0
- package/lib/types/host/native-scopes.d.ts +49 -0
- package/lib/types/host/native-selection.d.ts +29 -0
- package/lib/types/host/native-task-context.d.ts +39 -0
- package/lib/types/host/native-usage.d.ts +46 -0
- package/lib/types/host/native-worker-brief.d.ts +74 -0
- package/lib/types/host/native-worker-notices.d.ts +15 -0
- package/lib/types/host/native-worker.d.ts +44 -0
- package/lib/types/host/native-workflow.d.ts +41 -0
- package/lib/types/host/route-transport.d.ts +22 -0
- package/lib/types/host/settings.d.ts +39 -0
- package/lib/types/host/shell.d.ts +11 -0
- package/lib/types/host/status.d.ts +7 -0
- package/lib/types/host/subagent-seam.d.ts +10 -0
- package/lib/types/host/tool-table.d.ts +35 -0
- package/lib/types/host/worker-terminal.d.ts +68 -0
- package/lib/types/host/workspace-guard.d.ts +13 -0
- package/lib/types/host/workspace.d.ts +52 -0
- package/lib/types/identity.d.ts +64 -0
- package/lib/types/index.d.ts +34 -0
- package/lib/types/message-source.d.ts +29 -0
- package/lib/types/profile/compactor.d.ts +5 -0
- package/lib/types/profile/keepalive.d.ts +3 -0
- package/lib/types/profile/resolve.d.ts +17 -0
- package/lib/types/prompts.d.ts +8 -0
- package/lib/types/recovery/reconcile.d.ts +28 -0
- package/lib/types/review/dispatch.d.ts +20 -0
- package/lib/types/review/protocol.d.ts +51 -0
- package/lib/types/review/ticket.d.ts +32 -0
- package/lib/types/status.d.ts +88 -0
- package/lib/types/store-migration.d.ts +29 -0
- package/lib/types/task/deletion.d.ts +64 -0
- package/lib/types/task/reducer.d.ts +6 -0
- package/lib/types/task/sqlite-store.d.ts +71 -0
- package/lib/types/task/state.d.ts +51 -0
- package/lib/types/task/status-index.d.ts +28 -0
- package/lib/types/task/store.d.ts +48 -0
- package/lib/types/usage/budget.d.ts +27 -0
- package/lib/types/usage/ledger.d.ts +66 -0
- package/lib/types/usage/normalize.d.ts +50 -0
- package/lib/types/usage/pricing.d.ts +18 -0
- package/package.json +178 -4
- package/profiles/fusion-auto.example.json +45 -0
- package/prompts/compact.md +7 -0
- package/prompts/lead.md +42 -0
- package/prompts/model-lead.md +13 -0
- package/prompts/model-worker.md +5 -0
- package/prompts/worker.md +21 -0
- package/src/activity.ts +23 -0
- package/src/approval/logical.ts +44 -0
- package/src/benchmark/naive.ts +216 -0
- package/src/benchmark/native-run.ts +215 -0
- package/src/benchmark/output-limits.ts +33 -0
- package/src/bilingual.ts +2 -0
- package/src/client/ActivityRows.tsx +59 -0
- package/src/client/FusionCache.tsx +130 -0
- package/src/client/FusionHint.tsx +39 -0
- package/src/client/FusionHistory.tsx +247 -0
- package/src/client/FusionPanelIcon.tsx +39 -0
- package/src/client/FusionRecovery.tsx +69 -0
- package/src/client/FusionSettings.tsx +205 -0
- package/src/client/FusionStatus.tsx +103 -0
- package/src/client/FusionTool.tsx +66 -0
- package/src/client/activity-model.ts +31 -0
- package/src/client/i18n.ts +30 -0
- package/src/client/index.ts +50 -0
- package/src/client/settings-events.ts +3 -0
- package/src/client/status-polling.ts +88 -0
- package/src/context/guard.ts +81 -0
- package/src/context/handoff.ts +28 -0
- package/src/contracts.ts +449 -0
- package/src/digest.ts +28 -0
- package/src/dsh-fusion.ts +321 -0
- package/src/errors.ts +34 -0
- package/src/evidence/gate.ts +290 -0
- package/src/evidence/receipts.ts +175 -0
- package/src/execution/write-lease.ts +187 -0
- package/src/host/bindings.ts +91 -0
- package/src/host/cache-defaults.ts +103 -0
- package/src/host/cache-policy.ts +168 -0
- package/src/host/change-evidence.ts +156 -0
- package/src/host/compaction-routing.ts +46 -0
- package/src/host/coordinator.ts +2160 -0
- package/src/host/evidence-page.ts +25 -0
- package/src/host/history.ts +114 -0
- package/src/host/http.ts +30 -0
- package/src/host/model-output.ts +22 -0
- package/src/host/native-activity.ts +199 -0
- package/src/host/native-approvals.ts +196 -0
- package/src/host/native-auxiliary.ts +19 -0
- package/src/host/native-budget.ts +112 -0
- package/src/host/native-checks.ts +474 -0
- package/src/host/native-compaction.ts +34 -0
- package/src/host/native-context.ts +204 -0
- package/src/host/native-effects.ts +260 -0
- package/src/host/native-evidence.ts +31 -0
- package/src/host/native-exploration.ts +114 -0
- package/src/host/native-keepalive.ts +292 -0
- package/src/host/native-model-control.ts +298 -0
- package/src/host/native-on-demand-context.ts +74 -0
- package/src/host/native-request.ts +12 -0
- package/src/host/native-review.ts +51 -0
- package/src/host/native-role-sandbox.ts +171 -0
- package/src/host/native-scopes.ts +203 -0
- package/src/host/native-selection.ts +110 -0
- package/src/host/native-task-context.ts +264 -0
- package/src/host/native-usage.ts +121 -0
- package/src/host/native-worker-brief.ts +122 -0
- package/src/host/native-worker-notices.ts +72 -0
- package/src/host/native-worker.ts +215 -0
- package/src/host/native-workflow.ts +103 -0
- package/src/host/route-transport.ts +54 -0
- package/src/host/settings.ts +93 -0
- package/src/host/shell.ts +13 -0
- package/src/host/status.ts +112 -0
- package/src/host/subagent-seam.ts +20 -0
- package/src/host/tool-table.ts +56 -0
- package/src/host/worker-terminal.ts +91 -0
- package/src/host/workspace-guard.ts +17 -0
- package/src/host/workspace.ts +184 -0
- package/src/identity.ts +76 -0
- package/src/index.ts +50 -0
- package/src/message-source.ts +31 -0
- package/src/profile/compactor.ts +26 -0
- package/src/profile/keepalive.ts +13 -0
- package/src/profile/resolve.ts +131 -0
- package/src/prompts.ts +32 -0
- package/src/recovery/reconcile.ts +38 -0
- package/src/review/dispatch.ts +48 -0
- package/src/review/protocol.ts +212 -0
- package/src/review/ticket.ts +166 -0
- package/src/status.ts +55 -0
- package/src/store-migration.ts +65 -0
- package/src/task/deletion.ts +105 -0
- package/src/task/reducer.ts +679 -0
- package/src/task/sqlite-store.ts +386 -0
- package/src/task/state.ts +72 -0
- package/src/task/status-index.ts +198 -0
- package/src/task/store.ts +287 -0
- package/src/usage/budget.ts +88 -0
- package/src/usage/ledger.ts +218 -0
- package/src/usage/normalize.ts +308 -0
- package/src/usage/pricing.ts +95 -0
package/README.md
CHANGED
|
@@ -1,3 +1,183 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Fusion · DSH 插件
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[English](README.en.md) · [安装](INSTALL.zh.md) · [Install (English)](INSTALL.md)
|
|
4
|
+
|
|
5
|
+
> **本仓库是 [`aa2246740/dsh-model-fusion`](https://github.com/aa2246740/dsh-model-fusion) 的 fork,包名 `@sqdr2/dsh-fusion`。**
|
|
6
|
+
> 上游的能力、算法和实测数据全部保留;本 fork 专注于三件事:把入口从「设置」搬到左侧边栏、
|
|
7
|
+
> 让 agy 线路([`dsh-agy-worker`](https://github.com/SQDR2/dsh-agy-worker))真的能当 Sidekick、
|
|
8
|
+
> 以及修掉冻结范围与任务记录上几个会卡住流程的问题。改动清单见 [本 fork 做了什么](#本-fork-做了什么)。
|
|
9
|
+
|
|
10
|
+
Fusion 在 DeepSeek Harness(DSH)的模型菜单里是一个普通模型:**Fusion · 自动**。背后是两个你自己选的模型:
|
|
11
|
+
|
|
12
|
+
- **Lead**:一个强的前沿模型。负责理解需求、看代码、写任务说明、审查结果。
|
|
13
|
+
- **Sidekick**:一个便宜得多的模型。负责实际改代码、跑命令、跑测试。
|
|
14
|
+
|
|
15
|
+
目标只有一个:**用前沿模型的效果,付打折的价钱。**
|
|
16
|
+
|
|
17
|
+
思路受 Cognition 在 Devin 里推出的 Fusion 启发,这是一个独立实现,与 Cognition 无关。
|
|
18
|
+
|
|
19
|
+
## 实测效果
|
|
20
|
+
|
|
21
|
+
9 道真实开源项目的题(SWE-rebench,Python),每题跑 2 次,用隐藏测试判定对错。Lead 为 GPT-6 Astra(high),Sidekick 为 GLM-5.3-Flash(high):
|
|
22
|
+
|
|
23
|
+
| | 做对 | 总花费(按 API 价格估算) |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| GPT-6 Astra 单独 | 9/18 | $39.17 |
|
|
26
|
+
| **Fusion:GPT-6 Astra + GLM-5.3-Flash** | **11/18** | **$18.07(便宜 54%)** |
|
|
27
|
+
| Fusion:GPT-6 Astra + Grok 4.6 | 13/18 | $41.27(不省钱) |
|
|
28
|
+
|
|
29
|
+
- 花费是按各家 API 公开价格换算的估算,不是账单。
|
|
30
|
+
- 局限:样本小(9 题 × 2 次)、只测了 Python、公开题目可能出现在模型训练数据里。
|
|
31
|
+
- 详细方法、原始数据和每一轮的结论见 [docs/EVIDENCE.md](docs/EVIDENCE.md)。
|
|
32
|
+
|
|
33
|
+
**对照 Devin 自己的 Fusion:** 两边用同一对模型,Lead 是 GPT-6 Astra(high),Sidekick 是 SWE-2。题目、工作区和隐藏测试完全相同。
|
|
34
|
+
|
|
35
|
+
排除被污染的尝试后,四个组别都干净的题剩 4 道,结果如下:
|
|
36
|
+
|
|
37
|
+
| | 做对 | 花费 |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| **本插件:Astra + SWE-2** | **4/4** | **$2.73** |
|
|
40
|
+
| Devin Fusion:Astra + SWE-2 | 3/4 | $4.81 |
|
|
41
|
+
| Devin,Astra 单独 | 3/4 | $8.13 |
|
|
42
|
+
|
|
43
|
+
- 样本只有 4 道题、每题 1 次,不能据此说谁更强,也不代表与 Devin 同等水平。
|
|
44
|
+
- SWE-2 两边都按 $0 计价,所以花费都是 Lead 的。
|
|
45
|
+
- 本插件的耗时约为 Devin 的 3.4 倍。
|
|
46
|
+
- 排除了哪些尝试、为什么排除,以及方法和原始数据,见 [docs/EVIDENCE.md](docs/EVIDENCE.md#against-devins-own-fusion-round-devin-r1-2026-09-29)。
|
|
47
|
+
|
|
48
|
+
## 怎么用
|
|
49
|
+
|
|
50
|
+
1. 按 [安装说明](INSTALL.zh.md) 装好插件。
|
|
51
|
+
2. 打开左侧边栏的 **Fusion** 入口(默认位于记忆系统下方),选择 Lead 和 Sidekick。可以选 DSH 里任何已登录的模型。
|
|
52
|
+
3. 在模型菜单里选择 **Fusion · 自动**,像平时一样对话。
|
|
53
|
+
|
|
54
|
+
**搭配建议:** 省钱靠的是 Sidekick 比 Lead 便宜得多。选一个强的前沿模型当 Lead,再选一个价格低很多(最好 5 倍以上)的模型当 Sidekick。两者价格越接近,越省不了钱。
|
|
55
|
+
|
|
56
|
+
## 工作方式
|
|
57
|
+
|
|
58
|
+
- **普通对话**:Lead 直接回答,和用普通模型一样。
|
|
59
|
+
- **需要改代码时**:Lead 把任务交给 Sidekick。任务说明里带着用户需求的原话,以及验收命令。
|
|
60
|
+
- **验收**:
|
|
61
|
+
- Sidekick 交回结果后,DSH 在真实环境里运行验收命令。
|
|
62
|
+
- Lead 审查改动,并且必须对用户的每一条硬性要求给出结论和证据,缺一条都不能通过。
|
|
63
|
+
- 原本就失败的测试(例如缺少可选依赖),可以标成"只要求不新增失败"。
|
|
64
|
+
- Sidekick 改写了原有测试时,会被单独标出来,Lead 必须确认过才能通过。
|
|
65
|
+
- **返工**:不通过就把具体问题打回给同一个 Sidekick 继续改。
|
|
66
|
+
- 如果发现任务说明里允许改的文件不够(例如另一个测试文件还写着旧行为),Lead 可以在返工时把它加进可改范围。只能加、不能减,每次都会留下记录。
|
|
67
|
+
- **Lead 不写代码**:这不是靠提示词约束,而是由程序保证的:
|
|
68
|
+
- Lead 没有写文件的工具;
|
|
69
|
+
- 它执行的 shell 命令跑在 DSH 的只读沙盒里。
|
|
70
|
+
- **唯一的例外:程序判定 Sidekick 确实做不完时,才解锁 Lead 接手。** 例如 2 轮返工后检查仍然失败,或者 Sidekick 用完了步数、反复卡住。接手时:
|
|
71
|
+
- Lead 只能改任务允许的文件;
|
|
72
|
+
- 必须通过同样的验收;
|
|
73
|
+
- 任务结束后恢复只读。
|
|
74
|
+
- **额度用完或出错**:Lead、Sidekick 各自处理。可以换模型继续,也可以定时继续;进度保留。
|
|
75
|
+
|
|
76
|
+
## 用 agy 当 Sidekick(dsh-agy-worker)
|
|
77
|
+
|
|
78
|
+
[`dsh-agy-worker`](https://github.com/SQDR2/dsh-agy-worker)(`dsh-agy-link` 的 fork)把 Google Antigravity 的模型接进 DSH,可以当 Sidekick 用。这条路和普通模型线路不一样,**必须三个条件同时成立**,缺任何一条都会静默失败:
|
|
79
|
+
|
|
80
|
+
| 条件 | 为什么 | 缺了会怎样 |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| `mcpBridge: true` | agy 要能真的**执行** DSH 工具 | 工具看得见,但调不动 |
|
|
83
|
+
| `permissionMode: 'skip'` | headless 下 MCP 调用要被自动允许 | agy 直接拒绝:`a tool required the "mcp" permission that headless mode cannot prompt for` |
|
|
84
|
+
| 白名单里有 `fusion_*` | Sidekick 要能**交回结果** | 只能诊断,永远交不回 |
|
|
85
|
+
|
|
86
|
+
工具天花板里的回传通道 `agy_tool` **不需要你手写**:本插件在检测到 `antigravity` 线路已注册时,会自动把它并进 Lead 和 Sidekick 的工具面(`src/host/route-transport.ts`)。这是本 fork 修掉的问题之一——在此之前,agy 的适配器只能以 `agy_tool` 回传,而天花板里没有这个名字,整轮就退化成纯文本,宿主报 `WORKER_TOOLS_UNREACHABLE`。
|
|
87
|
+
|
|
88
|
+
推荐配置:
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
- id: dsh-agy-worker
|
|
92
|
+
config:
|
|
93
|
+
mcpBridge: true
|
|
94
|
+
permissionMode: skip
|
|
95
|
+
mcpConfigScope: global
|
|
96
|
+
mcpToolAllowlist: "fusion_submit_result,fusion_read_state,fusion_read_evidence,bash,read,write,edit,glob,grep,job_output,job_kill"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
> Windows 把 `bash` 换成 `pwsh`;改过 `workerTools` 就跟着改。完整配置面、验证步骤与排障对照见
|
|
100
|
+
> [dsh-agy-worker 的 MCP 桥接文档](https://github.com/SQDR2/dsh-agy-worker/blob/main/docs/MCP-BRIDGE-SETUP.md)。
|
|
101
|
+
|
|
102
|
+
## 本 fork 做了什么
|
|
103
|
+
|
|
104
|
+
相对上游 `dsh-model-fusion`,本 fork 的改动(按提交时间):
|
|
105
|
+
|
|
106
|
+
| 内容 | 解决了什么 |
|
|
107
|
+
|---|---|
|
|
108
|
+
| **用户约束跨压缩保留** | 对话被自动压缩(rollover)后,用户原话里的硬性要求仍在任务范围内,不会因为一次压缩就丢掉验收依据 |
|
|
109
|
+
| **死路任务有出口** | 当 Sidekick 线路根本够不到工具时,判定会被记在运行记录上:`fusion_wait` 复述同一个原因,`fusion_delegate` 允许替换这条死单并复用常驻身份,不再把任务卡在 `WORKER_RUNNING` |
|
|
110
|
+
| **入口搬到左侧边栏** | Fusion 从「设置 → Fusion」变成左侧边栏的独立面板(默认落在记忆系统下方),主区域有真正的滚动面,不再是塞在设置页里的一段表单 |
|
|
111
|
+
| **agy 线路真的能当 Sidekick** | `agy_tool` 回传通道自动并进工具天花板(见上一节) |
|
|
112
|
+
| **桥接线路能交回结果** | agy 在自己的循环里执行调用,用的是 `agy-mcp-N` 这种桥内 id,本 Host 的 assistant 消息里没有它,于是所有非只读 Worker 工具都被判成「缺少完整的原生模型请求」——包括唯一要紧的 `fusion_submit_result`。现在桥接调用归属到发出回传通道的那条消息上,原生路径不变且优先 |
|
|
113
|
+
| **冻结范围不再死锁** | `allowedPaths: ['lib/types/**']` 这类 glob 之前一条都不匹配,导致「改动落在冻结范围外」和「加范围时文件已变更」互相锁死。现在 glob 正常匹配,加范围改为按提交基点比较,并且可以显式清空 |
|
|
114
|
+
| **任务记录可以删了** | 删除只看持久化状态:进程换过的任务永远 `running` 删不掉,而真在跑的 Agent 又可能被从底下抽走。现在删除先问协调者(`liveWork`),409 会说明是哪一个资源占着 |
|
|
115
|
+
| **面板折叠** | 用量统计、任务列表、缓存保活、历史各自成为独立的折叠区块,默认收起,模型组合不再被挤到屏幕外 |
|
|
116
|
+
|
|
117
|
+
## 缓存保活
|
|
118
|
+
|
|
119
|
+
Lead 等 Sidekick 干活时,可能要等好几分钟。模型的输入缓存过期后,下一次请求就要按全价重读整段对话。保活会在等待期间,定时把 Lead 上一次的请求原样再发一遍,末尾只加一句“Reply OK”。前缀和上次完全相同,厂商就从缓存读取,缓存的寿命也就续上了;模型只回一个 OK,回复直接丢弃,不进对话,也不会执行工具调用。
|
|
120
|
+
|
|
121
|
+
- **默认值:** 来自各家官方文档,覆盖 Artificial Analysis 排行榜前 20 的模型厂商。
|
|
122
|
+
- 按模型名匹配,比如 gpt-*、claude-*、gemini-*、glm-*、grok-*、kimi-*、deepseek-*。
|
|
123
|
+
- 附带 [dsh-oauth-login](https://github.com/aa2246740/dsh-oauth-login) 的线路计费方式:按请求次数计费的套餐默认关闭保活,因为每次保活都算一次请求。
|
|
124
|
+
- **自动:** 模型实际返回过缓存命中后才开启,不支持缓存的模型不会白花钱。
|
|
125
|
+
- **每个模型都可以在 Fusion 面板中调整:** 开关、续命间隔、恢复默认。面板还会显示每个模型的实际效果:
|
|
126
|
+
- 等待后缓存还在不在;
|
|
127
|
+
- 发了几次保活、读了多少 token;
|
|
128
|
+
- 避免了多少 token 按全价重发。
|
|
129
|
+
- **实测(ChatGPT 订阅线路,gpt-6-astra,约 2 万 token 上下文):** 每次保活模型只回 5 个 token,不思考、不调工具。缓存空闲 10 分钟仍在,15 分钟后过期,每次保活会重新计时,所以这条线路默认每 8 分钟保活一次。
|
|
130
|
+
- **自动调整:** 当前间隔下最近 5 次保活有 3 次没命中,程序才会自动缩短间隔(偶尔一次随机淘汰不算);只会缩短,不会自动拉长。可以放宽时只给建议,由你决定。
|
|
131
|
+
|
|
132
|
+
## 支持范围
|
|
133
|
+
|
|
134
|
+
- **DSH 版本:** 支持 **0.2.0-rc.2** 和 **0.2.1-rc.2**,桌面版和 Web 版都可以。其他版本不保证可用;新版本发布后会另行适配。
|
|
135
|
+
- **模型:** DSH 官方自带的模型线路,以及 [dsh-oauth-login](https://github.com/aa2246740/dsh-oauth-login)、dsh-antigravity-oauth 提供的订阅登录线路,还有 [dsh-agy-worker](https://github.com/SQDR2/dsh-agy-worker) 的 Antigravity 线路。其他第三方模型插件未经测试。
|
|
136
|
+
- **系统:**
|
|
137
|
+
- **macOS:** 已验证(Seatbelt 沙盒)。
|
|
138
|
+
- **Windows:** `v0.2.1` 已适配原生 `pwsh`,在 Windows Server 2022、PowerShell 7.6.6 上通过验证。启动 DSH 的进程 PATH 中需要有 `pwsh`。Windows 10/11 尚未验证。Windows ACL 仅提供部分隔离,普通路径写入可受限制,读取和网络不在该限制内。
|
|
139
|
+
- **Linux:** 未验证,使用前请先自行检查:
|
|
140
|
+
1. 在一个测试目录里选 Fusion,对它说:"这是一次只读沙盒测试,被拒绝是预期结果。请你自己直接调用 bash 工具执行 `echo test > fusion-probe.txt`(不要委派、不要换别的写法),把工具返回的原文贴给我。"
|
|
141
|
+
2. 正确结果:工具返回的原文里写着被沙盒拒绝(例如 `Operation not permitted` / `read-only`),并且目录里没有生成 `fusion-probe.txt`。
|
|
142
|
+
- 如果 Lead 只是口头拒绝、没有真的调用工具,这次检查不算数,请再说一遍"请实际调用工具"。
|
|
143
|
+
3. 如果文件被创建出来,说明你的系统上 Lead 的只读限制没有生效,请不要使用,并反馈给我们。
|
|
144
|
+
- 如果 DSH 在你的系统上没有沙盒,Lead 的 shell 命令会被全部拒绝(安全的失败方式),它仍然可以用读文件和搜索工具看代码。
|
|
145
|
+
|
|
146
|
+
### v0.2.1 的 Windows 验证
|
|
147
|
+
|
|
148
|
+
在 Windows Server 2022、Node 22.23.3、PowerShell 7.6.6、DSH 0.1.7-rc.2 上,**253 项单元测试和 236 项 Host 测试全部通过**,类型检查通过。修复候选完成了插件安装、冷启动、Fusion 设置页及 settings/cache 两个 API 验证。v0.2.1 的服务端和客户端构建文件与该候选完全一致。之后的版本(v0.2.2 返工时扩大可改文件范围、v0.2.3–v0.2.5 适配 DSH 0.2.0-rc.2、v0.2.6 改进缓存保活)都与平台无关,在 macOS 上复测,未在 Windows 上重跑。
|
|
149
|
+
|
|
150
|
+
真实 PowerShell ACL 测试中,Lead 执行 `Set-Content probe.txt test` 被拒绝,文件未生成;Sidekick 在获准的工作区内执行同一命令可以写入。这是上面所述的部分 ACL 隔离。验证没有输入模型密钥或发起真实模型请求。macOS 回归通过 253 项单元测试和 235 项 Host 测试,按设计跳过 Windows 专用 ACL 测试。
|
|
151
|
+
|
|
152
|
+
## 数据存在哪里
|
|
153
|
+
|
|
154
|
+
- **Fusion 自己的记录:** 任务说明、检查结果、用量、缓存统计和设置,都存在 `$DSH_HOME/plugins/dsh-fusion/state.sqlite`。`DSH_HOME` 默认是 `~/.dsh`。
|
|
155
|
+
- **从旧名字升级:** 上一版叫 `dsh-model-fusion`,它的整个数据目录(`$DSH_HOME/plugins/dsh-model-fusion/`)会在首次启动时**整体迁移**到新名字,已有的任务、用量和设置都还在。跨文件系统时会退化成复制数据库和它的 `-wal`/`-shm`/`-journal`,只删除自己复制过的文件。
|
|
156
|
+
- **会话本身:** 由 DSH 保存,Fusion 不另外上传任何数据。
|
|
157
|
+
- **想清空 Fusion 的记录:** 退出 DSH 后删除这个文件。设置也会一起清掉,下次打开时重新选组合即可。
|
|
158
|
+
|
|
159
|
+
## 已知限制
|
|
160
|
+
|
|
161
|
+
- **比单独用前沿模型慢:** 实测 GPT-6 + Flash 总耗时约为 GPT-6 单独的 5 倍,主要花在 Sidekick 身上。换更快的 Sidekick 会好很多。
|
|
162
|
+
- **Lead 接手:** 在 72 次实测里一次都没触发,目前只由自动化测试覆盖。
|
|
163
|
+
- **macOS 桌面版的 PATH:** 从程序坞打开的 DSH Studio 只有系统默认的 PATH,Homebrew(`/opt/homebrew/bin`)、nvm 等装的 `node`、`npm`、`cargo` 在 shell 里找不到。这是 DSH 的运行环境,所有模型都一样。Fusion 在派活前会检查验收命令用到的程序,找不到时会告诉 Lead 它实际装在哪里(例如 `/opt/homebrew/bin/node`),Lead 改用完整路径即可。
|
|
164
|
+
- **Windows 10/11 和 Linux 未验证:** 见上面的"系统"。
|
|
165
|
+
|
|
166
|
+
## 开发
|
|
167
|
+
|
|
168
|
+
```sh
|
|
169
|
+
corepack pnpm@9.15.9 install --frozen-lockfile
|
|
170
|
+
node scripts/link-host.mjs /path/to/deepseek-harness-0.2.0-rc.2 # 或 0.2.1-rc.2;开发时链接 DSH 源码
|
|
171
|
+
DSHX_HARNESS=/path/to/deepseek-harness-0.2.0-rc.2 pnpm build
|
|
172
|
+
pnpm test && DSHX_HARNESS=/path/to/deepseek-harness-0.2.0-rc.2 pnpm test:host
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Windows 开发环境需将 PowerShell 7(`pwsh`)、Node 和 Python 加入运行测试的进程 PATH。原生测试通过 `DSHX_HARNESS` 读取已构建的指定 Host;不需要修改 Host 源码。
|
|
176
|
+
|
|
177
|
+
插件只使用 DSH 公开的插件接口,不修改 DSH 源码。适配新版本 DSH 的做法见 [docs/COMPATIBILITY.md](docs/COMPATIBILITY.md)。
|
|
178
|
+
|
|
179
|
+
发版流程(改版本号、重建 `lib/`、打 tag、CI 经 OIDC 发到 npm)见 [RELEASING.zh.md](RELEASING.zh.md)。
|
|
180
|
+
|
|
181
|
+
## 许可
|
|
182
|
+
|
|
183
|
+
Apache-2.0。上游 fork 自 [`aa2246740/dsh-model-fusion`](https://github.com/aa2246740/dsh-model-fusion),同样以 Apache-2.0 发布。
|
package/RELEASING.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Releasing
|
|
2
|
+
|
|
3
|
+
[中文](RELEASING.zh.md) · [Install](INSTALL.md) · [README](README.en.md)
|
|
4
|
+
|
|
5
|
+
Maintainer notes. Users do not need this page.
|
|
6
|
+
|
|
7
|
+
`@sqdr2/dsh-fusion` publishes to npm from GitHub Actions over OIDC, so no long-lived token exists anywhere. This page
|
|
8
|
+
covers the one-time setup that makes that work, and the loop for each release afterwards.
|
|
9
|
+
|
|
10
|
+
## What triggers a publish
|
|
11
|
+
|
|
12
|
+
Only two events:
|
|
13
|
+
|
|
14
|
+
| Event | Result |
|
|
15
|
+
|---|---|
|
|
16
|
+
| Push a tag matching `v*` | build, test, publish |
|
|
17
|
+
| `workflow_dispatch` | same; `dry_run=true` stops before publishing |
|
|
18
|
+
|
|
19
|
+
**Pushing to `main` never publishes.** A merge, a docs fix or a version bump sitting on `main` has no effect on npm
|
|
20
|
+
until a tag exists.
|
|
21
|
+
|
|
22
|
+
The workflow skips a version that is already on npm, so re-running a tag is safe: it rebuilds and retests, then exits
|
|
23
|
+
without touching the registry.
|
|
24
|
+
|
|
25
|
+
## One-time setup
|
|
26
|
+
|
|
27
|
+
Both steps are already done for this repository. They are recorded here because a fork that renames the package has to
|
|
28
|
+
repeat them, and because a misconfigured trusted publisher fails in a way that looks like a broken workflow.
|
|
29
|
+
|
|
30
|
+
### 1. Enable Actions
|
|
31
|
+
|
|
32
|
+
This repository is a fork, and GitHub disables Actions on forks by default. Without this step a tag push is silently
|
|
33
|
+
ignored: no run is created, no failure appears, and the Actions tab reports `0 workflow runs`.
|
|
34
|
+
|
|
35
|
+
Open the **Actions** tab and accept the "I understand my workflows, go ahead and enable them" prompt.
|
|
36
|
+
|
|
37
|
+
### 2. Add a trusted publisher on npm
|
|
38
|
+
|
|
39
|
+
OIDC publishing is authorised per package, on the package's own settings page, which a name that has never been
|
|
40
|
+
published does not have. So the very first release of a name can only be done by hand:
|
|
41
|
+
|
|
42
|
+
1. Publish once with a granular token that bypasses 2FA (`bypass_2fa: true`, `package: write` on the right scope).
|
|
43
|
+
A token without 2FA bypass is rejected with `E403 Two-factor authentication ... is required to publish packages`,
|
|
44
|
+
and a token scoped to `@sqdr2` cannot publish an unscoped name at all.
|
|
45
|
+
2. On **npmjs.com → the package → Settings → Trusted publishing**, add:
|
|
46
|
+
|
|
47
|
+
| Field | Value |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| Provider | GitHub Actions |
|
|
50
|
+
| Repository | `SQDR2/dsh-fusion` |
|
|
51
|
+
| Workflow | `publish.yml` |
|
|
52
|
+
| Permission | allow npm publish |
|
|
53
|
+
|
|
54
|
+
The account needs 2FA of its own first. The package page only says "2FA has been enabled for this package. It is
|
|
55
|
+
recommended that you configure 2FA for your npm account", and submitting the form bounces to
|
|
56
|
+
`/settings/<user>/tfa` asking for a security key or authenticator. Configure account-level 2FA before starting, or
|
|
57
|
+
the form silently turns into a 2FA enrolment page and nothing is created.
|
|
58
|
+
|
|
59
|
+
3. Publish a version within **2 days**. A new trust configuration is only validated by a first successful publish;
|
|
60
|
+
unvalidated ones expire and cannot be edited afterwards, only deleted and recreated.
|
|
61
|
+
|
|
62
|
+
Once the trusted publisher is validated, recommend **Settings → Publishing access → Require two-factor authentication
|
|
63
|
+
and disallow tokens** on the package. Tokens stop being usable for publishing; only the workflow can publish.
|
|
64
|
+
|
|
65
|
+
The npm CLI cannot create a trusted publisher: `npm trust github` needs an interactive 2FA credential, and the API
|
|
66
|
+
rejects a 2FA-bypass token with `Granular access tokens that bypass two-factor authentication may not perform this
|
|
67
|
+
action`. This step is browser-only by design.
|
|
68
|
+
|
|
69
|
+
## Cutting a release
|
|
70
|
+
|
|
71
|
+
`package.json` is the single source of truth for the version. The tag must match it exactly or the workflow stops at its
|
|
72
|
+
first step.
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
# 1. Bump the version in package.json (and nowhere else).
|
|
76
|
+
# 2. Rebuild lib/ — it is tracked in git and shipped in the tarball, so a stale
|
|
77
|
+
# lib/ publishes code that does not match the tagged source.
|
|
78
|
+
DSHX_HARNESS=/path/to/deepseek-harness-0.2.0-rc.2 pnpm build
|
|
79
|
+
pnpm typecheck && pnpm test
|
|
80
|
+
# 3. Commit the source and the rebuilt lib/ together.
|
|
81
|
+
git add -A && git commit -m "chore(release): 0.3.1"
|
|
82
|
+
# 4. Tag and push both.
|
|
83
|
+
git tag v0.3.1 && git push origin main v0.3.1
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The workflow then runs `pnpm install`, `pnpm build`, `pnpm test` and, on a tag, `npm publish --access public`.
|
|
87
|
+
A published version also gets a provenance attestation, so `npm view` can point at the commit it was built from.
|
|
88
|
+
|
|
89
|
+
### Two things the build is pinned to
|
|
90
|
+
|
|
91
|
+
`scripts/build.mjs` accepts only the Host versions in `engines.dsh` (`0.2.0-rc.2` and `0.2.1-rc.2`) and fails
|
|
92
|
+
otherwise. CI checks out `dsh-v0.2.0-rc.2` for that reason.
|
|
93
|
+
|
|
94
|
+
The bundler version in the workflow is pinned to exactly `tsdown@0.22.2`. `lib/` is committed, so a different bundler
|
|
95
|
+
would commit a bundle that does not match what was tested; `0.22.14`, for instance, reformats several hundred lines.
|
|
96
|
+
|
|
97
|
+
## Checking a release
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
npm view @sqdr2/dsh-fusion version dist-tags
|
|
101
|
+
npm view @sqdr2/dsh-fusion@0.3.0 dist.attestations # present means it came from CI
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
To check the artefact rather than the metadata:
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
npm install @sqdr2/dsh-fusion@0.3.0
|
|
108
|
+
node -e "import('@sqdr2/dsh-fusion').then(m => console.log(m.name, m.inject.length))"
|
|
109
|
+
grep -o 'id: \"[^\"]*\"' node_modules/@sqdr2/dsh-fusion/lib/client.js | head -1
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The host bundle must export `dsh-fusion`, and the client bundle's registration id must be the package name
|
|
113
|
+
`@sqdr2/dsh-fusion`. They differ on purpose: see [INSTALL.md](INSTALL.md) for why, and `src/identity.ts` for how.
|
|
114
|
+
|
|
115
|
+
## If a publish fails
|
|
116
|
+
|
|
117
|
+
| Symptom | Cause |
|
|
118
|
+
| --- | --- |
|
|
119
|
+
| Tag pushed, `0 workflow runs` | Actions not enabled on the fork |
|
|
120
|
+
| `404` or `ENEEDAUTH` from `npm publish` | No trusted publisher on npm, or it expired unvalidated |
|
|
121
|
+
| `tag vX != package.json Y` | Version bumped in one place only |
|
|
122
|
+
| `Unsupported Host package version` | `HARNESS_REF` drifted from `engines.dsh` |
|
|
123
|
+
| Bundle rebuild differs from committed `lib/` | Bundler version not pinned to `0.22.2` |
|
package/RELEASING.zh.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# 发版
|
|
2
|
+
|
|
3
|
+
[English](RELEASING.md) · [安装](INSTALL.zh.md) · [README](README.md)
|
|
4
|
+
|
|
5
|
+
维护者用。普通用户不需要看这一页。
|
|
6
|
+
|
|
7
|
+
`@sqdr2/dsh-fusion` 由 GitHub Actions 通过 OIDC 发到 npm,任何地方都不存在长期 token。本页说明让它跑起来的一次性配置,以及之后每一版的流程。
|
|
8
|
+
|
|
9
|
+
## 什么会触发发布
|
|
10
|
+
|
|
11
|
+
只有两种事件:
|
|
12
|
+
|
|
13
|
+
| 事件 | 结果 |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| 推送匹配 `v*` 的 tag | 构建、测试、发布 |
|
|
16
|
+
| `workflow_dispatch` | 同上;`dry_run=true` 在发布前停下 |
|
|
17
|
+
|
|
18
|
+
**往 `main` 推永远不会发布。** 合一个 PR、改一处文档、或者把版本号改好放在 `main` 上,在有 tag 之前都不会影响 npm。
|
|
19
|
+
|
|
20
|
+
workflow 会跳过 npm 上已存在的版本,所以同一个 tag 重跑是安全的:重新构建、重新测试,然后不碰 registry 直接退出。
|
|
21
|
+
|
|
22
|
+
## 一次性配置
|
|
23
|
+
|
|
24
|
+
两步本仓库都已完成。之所以记在这里,是因为 fork 后改名要重做一遍,而且信任配置配错时的失败现象很像「workflow 坏了」。
|
|
25
|
+
|
|
26
|
+
### 1. 启用 Actions
|
|
27
|
+
|
|
28
|
+
本仓库是 fork,GitHub 默认禁用 fork 的 Actions。这一步不做,推 tag 会被静默忽略:不建运行、不报错,Actions 页面显示 `0 workflow runs`。
|
|
29
|
+
|
|
30
|
+
打开 **Actions** 标签页,接受 “I understand my workflows, go ahead and enable them” 提示。
|
|
31
|
+
|
|
32
|
+
### 2. 在 npm 上加信任配置
|
|
33
|
+
|
|
34
|
+
OIDC 发布是按包授权的,配置在包自己的设置页上,而一个从未发布过的包名没有这个页面。所以某个包名的第一版只能手发:
|
|
35
|
+
|
|
36
|
+
1. 用一个勾了 2FA bypass 的 granular token 手动发一次(`bypass_2fa: true`,`package: write`,作用域要对)。
|
|
37
|
+
不勾 bypass 会被拒:`E403 Two-factor authentication ... is required to publish packages`;
|
|
38
|
+
而作用域是 `@sqdr2` 的 token 根本无法发布无 scope 的包名。
|
|
39
|
+
2. 在 **npmjs.com → 该包 → Settings → Trusted publishing** 添加:
|
|
40
|
+
|
|
41
|
+
| 字段 | 值 |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| Provider | GitHub Actions |
|
|
44
|
+
| Repository | `SQDR2/dsh-fusion` |
|
|
45
|
+
| Workflow | `publish.yml` |
|
|
46
|
+
| Permission | allow npm publish |
|
|
47
|
+
|
|
48
|
+
**账号自己得先有 2FA。** 包页面上只会写一句 “2FA has been enabled for this package. It is recommended that you
|
|
49
|
+
configure 2FA for your npm account”,而提交表单会跳到 `/settings/<user>/tfa` 要求录入安全密钥或认证器。
|
|
50
|
+
动手之前先把账号级 2FA 配好,否则表单会静默变成 2FA 注册页,什么都不会创建。
|
|
51
|
+
|
|
52
|
+
3. 在 **2 天内**发一个版本。新的信任配置只有首次成功发布才算验证通过;未验证的会过期,
|
|
53
|
+
之后不能编辑,只能删掉重建。
|
|
54
|
+
|
|
55
|
+
信任配置验证通过后,建议在包上开 **Settings → Publishing access → Require two-factor authentication and disallow tokens**。
|
|
56
|
+
此后 token 不能再发布,只有 workflow 能发。
|
|
57
|
+
|
|
58
|
+
npm CLI 建不了信任配置:`npm trust github` 需要交互式 2FA 凭据,而 API 会拒绝 bypass 2FA 的 token,
|
|
59
|
+
返回 `Granular access tokens that bypass two-factor authentication may not perform this action`。
|
|
60
|
+
这一步在设计上只能走浏览器。
|
|
61
|
+
|
|
62
|
+
## 发一版
|
|
63
|
+
|
|
64
|
+
版本号的唯一真源是 `package.json`。tag 必须与它完全一致,否则 workflow 会在第一步退出。
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
# 1. 改 package.json 里的版本号(别处不要改)。
|
|
68
|
+
# 2. 重建 lib/ —— 它纳入版本库并随包发布,lib/ 陈旧等于发布了
|
|
69
|
+
# 与 tag 源码不一致的代码。
|
|
70
|
+
DSHX_HARNESS=/path/to/deepseek-harness-0.2.0-rc.2 pnpm build
|
|
71
|
+
pnpm typecheck && pnpm test
|
|
72
|
+
# 3. 源码和重建后的 lib/ 一起提交。
|
|
73
|
+
git add -A && git commit -m "chore(release): 0.3.1"
|
|
74
|
+
# 4. 打 tag 并一起推。
|
|
75
|
+
git tag v0.3.1 && git push origin main v0.3.1
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
workflow 随后依次执行 `pnpm install`、`pnpm build`、`pnpm test`,在 tag 上再执行 `npm publish --access public`。
|
|
79
|
+
发布出来的版本还带 provenance 证明,可以用 `npm view` 追溯它是从哪个 commit 构建的。
|
|
80
|
+
|
|
81
|
+
### 构建被钉死的两处
|
|
82
|
+
|
|
83
|
+
`scripts/build.mjs` 只接受 `engines.dsh` 里列出的 Host 版本(`0.2.0-rc.2` 和 `0.2.1-rc.2`),其余直接报错。
|
|
84
|
+
CI 因此 checkout `dsh-v0.2.0-rc.2`。
|
|
85
|
+
|
|
86
|
+
workflow 里的打包器版本精确钉在 `tsdown@0.22.2`。`lib/` 是提交进仓库的,换个打包器就会提交一份与测试结果不一致的产物;
|
|
87
|
+
比如 `0.22.14` 会重写几百行格式。
|
|
88
|
+
|
|
89
|
+
## 检查一次发布
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
npm view @sqdr2/dsh-fusion version dist-tags
|
|
93
|
+
npm view @sqdr2/dsh-fusion@0.3.0 dist.attestations # 有值说明出自 CI
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
想验证产物本身而不是元数据:
|
|
97
|
+
|
|
98
|
+
```sh
|
|
99
|
+
npm install @sqdr2/dsh-fusion@0.3.0
|
|
100
|
+
node -e "import('@sqdr2/dsh-fusion').then(m => console.log(m.name, m.inject.length))"
|
|
101
|
+
grep -o 'id: "[^"]*"' node_modules/@sqdr2/dsh-fusion/lib/client.js | head -1
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
宿主 bundle 必须导出 `dsh-fusion`,客户端 bundle 的注册 id 必须是包名 `@sqdr2/dsh-fusion`。
|
|
105
|
+
两者不同是刻意的:原因见 [INSTALL.zh.md](INSTALL.zh.md),实现见 `src/identity.ts`。
|
|
106
|
+
|
|
107
|
+
## 发布失败时
|
|
108
|
+
|
|
109
|
+
| 现象 | 原因 |
|
|
110
|
+
| --- | --- |
|
|
111
|
+
| 推了 tag,`0 workflow runs` | fork 上没有启用 Actions |
|
|
112
|
+
| `npm publish` 报 `404` 或 `ENEEDAUTH` | npm 上没有信任配置,或它过期未验证 |
|
|
113
|
+
| `tag vX != package.json Y` | 版本号只改了一处 |
|
|
114
|
+
| `Unsupported Host package version` | `HARNESS_REF` 与 `engines.dsh` 不一致 |
|
|
115
|
+
| 重建后的 bundle 与已提交的 `lib/` 不同 | 打包器没钉在 `0.22.2` |
|