@ljwei-stak/dsh-model-router 0.16.0 → 0.16.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/.dsh-plugin/client.js +314 -80
- package/.dsh-plugin/index.mjs +23 -17
- package/.dsh-plugin/shared/adaptive-feedback.mjs +120 -40
- package/.dsh-plugin/shared/dynamic-data-view.mjs +59 -4
- package/.dsh-plugin/shared/dynamic-data.mjs +161 -83
- package/.dsh-plugin/shared/latest-versions.mjs +3 -21
- package/.dsh-plugin/shared/official-tools-runtime.mjs +188 -41
- package/.dsh-plugin/shared/router-state.mjs +139 -38
- package/.dsh-plugin/shared/run-ledger.mjs +32 -11
- package/.dsh-plugin/shared/version-order.mjs +30 -0
- package/CHANGELOG.md +20 -0
- package/INSTALLATION_GUIDE.zh.md +12 -12
- package/README.md +9 -5
- package/README.zh.md +9 -5
- package/docs/ROUTING_ADAPTIVE_LEARNING.zh.md +2 -0
- package/docs/ROUTING_MATURITY.zh.md +76 -0
- package/package.json +3 -1
|
@@ -14,21 +14,42 @@ const routeKey = (provider, model) => `${String(provider ?? '')}\u0000${String(m
|
|
|
14
14
|
|
|
15
15
|
/** USD cost of one package. Prefers a CLI-reported cost, else usage × configured price. */
|
|
16
16
|
export function actualCost(result, pricing) {
|
|
17
|
-
if (finite(result
|
|
17
|
+
if (result && Object.hasOwn(result, 'reportedCostUsd') && finite(result.reportedCostUsd) && result.reportedCostUsd >= 0) {
|
|
18
18
|
return { costUsd: result.reportedCostUsd, costSource: 'cli-reported' }
|
|
19
19
|
}
|
|
20
|
-
const usage = result
|
|
21
|
-
if (!usage || !pricing || !
|
|
20
|
+
const usage = result && Object.hasOwn(result, 'usage') ? result.usage : null
|
|
21
|
+
if (!usage || !pricing || !Object.hasOwn(pricing, 'input') || !Object.hasOwn(pricing, 'output')
|
|
22
|
+
|| pricing.input === undefined || pricing.input === null || pricing.output === undefined || pricing.output === null) {
|
|
22
23
|
return { costUsd: null, costSource: usage ? 'price-missing' : 'usage-missing' }
|
|
23
24
|
}
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
const nonnegative = value => finite(value) && value >= 0
|
|
26
|
+
if (typeof pricing !== 'object' || Array.isArray(pricing)
|
|
27
|
+
|| !nonnegative(pricing.input) || !nonnegative(pricing.output)
|
|
28
|
+
|| ['cacheRead', 'cacheWrite'].some(key => Object.hasOwn(pricing, key) && pricing[key] !== undefined && !nonnegative(pricing[key]))) {
|
|
29
|
+
return { costUsd: null, costSource: 'price-invalid' }
|
|
30
|
+
}
|
|
31
|
+
if (typeof usage !== 'object' || Array.isArray(usage)) return { costUsd: null, costSource: 'usage-invalid' }
|
|
32
|
+
if (!Object.hasOwn(usage, 'inputTokens') || !Object.hasOwn(usage, 'outputTokens')
|
|
33
|
+
|| usage.inputTokens === undefined || usage.inputTokens === null || usage.outputTokens === undefined || usage.outputTokens === null) {
|
|
34
|
+
return { costUsd: null, costSource: 'usage-missing' }
|
|
35
|
+
}
|
|
36
|
+
if (['inputTokens', 'outputTokens'].some(key => !nonnegative(usage[key]))
|
|
37
|
+
|| ['cacheReadTokens', 'cacheWriteTokens'].some(key => Object.hasOwn(usage, key) && usage[key] !== undefined && !nonnegative(usage[key]))) {
|
|
38
|
+
return { costUsd: null, costSource: 'usage-invalid' }
|
|
39
|
+
}
|
|
40
|
+
const input = usage.inputTokens
|
|
41
|
+
const output = usage.outputTokens
|
|
42
|
+
const cacheRead = Object.hasOwn(usage, 'cacheReadTokens') ? usage.cacheReadTokens ?? 0 : 0
|
|
43
|
+
const cacheWrite = Object.hasOwn(usage, 'cacheWriteTokens') ? usage.cacheWriteTokens ?? 0 : 0
|
|
44
|
+
const cacheReadPrice = Object.hasOwn(pricing, 'cacheRead') ? pricing.cacheRead ?? pricing.input : pricing.input
|
|
45
|
+
const cacheWritePrice = Object.hasOwn(pricing, 'cacheWrite') ? pricing.cacheWrite ?? pricing.input : pricing.input
|
|
46
|
+
// Divide each usage counter before multiplication to avoid intermediate
|
|
47
|
+
// overflow for a finite USD result; an actually unrepresentable cost is unknown.
|
|
48
|
+
const costUsd = input / 1_000_000 * pricing.input
|
|
49
|
+
+ cacheRead / 1_000_000 * cacheReadPrice
|
|
50
|
+
+ cacheWrite / 1_000_000 * cacheWritePrice
|
|
51
|
+
+ output / 1_000_000 * pricing.output
|
|
52
|
+
if (!nonnegative(costUsd)) return { costUsd: null, costSource: 'cost-invalid' }
|
|
32
53
|
return { costUsd, costSource: 'usage' }
|
|
33
54
|
}
|
|
34
55
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure x.y.z[-pre] ordering shared by the Host and the Desktop client.
|
|
3
|
+
* No Node APIs: the client bundle imports this file.
|
|
4
|
+
*/
|
|
5
|
+
const VERSION = /^(\d{1,6})\.(\d{1,6})\.(\d{1,6})(?:-[0-9A-Za-z.-]{1,64})?$/
|
|
6
|
+
|
|
7
|
+
export function isReleaseVersion(value) {
|
|
8
|
+
return typeof value === 'string' && VERSION.test(value)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Numeric comparison of x.y.z[-pre]; a prerelease sorts below its release. */
|
|
12
|
+
export function compareReleaseVersions(left, right) {
|
|
13
|
+
const parse = value => {
|
|
14
|
+
const match = VERSION.exec(String(value ?? ''))
|
|
15
|
+
return match ? { parts: match.slice(1, 4).map(Number), pre: String(value).includes('-') } : null
|
|
16
|
+
}
|
|
17
|
+
const a = parse(left)
|
|
18
|
+
const b = parse(right)
|
|
19
|
+
if (!a || !b) return null
|
|
20
|
+
for (let index = 0; index < 3; index += 1) {
|
|
21
|
+
if (a.parts[index] !== b.parts[index]) return a.parts[index] > b.parts[index] ? 1 : -1
|
|
22
|
+
}
|
|
23
|
+
if (a.pre !== b.pre) return a.pre ? -1 : 1
|
|
24
|
+
return 0
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** True when both versions parse and the installed copy is strictly older. */
|
|
28
|
+
export function versionStillOlder(installedVersion, latestVersion) {
|
|
29
|
+
return compareReleaseVersions(installedVersion, latestVersion) === -1
|
|
30
|
+
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.16.2 — 2026-10-09
|
|
4
|
+
|
|
5
|
+
Stable patch under the npm `latest` tag. Fully quit Harness, including the tray process, and restart after upgrading. Existing 0.16.1 artifacts remain unchanged.
|
|
6
|
+
|
|
7
|
+
- Official-tools update/install clicks keep the job started by that click. A status poll no longer replaces it with an older finished job or clears a failure.
|
|
8
|
+
- Refreshing an existing probe no longer disables the update button. A click that cannot start, and an install whose probed version is still older than latest, show an error on that row.
|
|
9
|
+
- Installed Claude Code runs `claude update` before the registry npm install. Installed Windows MiniMax runs the official installer. Other registry cards share the same click path and fail visibly when the probed version does not advance.
|
|
10
|
+
- Release validation: 628 tests passed, 4 conditional skips, client check passed. No paid calls or real CLI installs were part of this verification.
|
|
11
|
+
|
|
12
|
+
## 0.16.1 — 2026-10-08
|
|
13
|
+
|
|
14
|
+
Stable maturity patch under the npm `latest` tag. Fully quit Harness, including the tray process, and restart after upgrading. Existing 0.16.0 artifacts remain unchanged.
|
|
15
|
+
|
|
16
|
+
- Separate stable feedback evidence identity from hourly decay invalidation; expose bounded per-route/domain observed feedback diagnostics and exclusion reasons without changing objective quality floors.
|
|
17
|
+
- Remove superseded personalization, reject invalid/missing usage costs instead of treating them as free, and retain immutable historical charges.
|
|
18
|
+
- Recover interrupted public refresh leases, propagate overall timeout/cancellation, isolate source changes, sanitize public status, and reproject in-flight responses against current settings.
|
|
19
|
+
- Guard settings/rating submissions, preserve newer drafts, await summary refresh, fix paused-result Hook order, and surface retained-but-unverified summaries.
|
|
20
|
+
- Never steal live state locks; detach committed state, roll back rejected updates, preserve unsupported schemas and unique corrupt backups, and prevent incomplete charge history from passing configured budgets.
|
|
21
|
+
- Package the maturity derivations, regression reproduction and remaining limits in `docs/ROUTING_MATURITY.zh.md`. Release validation: 622 tests passed, 3 conditional skips, client/preview checks passed. No paid calls, real-user ledger changes or real quality-cost benefit claim.
|
|
22
|
+
|
|
3
23
|
## 0.16.0 — 2026-10-05
|
|
4
24
|
|
|
5
25
|
Stable release under the npm `latest` tag. Fully quit Harness, including the tray process, and restart after upgrading so both the Host and client load the new version. Public data refresh is opt-in; enabling it does not authorize paid model exploration.
|
package/INSTALLATION_GUIDE.zh.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
模型路由从 **0.12.0** 起独立发布;GAL 是新的 **0.1.0** 插件。两者均声明支持官方 **DeepSeek Harness Desktop 0.2.0-rc.1 / 0.2.0-rc.2**,可分别安装和更新。
|
|
4
4
|
|
|
5
|
-
当前路由正式版为 **0.16.0
|
|
5
|
+
当前路由正式版为 **0.16.2**。本版修复官方工具更新/安装按钮:点击会真正启动更新,失败时在该行显示原因,而不是没有任何反应。0.16.1 的反馈缓存、刷新与预算保护仍然保留。公开数据默认关闭;主观偏好调整不改变公共能力评分或质量门槛。源码开发可使用独立模拟 UI 预览;安装时选择下方精确版本。
|
|
6
6
|
|
|
7
7
|
[路由 README](README.zh.md) · [迁移说明](MIGRATION.md) · [独立 GAL README](https://github.com/Alice-Marx/deepseek-harness-galgame#readme)
|
|
8
8
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
| 需求 | 添加插件输入框 | 安装后的入口 |
|
|
12
12
|
| --- | --- | --- |
|
|
13
|
-
| 分析复杂度、按质量和费用选模型、调用官方工具 | `@ljwei-stak/dsh-model-router@0.16.
|
|
13
|
+
| 分析复杂度、按质量和费用选模型、调用官方工具 | `@ljwei-stak/dsh-model-router@0.16.2` | 模型路由 |
|
|
14
14
|
| 剧情、立绘、音乐、存档、自由对话 | `@ljwei-stak/dsh-galgame@0.1.0` | Gal 模块 |
|
|
15
15
|
| 两者都要 | 分别安装上面两个包 | 模型路由 + Gal 模块 |
|
|
16
16
|
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
2. 在“包名、GitHub 仓库地址或本地目录路径”输入框填一个完整包名,例如:
|
|
25
25
|
|
|
26
26
|
```text
|
|
27
|
-
@ljwei-stak/dsh-model-router@0.16.
|
|
27
|
+
@ljwei-stak/dsh-model-router@0.16.2
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
只想安装 GAL 时填写:
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
4. 核对预览的包名、版本和宿主兼容信息,安装并启用。完全退出 Harness(包括托盘进程)再启动,确保 Host 加载新代码。
|
|
43
|
-
5. 检查插件详情与侧边栏:路由应为 **0.16.
|
|
43
|
+
5. 检查插件详情与侧边栏:路由应为 **0.16.2 / 模型路由**;GAL 应为 **0.1.0 / Gal 模块**。仅装路由时没有 GAL 入口是预期行为。
|
|
44
44
|
|
|
45
45
|
普通用户无需 `npm install -g`,该命令不会把插件注册到当前 Harness profile。
|
|
46
46
|
|
|
@@ -48,13 +48,13 @@
|
|
|
48
48
|
|
|
49
49
|
进入对应 Release 下载 `.tgz`:
|
|
50
50
|
|
|
51
|
-
- [模型路由 Releases](https://github.com/Alice-Marx/dsh-model-router/releases)(也可运行 `npm pack @ljwei-stak/dsh-model-router@0.16.
|
|
51
|
+
- [模型路由 Releases](https://github.com/Alice-Marx/dsh-model-router/releases)(也可运行 `npm pack @ljwei-stak/dsh-model-router@0.16.2` 获取同一安装包)
|
|
52
52
|
- [独立 GAL v0.1.0](https://github.com/Alice-Marx/deepseek-harness-galgame/releases/tag/v0.1.0)
|
|
53
53
|
|
|
54
54
|
在“添加插件”填写下载文件的**绝对路径**,例如:
|
|
55
55
|
|
|
56
56
|
```text
|
|
57
|
-
D:\Plugins\ljwei-stak-dsh-model-router-0.16.
|
|
57
|
+
D:\Plugins\ljwei-stak-dsh-model-router-0.16.2.tgz
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
```text
|
|
@@ -64,7 +64,7 @@ D:\Plugins\ljwei-stak-dsh-galgame-0.1.0.tgz
|
|
|
64
64
|
如附有 `.sha256` 文件,用 PowerShell 计算并比较摘要:
|
|
65
65
|
|
|
66
66
|
```powershell
|
|
67
|
-
Get-FileHash -Algorithm SHA256 -LiteralPath 'D:\Plugins\ljwei-stak-dsh-model-router-0.16.
|
|
67
|
+
Get-FileHash -Algorithm SHA256 -LiteralPath 'D:\Plugins\ljwei-stak-dsh-model-router-0.16.2.tgz'
|
|
68
68
|
Get-FileHash -Algorithm SHA256 -LiteralPath 'D:\Plugins\ljwei-stak-dsh-galgame-0.1.0.tgz'
|
|
69
69
|
```
|
|
70
70
|
|
|
@@ -74,7 +74,7 @@ Get-FileHash -Algorithm SHA256 -LiteralPath 'D:\Plugins\ljwei-stak-dsh-galgame-0
|
|
|
74
74
|
|
|
75
75
|
1. 在旧合并插件的 GAL 播放器导出需要保留的剧情进度,并备份整个 Harness profile。每份 JSON 仅保存**当前剧情状态**,不含所有手动槽、设置、已读记录或本地音乐;重要槽位可依次读档再导出。
|
|
76
76
|
2. 在**同一个 profile**安装独立 `@ljwei-stak/dsh-galgame@0.1.0`。
|
|
77
|
-
3. 0.13.0 起包名改为 `@ljwei-stak/dsh-model-router`(旧包名最后版本为 0.13.0,内容相同,之后不再更新):在插件管理器卸载原 `@ljwei-stak/model-router-galgame`(保留 profile 与应用数据),再添加 `@ljwei-stak/dsh-model-router@0.16.
|
|
77
|
+
3. 0.13.0 起包名改为 `@ljwei-stak/dsh-model-router`(旧包名最后版本为 0.13.0,内容相同,之后不再更新):在插件管理器卸载原 `@ljwei-stak/model-router-galgame`(保留 profile 与应用数据),再添加 `@ljwei-stak/dsh-model-router@0.16.2`。不要两个同时安装(条目 id 与工具名相同);条目 id 未变,路由设置与执行记录会保留。完成两项更新后再玩剧情,避免同时操作旧合并入口和新入口。
|
|
78
78
|
4. 现在路由与 GAL 各有一个入口。独立 GAL 沿用旧存档 localStorage 键,核对当前进度和三槽;更换 profile 或进度未恢复时,先切换到匹配剧目,再导入 JSON 备份。
|
|
79
79
|
5. 后续分别更新需要的插件;只用路由可以不启用或不安装 GAL。保留 profile 与应用数据,卸载插件时不要清理故事数据。
|
|
80
80
|
|
|
@@ -82,7 +82,7 @@ GAL 核心只包含**《回声之城·正篇》**与**《旧城迁移篇:未
|
|
|
82
82
|
|
|
83
83
|
## 5. 模型路由第一次使用
|
|
84
84
|
|
|
85
|
-
工作台自 0.15.0 起分成**任务与执行、模型配置、官方工具、预算与安全**四页;0.16.
|
|
85
|
+
工作台自 0.15.0 起分成**任务与执行、模型配置、官方工具、预算与安全**四页;0.16.2 沿用该布局。切换页面保留安装任务、终端会话和未完成的输入。
|
|
86
86
|
|
|
87
87
|
1. 在 Harness 官方**模型**页配置供应商、模型与凭据。插件读取准确的 `provider/model` 目录,模型档案不保存 API Key。
|
|
88
88
|
2. 在**模型配置**刷新目录,逐条填写自报质量评分、核对过的输入/输出单价(USD / 百万 token)和擅长方向;缺价留空。可选 `cliModel` 必须是该厂商 CLI 已验证接受的名字。可选 LiveBench 名称须准确对应版本与推理档位;它是用户确认的映射,不自动证明实际执行档位。
|
|
@@ -114,7 +114,7 @@ GAL 核心只包含**《回声之城·正篇》**与**《旧城迁移篇:未
|
|
|
114
114
|
| 检查 | 预期 |
|
|
115
115
|
| --- | --- |
|
|
116
116
|
| 宿主版本 | 0.2.0-rc.1 或 0.2.0-rc.2;包括 `rc` 后缀。 |
|
|
117
|
-
| 路由独立安装 | 0.16.
|
|
117
|
+
| 路由独立安装 | 0.16.2 详情、模型路由入口、目录和模型档案可用;不出现旧合并 GAL 入口。 |
|
|
118
118
|
| GAL 独立安装 | 0.1.0 详情、Gal 模块入口、标题与两部核心剧情可用;不要求安装路由。 |
|
|
119
119
|
| 共同安装 | 两个入口各一份,路由工具和 GAL 播放器均能使用。 |
|
|
120
120
|
| 存档迁移 | 同 profile 可读旧键;跨 profile 用匹配剧目 JSON 导入;旧篇目的数据不覆盖。 |
|
|
@@ -125,11 +125,11 @@ GAL 核心只包含**《回声之城·正篇》**与**《旧城迁移篇:未
|
|
|
125
125
|
| 动态公开数据 | 默认关闭;自行启用后核对快照版本、校验时间及失败/过期状态;人工单价仍优先。 |
|
|
126
126
|
| 可编辑执行 | 在干净测试仓库核对审批、隔离工作区、补丁整合、厂商实际模型与计费。 |
|
|
127
127
|
|
|
128
|
-
历史 0.15.0 的自动测试验证为 220 项通过、3 项 Windows 平台跳过;组件 UI 预览检查使用模拟数据。**0.16.
|
|
128
|
+
历史 0.15.0 的自动测试验证为 220 项通过、3 项 Windows 平台跳过;组件 UI 预览检查使用模拟数据。**0.16.2 的发布验证见[更新记录](CHANGELOG.md)**,不把模拟公开源/模型流和组件预览当作真实付费调用或 Harness Desktop 端到端验收;上表中的实际安装、账号和工作区检查仍需在使用环境中完成。
|
|
129
129
|
|
|
130
130
|
## 8. 开发者从完整源码构建
|
|
131
131
|
|
|
132
|
-
路由需要 Node.js **22.19+** 与 **pnpm 10.34.6**。从完整源码仓库根目录构建;复现正式版 0.16.
|
|
132
|
+
路由需要 Node.js **22.19+** 与 **pnpm 10.34.6**。从完整源码仓库根目录构建;复现正式版 0.16.2 时检出对应发布标签。旧版(如 0.15.0)标签保留其当时内容。运行:
|
|
133
133
|
|
|
134
134
|
```powershell
|
|
135
135
|
pnpm install --frozen-lockfile --strict-peer-dependencies
|
package/README.md
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# Model Router · DeepSeek Harness Desktop
|
|
2
2
|
|
|
3
|
-
Version: **0.16.
|
|
3
|
+
Version: **0.16.2**. See [routing research](docs/ROUTING_RESEARCH.zh.md), [mathematical derivation and experiments](docs/ROUTING_DERIVATION_EXPERIMENTS.zh.md), and the [LiveBench evidence audit and validation protocol](docs/ROUTING_LIVEBENCH_VALIDATION.zh.md). The latest public 2026-06-25 score/cost tables are aggregates; its paired question-quality/cost matrix has not been obtained, and no real routing gain is claimed.
|
|
4
4
|
|
|
5
5
|
A cost-aware model-routing workbench for **DeepSeek Harness Desktop**. Describe a task, compare your configured models, inspect the plan, and explicitly choose when to execute it.
|
|
6
6
|
|
|
7
|
+
**0.16.2:** the official-tools update/install button keeps the job started by that click, stays usable while a previous probe is refreshing, and shows a row error when the click cannot start or the probed version does not advance. Installed Claude Code runs `claude update` before the registry npm install. Installed Windows MiniMax runs the official installer.
|
|
8
|
+
|
|
9
|
+
**0.16.1:** [maturity improvements and validation](docs/ROUTING_MATURITY.zh.md) adds stable feedback cache identity, per-model/task feedback explanations, source-refresh and settings-race protection, and budget gates for unreadable or incomplete cost history. Mechanism tests do not establish real quality–cost gains.
|
|
10
|
+
|
|
7
11
|
**0.16.0:** [dynamic data and adaptive feedback](docs/ROUTING_ADAPTIVE_LEARNING.zh.md) adds opt-in public benchmark/curated fixed-USD pricing refresh and task-specific, time-decayed, shrinkage-regularized subjective utility. Objective proxy quality floors remain separate. Public sources default off; preferences are shared within one local DSH_HOME and limited to the latest 200 runs. This is not a universal vendor-price scraper or evidence of real quality–cost gains.
|
|
8
12
|
|
|
9
|
-
Current version: **0.16.
|
|
13
|
+
Current version: **0.16.2** (`@ljwei-stak/dsh-model-router`). Its declared host compatibility is **DeepSeek Harness Desktop 0.2.0-rc.1 / 0.2.0-rc.2**. The router and [GAL](https://github.com/Alice-Marx/deepseek-harness-galgame) have been independent plugins since 0.12.0.
|
|
10
14
|
|
|
11
15
|
**0.15.0 changes:** a four-tab workbench with routing advice directly below task planning, protection against stale execution previews, preserved spending totals across history pruning and retries, and a standalone mock UI preview for source development.
|
|
12
16
|
|
|
@@ -38,16 +42,16 @@ Generating a route recommendation is local: it does not start a vendor CLI or ma
|
|
|
38
42
|
Open **Plugins → Add plugin** and enter:
|
|
39
43
|
|
|
40
44
|
```text
|
|
41
|
-
@ljwei-stak/dsh-model-router@0.16.
|
|
45
|
+
@ljwei-stak/dsh-model-router@0.16.2
|
|
42
46
|
```
|
|
43
47
|
|
|
44
|
-
Use the official HTTPS npm source `https://registry.npmjs.org/` when a mirror lacks that exact version. Enable the plugin, then fully quit Harness (including its tray process) and restart it. Plugin details should show **0.16.
|
|
48
|
+
Use the official HTTPS npm source `https://registry.npmjs.org/` when a mirror lacks that exact version. Enable the plugin, then fully quit Harness (including its tray process) and restart it. Plugin details should show **0.16.2** and the sidebar should contain **模型路由** (Model Router). A global `npm install -g` alone does not register a Desktop plugin.
|
|
45
49
|
|
|
46
50
|
You can instead install a local `.tgz` archive or its extracted inner `package` directory through the plugin manager. Both must contain `package.json` and `.dsh-plugin`. See [releases](https://github.com/Alice-Marx/dsh-model-router/releases) for archived builds, or build your own checkout below.
|
|
47
51
|
|
|
48
52
|
### Upgrade from the old package name
|
|
49
53
|
|
|
50
|
-
The old name `@ljwei-stak/model-router-galgame` ended at 0.13.0. Remove that plugin entry while retaining your profile/application data, then add `@ljwei-stak/dsh-model-router@0.16.
|
|
54
|
+
The old name `@ljwei-stak/model-router-galgame` ended at 0.13.0. Remove that plugin entry while retaining your profile/application data, then add `@ljwei-stak/dsh-model-router@0.16.2`. Do not keep both entries installed: they share the internal plugin id `model-router-galgame` and tool names. The retained id lets existing router settings and history carry over.
|
|
51
55
|
|
|
52
56
|
For the combined 0.11.x package, back up the profile and export the GAL saves you want to preserve before upgrading. Story playback, artwork, music and saves now belong to the independent `@ljwei-stak/dsh-galgame` package. The detailed save limitations are in [MIGRATION.md](MIGRATION.md).
|
|
53
57
|
|
package/README.zh.md
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# Model Router · DeepSeek Harness 模型路由插件
|
|
2
2
|
|
|
3
|
-
版本:**0.16.
|
|
3
|
+
版本:**0.16.2**。选模求解器概览见[路由研究说明](docs/ROUTING_RESEARCH.zh.md);公式、条件证明与实验见[数学推导与实验记录](docs/ROUTING_DERIVATION_EXPERIMENTS.zh.md)。[LiveBench 最新证据与验证协议](docs/ROUTING_LIVEBENCH_VALIDATION.zh.md)已核查 2026-06-25 聚合评分/费用;最新逐题质量—费用矩阵尚未取得,不声称真实路由收益。
|
|
4
4
|
|
|
5
5
|
为 **DeepSeek Harness Desktop** 提供任务规划、成本感知的模型分配和官方工具执行工作台。输入任务,比较已配置模型,审阅计划,再明确选择是否执行。
|
|
6
6
|
|
|
7
|
+
**0.16.2**:官方工具的更新/安装按钮会保留本次点击启动的任务;已有探测结果时重新体检不再把按钮禁用成无响应;点击无法开始、或安装后探测版本仍低于最新版时,在该行显示错误。已安装的 Claude Code 先执行 `claude update`,再按注册表走 npm;已安装的 Windows MiniMax 走官方安装脚本。
|
|
8
|
+
|
|
9
|
+
**0.16.1 成熟度改进**:稳定反馈缓存、分模型/任务解释、刷新与设置竞态保护,以及费用历史不可读取或不完整时的预算门禁。[推导与验证](docs/ROUTING_MATURITY.zh.md)随安装包提供,机制测试不等于真实质量—成本收益。
|
|
10
|
+
|
|
7
11
|
**0.16.0 新增**:[动态数据与持续反馈](docs/ROUTING_ADAPTIVE_LEARNING.zh.md):可选公开价格/LiveBench快照刷新;按任务类型、时间衰减和低样本收缩调整个人偏好,质量门槛独立保留。设置在“预算与安全”,公开源默认关闭;价格源需提供按官方文档核对的固定USD单价JSON,不是通用官网抓价器。本地DSH_HOME共享、最近200运行窗口,暂无真实收益证明。
|
|
8
12
|
|
|
9
|
-
当前版本为 **0.16.
|
|
13
|
+
当前版本为 **0.16.2**,包名为 `@ljwei-stak/dsh-model-router`;声明兼容的宿主为 **DeepSeek Harness Desktop 0.2.0-rc.1 / 0.2.0-rc.2**。自 0.12.0 起,路由与 [GAL](https://github.com/Alice-Marx/deepseek-harness-galgame) 已拆成两个独立插件。
|
|
10
14
|
|
|
11
15
|
**0.15.0 更新**:工作台分为四页,路由建议紧接任务规划展示;执行输入变化时丢弃旧预览;裁剪历史或重试后仍保留费用累计;源码开发新增独立模拟 UI 预览。
|
|
12
16
|
|
|
@@ -38,16 +42,16 @@
|
|
|
38
42
|
打开 **插件 → 添加插件**,填写:
|
|
39
43
|
|
|
40
44
|
```text
|
|
41
|
-
@ljwei-stak/dsh-model-router@0.16.
|
|
45
|
+
@ljwei-stak/dsh-model-router@0.16.2
|
|
42
46
|
```
|
|
43
47
|
|
|
44
|
-
镜像缺少该精确版本时使用官方 HTTPS npm 源 `https://registry.npmjs.org/`。安装并启用后,完全退出 Harness(包括托盘进程)再启动。插件详情应显示 **0.16.
|
|
48
|
+
镜像缺少该精确版本时使用官方 HTTPS npm 源 `https://registry.npmjs.org/`。安装并启用后,完全退出 Harness(包括托盘进程)再启动。插件详情应显示 **0.16.2**,侧栏出现**模型路由**。仅运行全局 `npm install -g` 不会把插件注册到桌面版 profile。
|
|
45
49
|
|
|
46
50
|
也可在插件管理器填写本地 `.tgz` 文件的绝对路径,或解压后的内层 `package` 目录;其中应包含 `package.json` 与 `.dsh-plugin`。[历史发布页](https://github.com/Alice-Marx/dsh-model-router/releases)提供归档;已克隆源码的开发方式见下文。
|
|
47
51
|
|
|
48
52
|
### 从旧包名升级
|
|
49
53
|
|
|
50
|
-
`@ljwei-stak/model-router-galgame` 的最后版本为 0.13.0。保留 profile 与应用数据,移除旧插件条目,再添加 `@ljwei-stak/dsh-model-router@0.16.
|
|
54
|
+
`@ljwei-stak/model-router-galgame` 的最后版本为 0.13.0。保留 profile 与应用数据,移除旧插件条目,再添加 `@ljwei-stak/dsh-model-router@0.16.2`。不要同时安装两个包:它们共用内部插件 id `model-router-galgame` 与工具名;id 保留使已有路由设置和执行历史能够延续。
|
|
51
55
|
|
|
52
56
|
从 0.11.x 合并版迁移时,先备份 profile 并导出希望保留的 GAL 进度。剧情、立绘、音乐、自由模式和存档属于独立 `@ljwei-stak/dsh-galgame` 插件。导出范围及同 profile 迁移的限制见 [MIGRATION.md](MIGRATION.md)。
|
|
53
57
|
|
|
@@ -149,3 +149,5 @@ npm run check:client
|
|
|
149
149
|
- Client `catalog.mjs`、`router-main.jsx`、`router-insights.jsx`:同源规划、陈旧回包保护和设置界面。
|
|
150
150
|
|
|
151
151
|
这些路径相对 `.dsh-plugin/`。2026-10-04研究阶段未推送、发布npm或变更用户现有设置;2026-10-05按用户要求将实现纳入正式版`0.16.0`,发布状态及安装方式见README/CHANGELOG。发布不自动修改用户现有设置或发起付费模型调用。
|
|
152
|
+
|
|
153
|
+
2026-10-08纳入正式版0.16.1的[成熟度改进](ROUTING_MATURITY.zh.md)补充稳定证据身份/小时衰减刷新、已观察权重诊断、异步/持久化保护及新的反例回归。原始估计式和2026-10-04实验记录保留不覆盖;新增验证不冒充真实质量—成本收益。
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# 动态路由成熟度:可靠性、可解释反馈与验证
|
|
2
|
+
|
|
3
|
+
2026-10-07开始,2026-10-08完成,纳入正式版0.16.1。2026-10-08早期开发归档仍保留当时“本地未发布”状态,正式发布状态以README/CHANGELOG与v0.16.1 Release为准。保留[原始自适应推导与机制实验](ROUTING_ADAPTIVE_LEARNING.zh.md),未覆盖旧实验文件。
|
|
4
|
+
|
|
5
|
+
## 1 本轮解决什么
|
|
6
|
+
|
|
7
|
+
| 复现的问题 | 改进 | 验证入口 |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| 相同账本两次读取,毫秒墙钟改变revision、清掉已生成建议 | 稳定证据身份与小时衰减刷新分离 | adaptive-maturity-feedback / host;实际浏览器生成后刷新 |
|
|
10
|
+
| 对已附加偏好的路线重新应用停用/撤回profile,旧偏好仍残留 | 先剥离旧偏好字段,再应用当前有效投影 | adaptive-maturity-feedback |
|
|
11
|
+
| 负用量、空用量、浮点溢出被计为负费、免费或Infinity | 非法/缺失值保持费用未知;合法零和CLI自报费用仍保留 | adaptive-maturity-feedback;计费账本回归 |
|
|
12
|
+
| 刷新进程中断或总超时未到达底层请求、旧错误在刷新中变成fresh | 有界租约恢复、总超时信号、非阻塞响应取消、保留失败状态 | adaptive-maturity-data |
|
|
13
|
+
| 公开源A换B后套用A价格、旧回包覆盖当前设置 | 源级取消/请求身份;Host按最新设置再次投影,磁盘旧快照不冒充新源 | adaptive-maturity-data / host |
|
|
14
|
+
| 同时保存设置冲突、旧提交成功清空新输入、暂停节点Hook顺序变化 | 同步提交保护、提交草稿比对、Hook固定顺序、显式摘要刷新状态 | adaptive-maturity-ui |
|
|
15
|
+
| 锁等待超时拆掉活锁、失败事务污染读取缓存 | 活锁超时明确失败;归属检查;成功后才提交分离缓存 | adaptive-maturity-state |
|
|
16
|
+
| 未知schema或损坏历史被当成正常零花费 | 未知schema拒读/拒写不降级;损坏备份唯一,历史不完整标记持久化,有限预算执行拒绝 | adaptive-maturity-state / host |
|
|
17
|
+
|
|
18
|
+
测试文件均在`tests/`;所有费用、评价、公开源、模型流都是隔离合成夹具,不使用真实用户DSH_HOME。
|
|
19
|
+
|
|
20
|
+
## 2 反馈估计不变,但解释更完整
|
|
21
|
+
|
|
22
|
+
在准确provider/model/任务域单元内,保留显式人工结果评分`r_i∈{-1,+1}`,完成时间为`t_i`。记半衰期H(天),`λ=ln(2)/(H×86400000)`,`w_i(t)=exp[-λ(t-t_i)]`。
|
|
23
|
+
|
|
24
|
+
令`R=Σw_i r_i`、`W=Σw_i`,收缩常数`κ≥1`、偏好上限`0≤B≤0.1`:
|
|
25
|
+
|
|
26
|
+
`b(t)=B R/(κ+W)`。
|
|
27
|
+
|
|
28
|
+
新增解释字段包括原始有用/不好数、W、`W/(κ+W)`收缩系数、b,以及权重集中诊断`n_eff=W²/Σw_i²`。若仅在一个假设模型下、给定固定权重把标签视为独立同方差变量,则加权平均的方差为`σ²Σw_i²/W²`,与`n_eff`个等权观察的方差形式相同;这只是解释公式来源。真实反馈并不保证独立、同方差或代表所有任务,所以这里**不产生置信区间、正确率、风险认证或真实收益结论**。
|
|
29
|
+
|
|
30
|
+
非负权重满足`0≤n_eff≤n`(全零定义0);等权非零时为n。实数运算下,所有完成时间统一变老且没有新证据时,权重乘相同因子,n_eff不变,而W及收缩系数下降。因此必须同时显示原始数、W和n_eff,不能仅凭n_eff声称旧证据仍新鲜。实现用相对最大权重计算集中度,避免极小权重平方下溢,并夹到`[0,n]`消除ULP越界;但原始指数权重本身下溢归零后,共同老化不变性不再成立,例如H=1且年龄1073/1074天时继续老化得到ESS约`1.8→1→0`,偏好此前已趋零。这些诊断不进入路线评分。
|
|
31
|
+
|
|
32
|
+
未参与学习的原因按固定类别展示:未评价/撤回、未成功执行、CLI实际模型未核验、过期学习起点、非法/未来时间或身份等。缺失评价不是不满意;修改同一结果评价不是新增独立样本。界面最多展开12组,且不复制任务文本/回答进学习profile。
|
|
33
|
+
|
|
34
|
+
## 3 稳定缓存身份与衰减精度的权衡
|
|
35
|
+
|
|
36
|
+
`evidenceRevision`由参数和有效结果身份/模型/域/评分/完成时间生成,不包含读取墙钟或仅用于审计的重评时间。有效反馈改变、撤回、替换、参数或重置改变会立即改变身份。`revision`另带1小时`decayEpoch`,仅在存在有效反馈且B>0时加入;空、停用或零上限profile不随时间无意义清空方案。FNV短revision只是缓存提示,不是安全哈希或连续权重的精确内容身份。
|
|
37
|
+
|
|
38
|
+
每次真正规划仍用实际`evaluatedAt`精算权重;已有方案在同一小时内可能保留微小旧偏好,跨小时在下次账本读取时失效。没有后台定时任务,关闭应用不会自动轮询。
|
|
39
|
+
|
|
40
|
+
在证据、参数不变且没有样本进入/退出有效集合的区间内,`R'=-λR`、`W'=-λW`,故
|
|
41
|
+
|
|
42
|
+
`b'=-λBκR/(κ+W)²`,且`|R|≤W`、`κW/(κ+W)²≤1/4`,得到
|
|
43
|
+
|
|
44
|
+
`|b(t+Δ)-b(t)|≤BλΔ/4`。
|
|
45
|
+
|
|
46
|
+
一小时内,在允许的极端H=1、B=0.1下,上界约0.000722;默认H=30、B=0.04约0.00000963。该界不是排名不变保证:极近的路线仍可能交换偏好顺序。新证据或参数变化不受这段固定集合界保护,会立即失效;质量硬门槛和费用约束没有放松。独立代数/数值机制核验见`adaptive-maturity-derivation.test.mjs`。
|
|
47
|
+
|
|
48
|
+
## 4 公开源与历史状态的安全降级
|
|
49
|
+
|
|
50
|
+
公开数据仍默认关闭、只支持无认证公开HTTPS端点,不发送任务或反馈。错误只投影固定公开类别。TTL是尝试间隔,pricing校验日期依然由来源声明的asOf决定;重新下载旧价格不会“洗新”。失败保留同源最后有效快照并展示陈旧/失败状态,源B未验证成功不能套用源A。超时、过大响应、不安全回包URL和非法UTF-8拒收;取消流不等待不可靠cancel承诺。默认总超时8秒、遗留请求租约加5秒宽限;按源处理取消,避免改价格源误停仍有效的基准请求。
|
|
51
|
+
|
|
52
|
+
状态锁使用单调时钟限等待,不因墙钟变化无限等,也不抢活锁;仅能证明owner进程已退出且满足陈旧条件才尝试回收。不认识owner则明确超时。回写事务失败不污染缓存,返回值与内部提交副本分离,异步updateRun会等待并正确回滚。
|
|
53
|
+
|
|
54
|
+
已损坏JSON先在写锁内重读、使用唯一备份名,再开始新记录;未来版本/不支持结构的有效JSON保留原字节并拒写。明确存在却畸形的费用集合、金额或时间戳会持久标记`historyIncomplete`;摘要不是完整账单,已配置日/月预算时不能用它授权新的执行。关闭提示不会清除这个标记;需从备份人工恢复并核验完整状态,不能用“从现在重新学习”抹掉费用保护。缺省的旧版可选字段仍兼容。
|
|
55
|
+
|
|
56
|
+
## 5 复现与覆盖
|
|
57
|
+
|
|
58
|
+
```powershell
|
|
59
|
+
pnpm install --frozen-lockfile --strict-peer-dependencies
|
|
60
|
+
npm run build:client
|
|
61
|
+
npm test
|
|
62
|
+
npm run check:client
|
|
63
|
+
node scripts/workbench-preview.mjs --check
|
|
64
|
+
node scripts/adaptive-routing-study.mjs --out <new-output.json>
|
|
65
|
+
npm run preview:ui -- --port 4173
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
最后一条只启动内存mock演示:公开连接被CSP禁用,无CLI或付费模型调用。已实际查看反馈解释、开关停用/恢复、半衰期保存、生成方案后无变化刷新保留、撤回反馈后旧方案清除、差评对应负调整;浏览器error日志为空。确定性UI事件测试另覆盖晚返回草稿、重复提交、冲突重试和paused→完成Hook顺序。
|
|
69
|
+
|
|
70
|
+
成熟度开发阶段的完整日志/源码副本/截图存独立归档,不覆盖2026-10-04合成实验。随后按用户要求发布0.16.1,安装方法与发布状态见README/CHANGELOG;没有修改真实用户配置或账本,发布不自动启动付费执行。
|
|
71
|
+
|
|
72
|
+
## 6 尚未覆盖
|
|
73
|
+
|
|
74
|
+
缺少最新同题质量—费用矩阵,不证明真实准确率、满意度、节省比例或自动学习最优参数。未做真实Harness安装/跨进程桌面端到端、真实付费模型或完整计费阶梯实测;偏好仍本地共享最近200运行,无账号隔离或自动付费探索。
|
|
75
|
+
|
|
76
|
+
损坏schema检查并非穷尽验证全部历史字段;文件锁同时回收死亡owner仍有检查与unlink之间的TOCTOU边界,未验证断电fsync级持久性;URL语法校验不是DNS重绑定隔离。需要更严格多租户/高并发环境时应在明确需求下迁移事务数据库、加入系统网络边界和时间外真实实验,而非把当前测试数当作一般保证。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ljwei-stak/dsh-model-router",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Model Router for official DeepSeek Harness Desktop: cost-aware task routing, dependent work packages and official vendor CLI discovery, installation and execution. GAL is available separately as @ljwei-stak/dsh-galgame.",
|
|
6
6
|
"repository": {
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
".dsh-plugin/shared/vendor-minimax-adapter.mjs",
|
|
58
58
|
".dsh-plugin/shared/vendor-mimo-grok-adapter.mjs",
|
|
59
59
|
".dsh-plugin/shared/latest-versions.mjs",
|
|
60
|
+
".dsh-plugin/shared/version-order.mjs",
|
|
60
61
|
".dsh-plugin/shared/npm-attestation.mjs",
|
|
61
62
|
".dsh-plugin/shared/zcode-bundle.mjs",
|
|
62
63
|
".dsh-plugin/shared/zcode-installer.mjs",
|
|
@@ -79,6 +80,7 @@
|
|
|
79
80
|
"docs/ROUTING_LIVEBENCH_DATA_SEARCH.zh.md",
|
|
80
81
|
"docs/ROUTING_SELFTEST_STEPS.zh.md",
|
|
81
82
|
"docs/ROUTING_ADAPTIVE_LEARNING.zh.md",
|
|
83
|
+
"docs/ROUTING_MATURITY.zh.md",
|
|
82
84
|
"docs/assets/workbench-task-preview.jpg",
|
|
83
85
|
"docs/assets/routing-workflow.svg",
|
|
84
86
|
"docs/assets/desktop-official-tools-0.9.0.png",
|