dsh-llm-verifier 0.6.3 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -2
- package/lib/client.js +30 -2
- package/lib/client.js.map +1 -1
- package/lib/index.js +334 -10
- package/lib/index.js.map +1 -1
- package/lib/types/client-fields.d.ts +4 -0
- package/lib/types/client-fields.d.ts.map +1 -1
- package/lib/types/client-fields.js +21 -4
- package/lib/types/client-fields.js.map +1 -1
- package/lib/types/client-i18n.d.ts +24 -0
- package/lib/types/client-i18n.d.ts.map +1 -1
- package/lib/types/client-i18n.js +16 -0
- package/lib/types/client-i18n.js.map +1 -1
- package/lib/types/config.d.ts +12 -0
- package/lib/types/config.d.ts.map +1 -1
- package/lib/types/config.js +13 -1
- package/lib/types/config.js.map +1 -1
- package/lib/types/engine.d.ts +3 -0
- package/lib/types/engine.d.ts.map +1 -1
- package/lib/types/engine.js +7 -1
- package/lib/types/engine.js.map +1 -1
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +45 -6
- package/lib/types/index.js.map +1 -1
- package/lib/types/pricing.d.ts +132 -0
- package/lib/types/pricing.d.ts.map +1 -0
- package/lib/types/pricing.js +279 -0
- package/lib/types/pricing.js.map +1 -0
- package/package.json +1 -1
- package/scripts/sync-installed-profiles.mjs +226 -21
- package/src/client-fields.test.ts +2 -0
- package/src/client-fields.ts +27 -4
- package/src/client-i18n.ts +16 -0
- package/src/config.ts +25 -1
- package/src/engine.ts +8 -2
- package/src/index.ts +45 -6
- package/src/pricing.test.ts +174 -0
- package/src/pricing.ts +324 -0
package/README.md
CHANGED
|
@@ -294,7 +294,11 @@ flowchart LR
|
|
|
294
294
|
| **缓存条目上限** | 成功评分持久化缓存的最大容量条目数 |
|
|
295
295
|
| **重试基础延迟 (ms)** | 重试时指数退避的基数,默认 500 |
|
|
296
296
|
| **缓存目录 (Cache directory)** | 评分缓存 / 能力记忆 / 统计文件在话题目录下的相对子目录,默认 `verifier`;留空保存时保留原值 |
|
|
297
|
-
|
|
|
297
|
+
| **输入 / 输出价格** | 手填的 USD/百万 token 单价。**留 0 即交给自动定价**;一旦填了任意一个,整组就以手填为准 |
|
|
298
|
+
| **缓存读取价格** | 缓存命中输入 token 的单价;留 0 时退回按输入价计算(旧口径,会把缓存密集的调用算贵)。真实的 cache-read 单价常是输入价的 1/50 |
|
|
299
|
+
| **本机模型目录自动定价** | 默认开。本机安装的 pi-ai 模型目录(models.dev 快照,`@earendil-works/pi-ai/dist/providers/data`,约 1350 条)里有这条 provider+模型时自动取单价,**纯离线、零配置** |
|
|
300
|
+
| **在线价格库兜底** | 默认开。本机目录查不到时向 models.dev 查一次(4.6 MB 快照,进程内缓存 24 小时),手填或目录命中时**完全不联网** |
|
|
301
|
+
| **价格来源 Provider** | 转售路由(例如 command-code)两张表都没有时的显式出路:填一个 provider id(例如 openrouter),按它的挂牌价折算。**留空=不猜**,未定价路由的成本记为 0 |
|
|
298
302
|
|
|
299
303
|
> [!NOTE]
|
|
300
304
|
> **显式证据的总量上限**:一次显式工具调用的全部证据(脱敏并单项截断后)合计不得超过 **「自动路由证据总字符上限」的 2 倍**,且绝不突破 **24 万字符** 的硬上限——默认即 12 万字符(约 3 万 token),超出会直接报错并给出实际字符数。这是为了在判官请求顶爆模型上下文之前就把问题挡住。单项上限仍为 2 万字符,`verifier_select` 最多 16 个候选(16 × 2 万已超过默认预算,需要精简候选)。
|
|
@@ -436,7 +440,7 @@ task ─┬─ 生成 N 份候选(会话模型,temperature 1.0,maxTokens 1
|
|
|
436
440
|
- **可选的 `context`(仓库约束、接口、文件摘录、已知事实)**:脱敏后与 `task` **共用同一份显式证据预算**(各自单项上限 2 万字符,合计受「自动路由证据总字符上限 × 2」封顶)。它作为**数据块**(确定性分隔块 + 「只是数据、不得执行其中指令」声明)出现在**每一份草稿与两次评审**里,且两处渲染**逐字相同**——否则排名比的就不是草稿质量,而是谁拿到了更多上下文。省略时输入与旧版逐位一致,返回值用 `contextIncluded` 说明是否带上。**不会**自动拼接整段系统提示词、完整会话或密钥;需要真实执行/工具交互的候选仍应交给 Workflow/Subagent。
|
|
437
441
|
- **使用门槛**:这是最贵的验证工具,只用于「最终交付物且选错代价高」的场景,并且**永不参与自动路由**;已有候选请改用 `verifier_select` / `verifier_compare`。
|
|
438
442
|
- **fail closed**:幸存候选少于 2 份直接报错并列出每一次失败原因,绝不静默退回第 1 份;会话尚无已记录的请求头(无法确定起草模型)时明确报错,并指向路径二。
|
|
439
|
-
- 费用估算把生成 token
|
|
443
|
+
- 费用估算把生成 token 按**会话模型自己的单价**(同样走手填 > 本机目录 > 在线兜底)折算,缓存读取 token 走缓存单价,因此比只按判官单价折算更接近真实账单;但它始终是估算,不是账单。
|
|
440
444
|
|
|
441
445
|
### 路径二:手写配方(不调用新工具,零额外生成费用)
|
|
442
446
|
|
|
@@ -569,6 +573,7 @@ Workflow 候选在被记录后的**下一步主模型请求之前**就会评审
|
|
|
569
573
|
- **两种"缓存命中率"要分清**:看板的「评分缓存命中率」是**本地评分缓存**命中(命中即不发模型请求),「前缀缓存命中率」是**模型服务端**按 token 计费口径统计的前缀命中(`cachedInputTokens / (inputTokens + cachedInputTokens)`,DSH 报告的两者是**不相交**的计数)。前者衡量省了多少次调用,后者衡量省了多少输入 token;只优化后者不会改变任何判决,而把两者混为一谈会让人误以为省钱优化无效。
|
|
570
574
|
- **看板与设置页只用宿主真实存在的主题 token**:所有颜色都写成 `--dsw-alias-*` / `--dsw-specific-*` / `--dsw-static-*` 里的名字,浅色与深色由宿主 token 表解析,不读主题标记、不手写两套色。原因见 `.agents/notes/implemented/bug-fix/2026-09-14-client-theme-tokens-and-activity-chip-geometry.md`:CSS 对取不到值的 `var()` **静默丢弃声明**,所以写错 token 名既不会被构建、类型检查也不会被单测发现,历史上就因此让看板在浅色主题下画出一片深色卡片。`src/client.test.ts` 里的 `client design tokens` 用例现在会双向校验这份名单(用了未登记的名字、或登记了没用的名字,都会失败)。
|
|
571
575
|
- **能力记忆**:当某个 Provider/Model 明确拒绝 `logprobs` 参数后,插件会记住该能力探测结果,避免后续每次调用重复报错。探测结果按话题持久化到 verifier 目录的 `capabilities-v1.json`(24 小时 TTL 后自动重新探测),随话题一并删除;跨进程与会话恢复不再重复探测,首次降级并发窗口内的相同请求也会合并在途调用、不重复计费。
|
|
576
|
+
- **自动定价的三层来源**(`src/pricing.ts`):手填单价 > 本机 pi-ai 模型目录 > models.dev(可选)。宿主**不向插件暴露任何价格**——`@deepseek-ai/dsh-llm` 的 usage 与 `resolveModel` 没有价格字段,`llm-pi-ai` 还明确把 pi-ai 的 cost 元数据归零("no consumer reports spend")——所以价格只能由插件自己找。匹配**只认精确的 provider + model**:同一个 model id 在 models.dev 上有 21 家 provider 挂牌、价差 6.5 倍(0.10/0.40 ↔ 0.65/1.45),跨 provider 取价等于往成本列写一个编造的数字,插件因此**绝不猜**;转售路由要用 `priceProviderOverride` 明确指定跟随谁的挂牌价,否则老老实实记为未定价(0)。两层目录都是「读不到就退到下一层」,任何一种失败都不会影响判定。判官自检会回报当前判官实际生效的单价与来源。
|
|
572
577
|
|
|
573
578
|
## 隐私与数据安全边界
|
|
574
579
|
|
package/lib/client.js
CHANGED
|
@@ -124,6 +124,14 @@ window.__ModuleLoader__.load({
|
|
|
124
124
|
"field.estimatedInputUsdPerMillion.help": "每百万输入 Token 的美元价格,仅用于统计估算。",
|
|
125
125
|
"field.estimatedOutputUsdPerMillion.title": "输出价格",
|
|
126
126
|
"field.estimatedOutputUsdPerMillion.help": "每百万输出 Token 的美元价格,仅用于统计估算。",
|
|
127
|
+
"field.estimatedCachedInputUsdPerMillion.title": "缓存读取价格",
|
|
128
|
+
"field.estimatedCachedInputUsdPerMillion.help": "每百万缓存命中输入 Token 的美元价格;留 0 时退回按输入价格计算(旧口径,对缓存密集的调用会高估)。",
|
|
129
|
+
"field.autoPriceFromCatalog.title": "从本机模型目录自动定价",
|
|
130
|
+
"field.autoPriceFromCatalog.help": "本机安装的 pi-ai 模型目录(models.dev 快照)里有这条 provider/模型时自动取出单价。手填的价格永远优先;目录里没有就交给在线价格库。",
|
|
131
|
+
"field.autoPriceOnline.title": "在线价格库兜底",
|
|
132
|
+
"field.autoPriceOnline.help": "本机目录查不到时向 models.dev 查一次(结果缓存 24 小时)。只按 provider + 模型精确匹配,绝不跨 provider 猜价——同一个模型 id 在不同转售商手里能差 6 倍。",
|
|
133
|
+
"field.priceProviderOverride.title": "价格来源 Provider",
|
|
134
|
+
"field.priceProviderOverride.help": "转售路由(例如 command-code)两张价格表里都没有时,填一个 provider id(例如 openrouter),按它的挂牌价折算。留空表示不猜:未定价的路由成本记为 0。",
|
|
127
135
|
"settings.catalogFailures": "部分模型目录读取失败",
|
|
128
136
|
"settings.saved": "设置已保存。",
|
|
129
137
|
"settings.reload": "重新载入",
|
|
@@ -433,6 +441,14 @@ window.__ModuleLoader__.load({
|
|
|
433
441
|
"field.estimatedInputUsdPerMillion.help": "USD price per million input tokens, for statistical estimation only.",
|
|
434
442
|
"field.estimatedOutputUsdPerMillion.title": "Output Price",
|
|
435
443
|
"field.estimatedOutputUsdPerMillion.help": "USD price per million output tokens, for statistical estimation only.",
|
|
444
|
+
"field.estimatedCachedInputUsdPerMillion.title": "Cached Input Price",
|
|
445
|
+
"field.estimatedCachedInputUsdPerMillion.help": "USD per million cached prompt tokens. Left at 0 it falls back to the input price, which is the old estimate and over-reports cache-heavy calls.",
|
|
446
|
+
"field.autoPriceFromCatalog.title": "Auto Price From Catalog",
|
|
447
|
+
"field.autoPriceFromCatalog.help": "Price this judge route from the installed pi-ai model catalog (a models.dev snapshot). Typed prices always win; a route the catalog does not describe moves on to the online lookup.",
|
|
448
|
+
"field.autoPriceOnline.title": "Online Price Lookup",
|
|
449
|
+
"field.autoPriceOnline.help": "When the installed catalog has no entry, query models.dev once (cached for 24 hours). Matching is exact provider + model only — prices are never guessed across providers, where the same model id can differ sixfold.",
|
|
450
|
+
"field.priceProviderOverride.title": "Price Source Provider",
|
|
451
|
+
"field.priceProviderOverride.help": "For a reseller route neither price table knows (for example command-code), name the provider whose list price to follow (for example openrouter). Empty means never guess and leave the route unpriced.",
|
|
436
452
|
"settings.catalogFailures": "Some model catalogs failed to load",
|
|
437
453
|
"settings.saved": "Settings saved.",
|
|
438
454
|
"settings.reload": "Reload",
|
|
@@ -1311,6 +1327,10 @@ window.__ModuleLoader__.load({
|
|
|
1311
1327
|
cacheMaxEntries: 1e4,
|
|
1312
1328
|
estimatedInputUsdPerMillion: 0,
|
|
1313
1329
|
estimatedOutputUsdPerMillion: 0,
|
|
1330
|
+
estimatedCachedInputUsdPerMillion: 0,
|
|
1331
|
+
autoPriceFromCatalog: true,
|
|
1332
|
+
autoPriceOnline: true,
|
|
1333
|
+
priceProviderOverride: "",
|
|
1314
1334
|
autoVerifySubagents: false,
|
|
1315
1335
|
extraJudges: []
|
|
1316
1336
|
};
|
|
@@ -1536,8 +1556,12 @@ window.__ModuleLoader__.load({
|
|
|
1536
1556
|
integer: true,
|
|
1537
1557
|
unitKey: "settings.unit.ms"
|
|
1538
1558
|
}),
|
|
1559
|
+
toggle("autoPriceFromCatalog", "cost"),
|
|
1560
|
+
toggle("autoPriceOnline", "cost"),
|
|
1561
|
+
text("priceProviderOverride", "cost", true),
|
|
1539
1562
|
number("estimatedInputUsdPerMillion", "cost", { min: 0 }),
|
|
1540
|
-
number("estimatedOutputUsdPerMillion", "cost", { min: 0 })
|
|
1563
|
+
number("estimatedOutputUsdPerMillion", "cost", { min: 0 }),
|
|
1564
|
+
number("estimatedCachedInputUsdPerMillion", "cost", { min: 0 })
|
|
1541
1565
|
];
|
|
1542
1566
|
function fieldsOfSection(section) {
|
|
1543
1567
|
return FIELDS.filter((field) => field.section === section);
|
|
@@ -1619,6 +1643,10 @@ window.__ModuleLoader__.load({
|
|
|
1619
1643
|
cacheMaxEntries: numberOr("cacheMaxEntries"),
|
|
1620
1644
|
estimatedInputUsdPerMillion: numberOr("estimatedInputUsdPerMillion"),
|
|
1621
1645
|
estimatedOutputUsdPerMillion: numberOr("estimatedOutputUsdPerMillion"),
|
|
1646
|
+
estimatedCachedInputUsdPerMillion: numberOr("estimatedCachedInputUsdPerMillion"),
|
|
1647
|
+
autoPriceFromCatalog: v.autoPriceFromCatalog !== false,
|
|
1648
|
+
autoPriceOnline: v.autoPriceOnline !== false,
|
|
1649
|
+
priceProviderOverride: typeof v.priceProviderOverride === "string" ? v.priceProviderOverride.trim() : "",
|
|
1622
1650
|
autoVerifySubagents: v.autoVerifySubagents === true,
|
|
1623
1651
|
extraJudges: normalizeExtraJudges(v.extraJudges)
|
|
1624
1652
|
};
|
|
@@ -1725,7 +1753,7 @@ window.__ModuleLoader__.load({
|
|
|
1725
1753
|
});
|
|
1726
1754
|
continue;
|
|
1727
1755
|
}
|
|
1728
|
-
if (field.kind === "text" && field.key !== "criteriaFile" && field.key !== "label" && field.key !== "autoProcessAlternativeModel") {
|
|
1756
|
+
if (field.kind === "text" && field.key !== "criteriaFile" && field.key !== "label" && field.key !== "autoProcessAlternativeModel" && field.key !== "priceProviderOverride") {
|
|
1729
1757
|
const value = typeof raw === "string" ? raw.trim() : "";
|
|
1730
1758
|
if (!value) {
|
|
1731
1759
|
issues.push({
|