dsh-budget 0.4.9 → 0.4.11

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-zh.md CHANGED
@@ -10,13 +10,16 @@
10
10
  > **官方仓库。** 本仓库是 dsh-budget 的唯一官方仓库,由 PerryLink 维护。其他账号下的同名仓库与本项目无关。
11
11
 
12
12
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
13
+ [![Gitee](https://img.shields.io/badge/Gitee-mirror-c71d23?logo=gitee)](https://gitee.com/perrylink/dsh-budget)
13
14
  [![DSH plugin](https://img.shields.io/badge/dsh--plugin-✅-green)](https://github.com/topics/dsh-plugin)
14
15
  [![dsh-doctor](https://raw.githubusercontent.com/PerryLink/dsh-plugin-doctor/main/badges/PerryLink__dsh-budget.svg)](https://github.com/PerryLink/dsh-plugin-doctor#verified-徽章)
16
+ [![DSH Market](https://raw.githubusercontent.com/2BingLing/dsh-market/master/assets/readme/badge-listed-zh.svg)](https://dsh.market/)
15
17
  [![Node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-brightgreen.svg)](#)
16
18
  [![CI](https://img.shields.io/github/actions/workflow/status/PerryLink/dsh-budget/ci.yml?branch=main&label=CI)](https://github.com/PerryLink/dsh-budget/actions)
17
19
  [![Version](https://img.shields.io/github/v/tag/PerryLink/dsh-budget?label=version)](https://github.com/PerryLink/dsh-budget/releases)
18
20
  [![npm version](https://img.shields.io/npm/v/dsh-budget)](https://www.npmjs.com/package/dsh-budget)
19
21
  [![npm downloads](https://img.shields.io/npm/dm/dsh-budget)](https://www.npmjs.com/package/dsh-budget)
22
+ [![dshfind](https://dshfind.com/api/badge/PerryLink/dsh-budget?metric=downloads&lang=zh)](https://dshfind.com/zh/plugins/PerryLink/dsh-budget?ref=badge)
20
23
 
21
24
  [English](README.md) · [简体中文](README-zh.md) · [Español](README-es.md) · [Português](README-pt.md) · [हिन्दी](README-hi.md)
22
25
 
@@ -28,7 +31,7 @@
28
31
 
29
32
  | 方面 | 状态 |
30
33
  |---|---|
31
- | Harness | DeepSeek Harness `dsh-v0.1.5-rc.2`(GitHub tag,2026-09-11 核验;npm 钉号 `0.1.5-rc.2`,2026-09-10 已适配;peer 范围 `>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0`):会话信封保留 ignorable 字段但仅用于存量日志读取兼容——Session.append 仍无法盖章,门控行为不变。已于 2026-09-11 对照 dsh-v0.1.5-rc.2 master 检出核验(完整本地门禁链;profile 安装冒烟由每月 Compat workflow 覆盖)。 |
34
+ | Harness | DeepSeek Harness `dsh-v0.1.7-rc.1`(GitHub tag,2026-09-24 已适配;peer 范围 `>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0`):alpha.2 目录价已内置进价目表,未定价模型以「未定价」呈现而非虚构估算;审计门继续抑制 `budget/alert`/`budget/block` 落盘(fail-closed 会话事件词表)。已于 2026-09-24 通过双尺子 typecheck 链与完整本地门禁核验;浏览器面板项为 人工·未测即未完成(维护者人工清单)。 |
32
35
 
33
36
  | 审计事件 | `0.1.2-rc.1` 之前的宿主上写入;在 `0.1.2-rc.1` 及以后抑制并记录降级原因(fail-closed 会话事件词表,无外部注册面) || Node | `^22.19.0 \|\| >=24.0.0` |
34
37
  | 界面 | Host + Web 客户端(设置页预算页签);`/budget` 命令 |
@@ -73,7 +76,7 @@ dsh --profile web --dump-config | grep -A2 'id: budget'
73
76
  | 键 | 默认值 | 含义 |
74
77
  |---|---|---|
75
78
  | `prices` | `{}` | 每模型 USD/百万 token 价格,合并覆盖内置价目表 |
76
- | `defaultPrice` | `{input: 1.0, output: 3.0}` | 两表均无该模型时的回退价格 |
79
+ | `defaultPrice` | 未定价信号(`priced: false`,数字为零) | 两表均无该模型时的回退:默认对记账贡献 0 并显示「未定价」;设置数字并加 `priced: true` 可为未知模型显式定价 |
77
80
  | `budgets.session` / `daily` / `monthly` | `10` / `50` / `500` | 各作用域 USD 预算上限;缺省表示不限 |
78
81
  | `warnRatio` | `0.8` | 用量达到上限该比例时告警(0..1) |
79
82
  | `overLimit` | `alert` | 超限后策略:`alert` / `block` / `degrade` |
@@ -125,7 +128,7 @@ dsh --profile web --dump-config | grep -A2 'id: budget'
125
128
  ```sh
126
129
  pnpm install # node ^22.19 || >=24
127
130
  pnpm run typecheck # tsc:src + tests,对照本地 harness checkout
128
- pnpm run typecheck:ci # tsc:对照已发布的 0.1.5-rc.2 类型(无 paths)
131
+ pnpm run typecheck:ci # tsc:对照已发布的 0.1.7-rc.1 类型(无 paths)
129
132
  pnpm test # vitest
130
133
  pnpm run build # tsc 声明 + tsdown bundles(lib/)
131
134
  pnpm run verify:self-contained # 依赖声明全部来自 registry
@@ -143,46 +146,56 @@ pnpm pack # 发布用 tarball
143
146
 
144
147
  ## PerryLink DSH Plugin Family
145
148
 
146
- 这是 [PerryLink](https://github.com/PerryLink) 维护的 [37 个 DeepSeek Harness 插件](https://github.com/PerryLink) 之一。如果它能帮到你,其他的也会:
149
+ This project is one of the **45 DeepSeek Harness plugins** maintained by [PerryLink](https://github.com/PerryLink). If this one helps you, the others likely will too:
147
150
 
148
151
  | Plugin | One-liner |
149
152
  |---|---|
150
- | **[dsh-auto-review](https://github.com/PerryLink/dsh-auto-review)** | 审批链上的第二模型自动审查,默认失败关闭 | |
151
- | **[dsh-background-agents](https://github.com/PerryLink/dsh-background-agents)** | 带 Web UI 侧栏、消息与中断的持久后台子代理 | |
152
- | **[dsh-checkpoint-rewind](https://github.com/PerryLink/dsh-checkpoint-rewind)** | Claude Code /rewind 等价:快照、会话 fork、一次性恢复 | |
153
- | **[dsh-claude-move](https://github.com/PerryLink/dsh-claude-move)** | 把 Claude Code 会话、记忆、技能与 CLAUDE.md 迁入 DSH | |
154
- | **[dsh-click](https://github.com/PerryLink/dsh-click)** | 跨平台原生桌面控制(DeepSeek Harness),Windows 优先。 | |
155
- | **[dsh-composer-history](https://github.com/PerryLink/dsh-composer-history)** | Web 输入框的终端式历史:方向键、Ctrl+R 搜索 | |
156
- | **[dsh-data-quality](https://github.com/PerryLink/dsh-data-quality)** | 数据集质量检查与引文核查(本插件可选消费的数字核查桥) | |
157
- | **[dsh-defend](https://github.com/PerryLink/dsh-defend)** | DeepSeek Harness 的提示注入、越狱与密钥泄露防护。 | |
158
- | **[dsh-doublecheck](https://github.com/PerryLink/dsh-doublecheck)** | 工程纪律守卫:需求质询、测试门禁、对手评审 | |
159
- | **[dsh-draw](https://github.com/PerryLink/dsh-draw)** | DeepSeek Harness 的统一静态图像生成路由。 | |
160
- | **[dsh-fast](https://github.com/PerryLink/dsh-fast)** | DeepSeek Harness 只读性能诊断。 | |
161
- | **[dsh-fund-research](https://github.com/PerryLink/dsh-fund-research)** | 面向中国公募基金的确定性研究报告 | |
162
- | **[dsh-github](https://github.com/PerryLink/dsh-github)** | 面向 DSH 的 GitHub PR/issues 集成,每次写入经审批门控 | |
163
- | **[dsh-industry-research](https://github.com/PerryLink/dsh-industry-research)** | 行业研究编排,经本插件的 `ctx.researchReport.assemble` 封存交付物 | |
164
- | **[dsh-library](https://github.com/PerryLink/dsh-library)** | DeepSeek Harness 的本地文档知识库。 | |
165
- | **[dsh-local-ai](https://github.com/PerryLink/dsh-local-ai)** | DeepSeek Harness 的本地模型(Ollama)接入。 | |
166
- | **[dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions)** | 通过语言服务器的 LSP 诊断、格式化、补全、代码操作与重命名 | |
167
- | **[dsh-mask](https://github.com/PerryLink/dsh-mask)** | PII 脱敏中间件:模型边界匿名化、展示层还原 | |
168
- | **[dsh-mcp-panel](https://github.com/PerryLink/dsh-mcp-panel)** | 只读 MCP 运行时面板:/mcp 命令 + 带状态、工具与错误的 Settings 标签页 | |
169
- | **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | 审批门控的跨会话记忆:ctx.memory 接缝 + SQLite + 记忆工具 | |
170
- | **[dsh-observe](https://github.com/PerryLink/dsh-observe)** | DeepSeek Harness 的 OpenTelemetry 与 Langfuse 可观测导出器。 | |
171
- | **[dsh-output-styles](https://github.com/PerryLink/dsh-output-styles)** | Claude Code outputStyles 等价的运行时风格切换 | |
172
- | **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | Claude Code 风格声明式 allow/deny/ask 权限规则,带审计 | |
173
- | **[dsh-personal-directive](https://github.com/PerryLink/dsh-personal-directive)** | 个人指令注入器:顶栏开关(框架版) |
174
- | **[dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide)** | 作为按需代理技能的插件开发知识库 | |
175
- | **[dsh-reach](https://github.com/PerryLink/dsh-reach)** | 多渠道审批/提问桥接:微信/Telegram/飞书,会话控制台 |
176
- | **[dsh-research-report](https://github.com/PerryLink/dsh-research-report)** | 可验证研究报告引擎:内容寻址证据账本与封存版本 | |
177
- | **[dsh-score](https://github.com/PerryLink/dsh-score)** | DeepSeek Harness 插件的多维质量评分。 | |
178
- | **[dsh-session-pin](https://github.com/PerryLink/dsh-session-pin)** | 在 Web 侧栏置顶会话,带持久排序 | |
179
- | **[dsh-session-sync](https://github.com/PerryLink/dsh-session-sync)** | DeepSeek Harness 的跨设备会话同步——会话存储的专用 git 镜像。 | |
180
- | **[dsh-skill-pack-security](https://github.com/PerryLink/dsh-skill-pack-security)** | 安全审计技能包:密钥扫描、依赖与供应链审查 | |
181
- | **[dsh-talk](https://github.com/PerryLink/dsh-talk)** | DeepSeek Harness 的语音优先会话闭环:对它说,听它答。 | |
182
- | **[dsh-test-drive](https://github.com/PerryLink/dsh-test-drive)** | DeepSeek Harness 插件的隔离试装冒烟。 | |
183
- | **[dsh-ticktick](https://github.com/PerryLink/dsh-ticktick)** | TickTick/滴答清单任务桥接:会话头面板 + 11 个工具 |
184
- | **[dsh-translate](https://github.com/PerryLink/dsh-translate)** | DeepSeek Harness 的厂商参数翻译与确定性 JSON 修复。 | |
185
- | **[dsh-wechat](https://github.com/PerryLink/dsh-wechat)** | 微信 ↔ DSH 桥接(Tencent iLink 机器人):文本/图片/文件/语音,聊天内审批卡片 |
153
+ | **[dsh-auto-review](https://github.com/PerryLink/dsh-auto-review)** | Second-model auto-review on the approval chain, fail-closed by default | |
154
+ | **[dsh-autotier](https://github.com/PerryLink/dsh-autotier)** | Automatic strong/cheap model-tier routing with deterministic risk guards and a `/tier` command | |
155
+ | **[dsh-background-agents](https://github.com/PerryLink/dsh-background-agents)** | Durable background child agents with a Web UI sidebar, messaging and interrupt | |
156
+ | **[dsh-budget](https://github.com/PerryLink/dsh-budget)** | Cost governance for DeepSeek Harness: budgets, carbon, and latency in one panel. | |
157
+ | **[dsh-catalog](https://github.com/PerryLink/dsh-catalog)** | DSH Desktop Market standard catalog source for the PerryLink family | |
158
+ | **[dsh-cert-mcp](https://github.com/PerryLink/dsh-cert-mcp)** | Read-only MCP server exposing the certification registry: grades, snapshots and five-dimension evidence | |
159
+ | **[dsh-checkpoint-rewind](https://github.com/PerryLink/dsh-checkpoint-rewind)** | Claude Code /rewind-equivalent: snapshots, session forks, one-shot restore | |
160
+ | **[dsh-claude-move](https://github.com/PerryLink/dsh-claude-move)** | Migrate Claude Code sessions, memory, skills and CLAUDE.md into DSH | |
161
+ | **[dsh-click](https://github.com/PerryLink/dsh-click)** | Cross-platform native desktop control for DeepSeek Harness — Windows first. | |
162
+ | **[dsh-composer-history](https://github.com/PerryLink/dsh-composer-history)** | Terminal-style input history for the web composer: arrows, Ctrl+R search | |
163
+ | **[dsh-data-quality](https://github.com/PerryLink/dsh-data-quality)** | Dataset quality checks and citation cross-checks (the optional numeric bridge consumed here) | |
164
+ | **[dsh-defend](https://github.com/PerryLink/dsh-defend)** | Prompt-injection, jailbreak, and secret-leak defense for DeepSeek Harness. | |
165
+ | **[dsh-doublecheck](https://github.com/PerryLink/dsh-doublecheck)** | Engineering-discipline guard: requirements grill, test gates, adversary review | |
166
+ | **[dsh-draw](https://github.com/PerryLink/dsh-draw)** | Unified static-image generation routing for DeepSeek Harness. | |
167
+ | **[dsh-fast](https://github.com/PerryLink/dsh-fast)** | Read-only performance diagnostics for DeepSeek Harness. | |
168
+ | **[dsh-fund-research](https://github.com/PerryLink/dsh-fund-research)** | Deterministic research reports for Chinese public mutual funds | |
169
+ | **[dsh-github](https://github.com/PerryLink/dsh-github)** | GitHub PR/issues integration for DSH, every write gated by approval | |
170
+ | **[dsh-industry-research](https://github.com/PerryLink/dsh-industry-research)** | Industry research orchestration that seals its deliverables through this plugin's `ctx.researchReport.assemble` | |
171
+ | **[dsh-laya](https://github.com/PerryLink/dsh-laya)** | Laya typed decisions (`noul`/`choice`/`score`) as a first-class Cordis service and model-visible tools | |
172
+ | **[dsh-library](https://github.com/PerryLink/dsh-library)** | Local document knowledge base for DeepSeek Harness. | |
173
+ | **[dsh-local-ai](https://github.com/PerryLink/dsh-local-ai)** | Local-model (Ollama) integration for DeepSeek Harness. | |
174
+ | **[dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions)** | LSP diagnostics, formatting, completion, code actions and rename over language servers | |
175
+ | **[dsh-mask](https://github.com/PerryLink/dsh-mask)** | PII masking middleware: anonymize at the model boundary, restore at the display layer | |
176
+ | **[dsh-mcp-panel](https://github.com/PerryLink/dsh-mcp-panel)** | Read-only MCP runtime panel: /mcp command + Settings tab with status, tools and errors | |
177
+ | **[dsh-memento](https://github.com/PerryLink/dsh-memento)** | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool | |
178
+ | **[dsh-observe](https://github.com/PerryLink/dsh-observe)** | OpenTelemetry and Langfuse observability exporter for DeepSeek Harness. | |
179
+ | **[dsh-output-styles](https://github.com/PerryLink/dsh-output-styles)** | Claude Code outputStyles-equivalent runtime style switching | |
180
+ | **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | Claude Code-style declarative allow/deny/ask permission rules with audit | |
181
+ | **[dsh-plugin-certification](https://github.com/PerryLink/dsh-plugin-certification)** | Community certification registry with repro-checkable grades and badges | |
182
+ | **[dsh-plugin-doctor](https://github.com/PerryLink/dsh-plugin-doctor)** | Zero-dependency static + sandbox smoke detector for DSH plugins | |
183
+ | **[dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide)** | Plugin-development knowledge base as an on-demand agent skill | |
184
+ | **[dsh-plugin-kit](https://github.com/PerryLink/dsh-plugin-kit)** | Shared zero-runtime-dependency toolkit for the PerryLink DSH plugins | |
185
+ | **[dsh-plugin-upgrade](https://github.com/PerryLink/dsh-plugin-upgrade)** | One-package, one-corridor-index plugin upgrade skill: routes a repository to the matching closed corridor card | |
186
+ | **[dsh-plugin-upgrade-015](https://github.com/PerryLink/dsh-plugin-upgrade-015)** | Merged `0.1.3-alpha.1` → `0.1.5-rc.1` upgrade corridor card plus a zero-dependency seam scanner | |
187
+ | **[dsh-reach](https://github.com/PerryLink/dsh-reach)** | Multi-channel approval/question bridge: WeChat/Telegram/Feishu, session console | |
188
+ | **[dsh-research-report](https://github.com/PerryLink/dsh-research-report)** | Verifiable research-report engine: content-addressed evidence ledger and sealed versions | |
189
+ | **[dsh-score](https://github.com/PerryLink/dsh-score)** | Multi-dimensional quality scoring for DeepSeek Harness plugins. | |
190
+ | **[dsh-session-pin](https://github.com/PerryLink/dsh-session-pin)** | Pin sessions in the Web sidebar with durable ordering | |
191
+ | **[dsh-session-sync](https://github.com/PerryLink/dsh-session-sync)** | Cross-device session sync for DeepSeek Harness — a dedicated git mirror of your session store. | |
192
+ | **[dsh-skill-pack-security](https://github.com/PerryLink/dsh-skill-pack-security)** | Security-audit skill pack: secret scan, dependency and supply-chain review | |
193
+ | **[dsh-talk](https://github.com/PerryLink/dsh-talk)** | Voice-first session loop for DeepSeek Harness: talk to it, hear it answer. | |
194
+ | **[dsh-team-rooms](https://github.com/PerryLink/dsh-team-rooms)** | Cross-session team rooms: shared message bus, task board and timeline | |
195
+ | **[dsh-test-drive](https://github.com/PerryLink/dsh-test-drive)** | Isolated install-and-smoke test drives for DeepSeek Harness plugins. | |
196
+ | **[dsh-ticktick](https://github.com/PerryLink/dsh-ticktick)** | TickTick/Dida365 task bridge: session-header panel + 11 tools | |
197
+ | **[dsh-translate](https://github.com/PerryLink/dsh-translate)** | Vendor parameter translation and deterministic JSON repair for DeepSeek Harness. | |
198
+
186
199
 
187
200
  ## License
188
201
 
package/README.md CHANGED
@@ -3,6 +3,8 @@
3
3
  # 💰 dsh-budget
4
4
  - **1024 store channel**: `npm i -g dsh1024` once, then `dsh1024 plugin --profile web add dsh-budget` (counts toward the [deepseek1024.com](https://deepseek1024.com) install ranking).
5
5
  [![Gitee](https://img.shields.io/badge/Gitee-mirror-c71d23?logo=gitee)](https://gitee.com/perrylink/dsh-budget)
6
+ [![dshfind](https://dshfind.com/api/badge/PerryLink/dsh-budget?metric=downloads)](https://dshfind.com/plugins/PerryLink/dsh-budget?ref=badge)
7
+ [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/PerryLink/dsh-budget/badge)](https://api.securityscorecards.dev/projects/github.com/PerryLink/dsh-budget)
6
8
 
7
9
  **Cost governance for DeepSeek Harness: budgets, carbon, and latency in one panel.**
8
10
 
@@ -13,6 +15,7 @@
13
15
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
14
16
  [![DSH plugin](https://img.shields.io/badge/dsh--plugin-✅-green)](https://github.com/topics/dsh-plugin)
15
17
  [![dsh-doctor](https://raw.githubusercontent.com/PerryLink/dsh-plugin-doctor/main/badges/PerryLink__dsh-budget.svg)](https://github.com/PerryLink/dsh-plugin-doctor#verified-徽章)
18
+ [![DSH Market](https://raw.githubusercontent.com/2BingLing/dsh-market/master/assets/readme/badge-listed-en.svg)](https://dsh.market/)
16
19
  [![Node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-brightgreen.svg)](#)
17
20
  [![CI](https://img.shields.io/github/actions/workflow/status/PerryLink/dsh-budget/ci.yml?branch=main&label=CI)](https://github.com/PerryLink/dsh-budget/actions)
18
21
  [![Version](https://img.shields.io/github/v/tag/PerryLink/dsh-budget?label=version)](https://github.com/PerryLink/dsh-budget/releases)
@@ -29,7 +32,7 @@
29
32
 
30
33
  | Surface | Status |
31
34
  |---|---|
32
- | Harness | DeepSeek Harness `dsh-v0.1.5-rc.2` (GitHub tag, verified 2026-09-11; npm pin `0.1.5-rc.2` adapted 2026-09-10; peer range `>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0`): the session envelope keeps its ignorable field for stored-log read compatibility only - Session.append still cannot stamp it, so audit-gate behavior is unchanged. Verified 2026-09-11 against the dsh-v0.1.5-rc.2 master checkout (full local gate chain; the profile install smoke runs in the monthly Compat workflow). |
35
+ | Harness | DeepSeek Harness `dsh-v0.1.7-rc.1` (GitHub tag, adapted 2026-09-24; peer range `>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0 || >=0.1.7-0 <0.2.0`): the alpha.2 catalog prices are built into the price table and unknown models surface as unpriced instead of a fabricated estimate; the audit gate keeps suppressing `budget/alert`/`budget/block` appends (fail-closed session event vocabulary). Verified 2026-09-24 by the two-ruler typecheck chain and the full local gate; the browser-panel items stay 人工·未测即未完成 (maintainer manual checklist). |
33
36
 
34
37
  | Audit events | Written on harnesses before `0.1.2-rc.1`; suppressed with a logged degradation reason on `0.1.2-rc.1` and later (fail-closed session event vocabulary, no external registration surface) || Node | `^22.19.0 \|\| >=24.0.0` |
35
38
  | Surfaces | Host + Web client (Settings budget tab); `/budget` command |
@@ -74,7 +77,7 @@ All tunables are Schemastery `Config` fields (changeable from cordis.yml). `cord
74
77
  | Key | Default | Meaning |
75
78
  |---|---|---|
76
79
  | `prices` | `{}` | Per-model USD prices per 1M tokens, merged over the built-in table |
77
- | `defaultPrice` | `{input: 1.0, output: 3.0}` | Fallback for models absent from both tables |
80
+ | `defaultPrice` | unpriced signal (`priced: false`, zero numbers) | Fallback for models absent from both tables: the default contributes 0 to accounting and surfaces as "unpriced"; set numbers with `priced: true` to price unknown models explicitly |
78
81
  | `budgets.session` / `daily` / `monthly` | `10` / `50` / `500` | Budget caps in USD per scope; omit for unlimited |
79
82
  | `warnRatio` | `0.8` | Alert once usage reaches this fraction of a cap (0..1) |
80
83
  | `overLimit` | `alert` | `alert` / `block` / `degrade` after a cap is crossed |
@@ -126,7 +129,7 @@ All tunables are Schemastery `Config` fields (changeable from cordis.yml). `cord
126
129
  ```sh
127
130
  pnpm install # node ^22.19 || >=24
128
131
  pnpm run typecheck # tsc: src + tests against the local harness checkout
129
- pnpm run typecheck:ci # tsc against the published 0.1.5-rc.2 types (no paths)
132
+ pnpm run typecheck:ci # tsc against the published types (no paths)
130
133
  pnpm test # vitest
131
134
  pnpm run build # tsc declarations + tsdown bundles (lib/)
132
135
  pnpm run verify:self-contained # dependency specs resolve from the registry
@@ -144,12 +147,16 @@ pnpm pack # the published tarball
144
147
 
145
148
  ## PerryLink DSH Plugin Family
146
149
 
147
- This project is one of the [37 DeepSeek Harness plugins](https://github.com/PerryLink) maintained by [PerryLink](https://github.com/PerryLink). If this one helps you, the others likely will too:
150
+ This project is one of the **45 DeepSeek Harness plugins** maintained by [PerryLink](https://github.com/PerryLink). If this one helps you, the others likely will too:
148
151
 
149
152
  | Plugin | One-liner |
150
153
  |---|---|
151
154
  | **[dsh-auto-review](https://github.com/PerryLink/dsh-auto-review)** | Second-model auto-review on the approval chain, fail-closed by default | |
155
+ | **[dsh-autotier](https://github.com/PerryLink/dsh-autotier)** | Automatic strong/cheap model-tier routing with deterministic risk guards and a `/tier` command | |
152
156
  | **[dsh-background-agents](https://github.com/PerryLink/dsh-background-agents)** | Durable background child agents with a Web UI sidebar, messaging and interrupt | |
157
+ | **[dsh-budget](https://github.com/PerryLink/dsh-budget)** | Cost governance for DeepSeek Harness: budgets, carbon, and latency in one panel. | |
158
+ | **[dsh-catalog](https://github.com/PerryLink/dsh-catalog)** | DSH Desktop Market standard catalog source for the PerryLink family | |
159
+ | **[dsh-cert-mcp](https://github.com/PerryLink/dsh-cert-mcp)** | Read-only MCP server exposing the certification registry: grades, snapshots and five-dimension evidence | |
153
160
  | **[dsh-checkpoint-rewind](https://github.com/PerryLink/dsh-checkpoint-rewind)** | Claude Code /rewind-equivalent: snapshots, session forks, one-shot restore | |
154
161
  | **[dsh-claude-move](https://github.com/PerryLink/dsh-claude-move)** | Migrate Claude Code sessions, memory, skills and CLAUDE.md into DSH | |
155
162
  | **[dsh-click](https://github.com/PerryLink/dsh-click)** | Cross-platform native desktop control for DeepSeek Harness — Windows first. | |
@@ -162,6 +169,7 @@ This project is one of the [37 DeepSeek Harness plugins](https://github.com/Perr
162
169
  | **[dsh-fund-research](https://github.com/PerryLink/dsh-fund-research)** | Deterministic research reports for Chinese public mutual funds | |
163
170
  | **[dsh-github](https://github.com/PerryLink/dsh-github)** | GitHub PR/issues integration for DSH, every write gated by approval | |
164
171
  | **[dsh-industry-research](https://github.com/PerryLink/dsh-industry-research)** | Industry research orchestration that seals its deliverables through this plugin's `ctx.researchReport.assemble` | |
172
+ | **[dsh-laya](https://github.com/PerryLink/dsh-laya)** | Laya typed decisions (`noul`/`choice`/`score`) as a first-class Cordis service and model-visible tools | |
165
173
  | **[dsh-library](https://github.com/PerryLink/dsh-library)** | Local document knowledge base for DeepSeek Harness. | |
166
174
  | **[dsh-local-ai](https://github.com/PerryLink/dsh-local-ai)** | Local-model (Ollama) integration for DeepSeek Harness. | |
167
175
  | **[dsh-lsp-actions](https://github.com/PerryLink/dsh-lsp-actions)** | LSP diagnostics, formatting, completion, code actions and rename over language servers | |
@@ -171,19 +179,24 @@ This project is one of the [37 DeepSeek Harness plugins](https://github.com/Perr
171
179
  | **[dsh-observe](https://github.com/PerryLink/dsh-observe)** | OpenTelemetry and Langfuse observability exporter for DeepSeek Harness. | |
172
180
  | **[dsh-output-styles](https://github.com/PerryLink/dsh-output-styles)** | Claude Code outputStyles-equivalent runtime style switching | |
173
181
  | **[dsh-permission-rules](https://github.com/PerryLink/dsh-permission-rules)** | Claude Code-style declarative allow/deny/ask permission rules with audit | |
174
- | **[dsh-personal-directive](https://github.com/PerryLink/dsh-personal-directive)** | Personal directive injector with top-bar toggle (framework edition) |
182
+ | **[dsh-plugin-certification](https://github.com/PerryLink/dsh-plugin-certification)** | Community certification registry with repro-checkable grades and badges | |
183
+ | **[dsh-plugin-doctor](https://github.com/PerryLink/dsh-plugin-doctor)** | Zero-dependency static + sandbox smoke detector for DSH plugins | |
175
184
  | **[dsh-plugin-guide](https://github.com/PerryLink/dsh-plugin-guide)** | Plugin-development knowledge base as an on-demand agent skill | |
176
- | **[dsh-reach](https://github.com/PerryLink/dsh-reach)** | Multi-channel approval/question bridge: WeChat/Telegram/Feishu, session console |
185
+ | **[dsh-plugin-kit](https://github.com/PerryLink/dsh-plugin-kit)** | Shared zero-runtime-dependency toolkit for the PerryLink DSH plugins | |
186
+ | **[dsh-plugin-upgrade](https://github.com/PerryLink/dsh-plugin-upgrade)** | One-package, one-corridor-index plugin upgrade skill: routes a repository to the matching closed corridor card | |
187
+ | **[dsh-plugin-upgrade-015](https://github.com/PerryLink/dsh-plugin-upgrade-015)** | Merged `0.1.3-alpha.1` → `0.1.5-rc.1` upgrade corridor card plus a zero-dependency seam scanner | |
188
+ | **[dsh-reach](https://github.com/PerryLink/dsh-reach)** | Multi-channel approval/question bridge: WeChat/Telegram/Feishu, session console | |
177
189
  | **[dsh-research-report](https://github.com/PerryLink/dsh-research-report)** | Verifiable research-report engine: content-addressed evidence ledger and sealed versions | |
178
190
  | **[dsh-score](https://github.com/PerryLink/dsh-score)** | Multi-dimensional quality scoring for DeepSeek Harness plugins. | |
179
191
  | **[dsh-session-pin](https://github.com/PerryLink/dsh-session-pin)** | Pin sessions in the Web sidebar with durable ordering | |
180
192
  | **[dsh-session-sync](https://github.com/PerryLink/dsh-session-sync)** | Cross-device session sync for DeepSeek Harness — a dedicated git mirror of your session store. | |
181
193
  | **[dsh-skill-pack-security](https://github.com/PerryLink/dsh-skill-pack-security)** | Security-audit skill pack: secret scan, dependency and supply-chain review | |
182
194
  | **[dsh-talk](https://github.com/PerryLink/dsh-talk)** | Voice-first session loop for DeepSeek Harness: talk to it, hear it answer. | |
195
+ | **[dsh-team-rooms](https://github.com/PerryLink/dsh-team-rooms)** | Cross-session team rooms: shared message bus, task board and timeline | |
183
196
  | **[dsh-test-drive](https://github.com/PerryLink/dsh-test-drive)** | Isolated install-and-smoke test drives for DeepSeek Harness plugins. | |
184
- | **[dsh-ticktick](https://github.com/PerryLink/dsh-ticktick)** | TickTick/Dida365 task bridge: session-header panel + 11 tools |
197
+ | **[dsh-ticktick](https://github.com/PerryLink/dsh-ticktick)** | TickTick/Dida365 task bridge: session-header panel + 11 tools | |
185
198
  | **[dsh-translate](https://github.com/PerryLink/dsh-translate)** | Vendor parameter translation and deterministic JSON repair for DeepSeek Harness. | |
186
- | **[dsh-wechat](https://github.com/PerryLink/dsh-wechat)** | WeChat ↔ DSH bridge (Tencent iLink bot): text/image/file/voice, approvals in chat |
199
+
187
200
 
188
201
  ### Install from the DSH Desktop Market
189
202
 
package/lib/client.js CHANGED
@@ -30,8 +30,9 @@ window.__ModuleLoader__.load({
30
30
  //#region src/client/BudgetTab.tsx
31
31
  /** The budget settings tab: usage bars, model breakdown, alerts, cap editors, and unblock actions. */
32
32
  /** The budget tab body. */
33
- function BudgetTab({ status, setSettings, unblock, t }) {
33
+ function BudgetTab({ status, setSettings, unblock, sessionBound, t }) {
34
34
  const [state, setState] = (0, react.useState)({ status: "loading" });
35
+ const [bound, setBound] = (0, react.useState)(true);
35
36
  const [sessionCap, setSessionCap] = (0, react.useState)("");
36
37
  const [dailyCap, setDailyCap] = (0, react.useState)("");
37
38
  const [monthlyCap, setMonthlyCap] = (0, react.useState)("");
@@ -47,6 +48,7 @@ window.__ModuleLoader__.load({
47
48
  status: "ready",
48
49
  snapshot
49
50
  });
51
+ setBound(sessionBound());
50
52
  setSessionCap(snapshot.scopes.find((scope) => scope.scope === "session")?.capUsd?.toString() ?? "");
51
53
  setDailyCap(snapshot.scopes.find((scope) => scope.scope === "daily")?.capUsd?.toString() ?? "");
52
54
  setMonthlyCap(snapshot.scopes.find((scope) => scope.scope === "monthly")?.capUsd?.toString() ?? "");
@@ -142,6 +144,10 @@ window.__ModuleLoader__.load({
142
144
  className: "dbud-section",
143
145
  "data-dsh-budget": true,
144
146
  children: [
147
+ bound ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
148
+ className: "dbud-notice",
149
+ children: t("noSessionBound")
150
+ }),
145
151
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
146
152
  className: "dbud-rows",
147
153
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
@@ -243,7 +249,7 @@ window.__ModuleLoader__.load({
243
249
  ]
244
250
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
245
251
  className: "dbud-model-meta",
246
- children: `${formatMoney(snapshot, model.costUsd)} · ${model.inputTokens} in / ${model.outputTokens} out · ${t("latency")} ${model.latency.p50 === null ? "-" : `${model.latency.p50}ms`}`
252
+ children: `${model.priced === false ? t("unpriced") : formatMoney(snapshot, model.costUsd)} · ${model.inputTokens} in / ${model.outputTokens} out · ${t("latency")} ${model.latency.p50 === null ? "-" : `${model.latency.p50}ms`}`
247
253
  })] }, model.model))
248
254
  })]
249
255
  }),
@@ -388,6 +394,8 @@ window.__ModuleLoader__.load({
388
394
  save: "保存",
389
395
  saved: "已保存(会话内生效,重载后恢复 cordis.yml 配置)",
390
396
  degraded: "已降级至",
397
+ unpriced: "未定价",
398
+ noSessionBound: "未绑定当前会话:会话作用域用量以「未绑定」口径显示。",
391
399
  history: "最近告警",
392
400
  usageCurve: "用量曲线"
393
401
  };
@@ -425,6 +433,8 @@ window.__ModuleLoader__.load({
425
433
  save: "Save",
426
434
  saved: "Saved (session-scoped; a reload restores the cordis.yml values)",
427
435
  degraded: "Degraded to",
436
+ unpriced: "unpriced",
437
+ noSessionBound: "No current session bound: session-scope usage is shown as unbound.",
428
438
  history: "Recent alerts",
429
439
  usageCurve: "Usage curve"
430
440
  };
@@ -5458,6 +5468,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5458
5468
  *
5459
5469
  * @module dsh-budget/wire
5460
5470
  */
5471
+ /**
5472
+ * Strict wire codec carrying BOTH published and checkout faces: the
5473
+ * `schema` field feeds the npm-published 0.1.5-rc.2 line, `create` feeds the
5474
+ * checkout 0.1.6-alpha.1+ line (schemas materialize lazily on first use).
5475
+ * Built through a variable, so neither typecheck ruler flags the other
5476
+ * face's field as excess.
5477
+ */
5478
+ function strictWire(typeSymbol, schema) {
5479
+ return Object.freeze({
5480
+ mode: "strict",
5481
+ typeSymbol,
5482
+ schema,
5483
+ create: () => schema
5484
+ });
5485
+ }
5461
5486
  /** The scopes a budget cap applies to. */
5462
5487
  const BUDGET_SCOPES = [
5463
5488
  "session",
@@ -5487,7 +5512,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5487
5512
  p95: number().int().nullable(),
5488
5513
  max: number().int().nullable(),
5489
5514
  samples: number().int()
5490
- })
5515
+ }),
5516
+ priced: boolean()
5491
5517
  })),
5492
5518
  alerts: array(object({
5493
5519
  scope: _enum(BUDGET_SCOPES),
@@ -5535,18 +5561,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5535
5561
  name: "sessionId",
5536
5562
  wire: "sessionId",
5537
5563
  source: "json",
5538
- codec: Object.freeze({
5539
- mode: "strict",
5540
- typeSymbol: "dsh-budget/types#SessionId",
5541
- schema: BUDGET_SESSION_ID_SCHEMA
5542
- }),
5564
+ codec: strictWire("dsh-budget/types#SessionId", BUDGET_SESSION_ID_SCHEMA),
5543
5565
  acceptsUndefined: true
5544
5566
  })]),
5545
- result: Object.freeze({
5546
- mode: "strict",
5547
- typeSymbol: "dsh-budget/types#BudgetStatus",
5548
- schema: BUDGET_STATUS_SCHEMA
5549
- }),
5567
+ result: strictWire("dsh-budget/types#BudgetStatus", BUDGET_STATUS_SCHEMA),
5550
5568
  sourceLocation: Object.freeze({
5551
5569
  file: "src/wire.ts",
5552
5570
  line: 1,
@@ -5575,17 +5593,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5575
5593
  name: "settingsJson",
5576
5594
  wire: "settingsJson",
5577
5595
  source: "json",
5578
- codec: Object.freeze({
5579
- mode: "strict",
5580
- typeSymbol: "dsh-budget/types#BudgetSettingsJson",
5581
- schema: string()
5582
- })
5596
+ codec: strictWire("dsh-budget/types#BudgetSettingsJson", string())
5583
5597
  })]),
5584
- result: Object.freeze({
5585
- mode: "strict",
5586
- typeSymbol: "dsh-budget/types#BudgetStatus",
5587
- schema: BUDGET_STATUS_SCHEMA
5588
- }),
5598
+ result: strictWire("dsh-budget/types#BudgetStatus", BUDGET_STATUS_SCHEMA),
5589
5599
  sourceLocation: Object.freeze({
5590
5600
  file: "src/wire.ts",
5591
5601
  line: 1,
@@ -5608,17 +5618,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5608
5618
  name: "scope",
5609
5619
  wire: "scope",
5610
5620
  source: "json",
5611
- codec: Object.freeze({
5612
- mode: "strict",
5613
- typeSymbol: "dsh-budget/types#BudgetUnblockScope",
5614
- schema: BUDGET_UNBLOCK_SCOPE_SCHEMA
5615
- })
5621
+ codec: strictWire("dsh-budget/types#BudgetUnblockScope", BUDGET_UNBLOCK_SCOPE_SCHEMA)
5616
5622
  })]),
5617
- result: Object.freeze({
5618
- mode: "strict",
5619
- typeSymbol: "dsh-budget/types#BudgetStatus",
5620
- schema: BUDGET_STATUS_SCHEMA
5621
- }),
5623
+ result: strictWire("dsh-budget/types#BudgetStatus", BUDGET_STATUS_SCHEMA),
5622
5624
  sourceLocation: Object.freeze({
5623
5625
  file: "src/wire.ts",
5624
5626
  line: 1,
@@ -5655,7 +5657,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5655
5657
  */
5656
5658
  /** One `<style>` installation; returns the exact disposer that removes it. */
5657
5659
  function installBudgetStyles() {
5658
- if (document.querySelector("style[data-dsh-budget]") !== null) return () => {};
5660
+ const stale = document.querySelector("style[data-dsh-budget]");
5661
+ if (stale !== null) stale.remove();
5659
5662
  const element = document.createElement("style");
5660
5663
  element.dataset.dshBudget = "";
5661
5664
  element.textContent = BUDGET_CSS;
@@ -5908,6 +5911,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5908
5911
  const status = async () => unwrap(await scope.remote.budget.status(currentSessionId(scope.get("sessions"))), "status");
5909
5912
  const setSettings = async (settingsJson) => unwrap(await scope.remote.budget.setSettings(settingsJson), "setSettings");
5910
5913
  const unblock = async (scopeName) => unwrap(await scope.remote.budget.unblock(scopeName), "unblock");
5914
+ const sessionBound = () => currentSessionId(scope.get("sessions")) !== void 0;
5911
5915
  const slots = scope.get("slots");
5912
5916
  slots.inject("settings.plugins.tab", () => slots.register({
5913
5917
  name: "settings.plugins.tab",
@@ -5918,23 +5922,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5918
5922
  inject: () => ({
5919
5923
  status,
5920
5924
  setSettings,
5921
- unblock
5925
+ unblock,
5926
+ sessionBound
5922
5927
  })
5923
5928
  }, BudgetTab));
5924
5929
  });
5925
5930
  }
5926
5931
  /**
5927
- * Read the current session id from the sessions store face (structural:
5928
- * the store shape differs across harness lines, so only the leaf is read).
5932
+ * Read the current (main-view) session id from the sessions store face
5933
+ * (structural, so it survives both harness lines): the deleted
5934
+ * `SessionListState.current` leaf is replaced by the first session whose
5935
+ * `retainedBy.mainView` is positive, mirroring the upstream ui-session
5936
+ * main-binding derivation. Returns undefined when the face is absent — the
5937
+ * panel then degrades visibly instead of silently attributing usage to "".
5929
5938
  */
5930
5939
  function currentSessionId(sessions) {
5931
5940
  try {
5932
- const list = sessions?.list;
5941
+ const face = sessions;
5942
+ if (typeof face !== "object" || face === null) return void 0;
5943
+ const list = face.list;
5933
5944
  if (typeof list !== "object" || list === null) return void 0;
5934
5945
  const getSnapshot = list.getSnapshot;
5935
5946
  if (typeof getSnapshot !== "function") return void 0;
5936
- const current = getSnapshot().current;
5937
- return typeof current === "string" ? current : void 0;
5947
+ const byId = getSnapshot().byId;
5948
+ if (typeof byId !== "object" || byId === null) return void 0;
5949
+ return Object.entries(byId).find(([, row]) => (row?.retainedBy?.mainView ?? 0) > 0)?.[0];
5938
5950
  } catch {
5939
5951
  return;
5940
5952
  }