dsh-plugin-workspace-spend 0.0.0-stage → 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dsh-plugin-workspace-spend contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/PUBLISHING.md ADDED
@@ -0,0 +1,85 @@
1
+ # 发布到开源社区
2
+
3
+ 这是一份发布清单。插件本身**没有构建步骤**、没有运行时依赖,发布就是把当前目录原样推到 npm / Git 仓库。
4
+
5
+ ## 发布前检查
6
+
7
+ - [x] `package.json` 无 `private: true`,`name = dsh-plugin-workspace-spend`(npm 上当前可用)
8
+ - [x] `license: MIT` + `LICENSE` 文件
9
+ - [x] `engines.dsh: ">=0.2.1-rc.5"`(Plugin Manager 的版本兼容检查会读它)
10
+ - [x] `dsh.bundle.patch` 与 `dsh.client`(`platform: web`、`immediately: true`)
11
+ - [x] `exports` 暴露 `./client`、`./locale/*.json`、`./icon`
12
+ - [x] 图标、中英 locale 元数据(插件页显示标题与描述)
13
+ - [x] `npm test` / `npm run check` 通过
14
+ - [x] 仓库内没有个人路径、密钥、会话内容;`tools/verify-real-logs.mjs` 只读本机 `~/.dsh`
15
+ - [ ] 按需补 `author`、`repository`、`homepage`、`bugs` 字段(在 npm 发布前或之后都可补)
16
+
17
+ ## 首次发布(npm)
18
+
19
+ 先确认 npm 指向的 registry:本机若配置了国内镜像(`npm config get registry` 返回 `https://registry.npmmirror.com` 之类),镜像**只能读、不能发**,发布时必须显式指定 npm 官方 registry。
20
+
21
+ ```sh
22
+ cd /path/to/dsh-plugin-workspace-spend
23
+
24
+ # 1. 预览将发布哪些文件(不会真的上传)
25
+ npm pack --dry-run
26
+
27
+ # 2. 登录 npm 官方 registry(浏览器完成一次授权)
28
+ npm login --registry https://registry.npmjs.org
29
+
30
+ # 3. 发布(unscoped 包默认 public)
31
+ npm publish --registry https://registry.npmjs.org --access public
32
+ ```
33
+
34
+ 发布后用户即可:
35
+
36
+ ```sh
37
+ dsh plugin add dsh-plugin-workspace-spend
38
+ ```
39
+
40
+ 或在 Web 的 **Plugins → Add plugin** 里填 `dsh-plugin-workspace-spend`。
41
+
42
+ ## 同时放到 GitHub(推荐)
43
+
44
+ 仓库地址:`git@github.com:MikaZou/dsh-plugin-workspace-spend.git`
45
+
46
+ ```sh
47
+ git remote add origin git@github.com:MikaZou/dsh-plugin-workspace-spend.git
48
+ git push -u origin main
49
+ ```
50
+
51
+ 然后:
52
+
53
+ 1. `package.json` 已补好 `repository` / `homepage` / `bugs`(指向 MikaZou/dsh-plugin-workspace-spend)。
54
+ 2. 用户也可以直接从 Git 安装:`dsh plugin add github:MikaZou/dsh-plugin-workspace-spend`。
55
+ 3. 打 tag / 发 Release:`git tag v1.0.0 && git push --tags`。
56
+
57
+ ## 升级发布
58
+
59
+ ```sh
60
+ npm version patch # 或 minor / major,自动改 package.json 并打 tag
61
+ npm test
62
+ npm run check
63
+ npm publish
64
+ ```
65
+
66
+ 用户侧在 Plugins 页点 **Update**,或重新 `dsh plugin add dsh-plugin-workspace-spend@<version>`。
67
+
68
+ ## 版本兼容策略
69
+
70
+ - `engines.dsh` 表示测试过的 DSH 范围;DSH 升级后如果接口变化,先在新版本上跑一遍 `npm test` 和 `node tools/verify-real-logs.mjs`,再放宽/收紧范围。
71
+ - 若 DSH 的兼容检查拒绝某个较新的**预发布**版本(SemVer 对 prerelease 的范围匹配较严格),用户可以临时用插件页的版本豁免(`allow-version`),但建议尽快发布一个更新了 `engines.dsh` 的版本。
72
+ - 不要放宽到你没有测过的版本上——Host 半边直接跑在 Harness 进程里。
73
+
74
+ ## 其他分发方式
75
+
76
+ - **tarball**:`npm pack` 生成 `dsh-plugin-workspace-spend-1.0.0.tgz`,用户 `dsh plugin add ./<file>.tgz`。
77
+ - **私有 registry / 镜像**:`dsh plugin add` 支持配置 registry 与 fallback 镜像,安装时按顺序查找。
78
+ - **本地目录**:`dsh plugin add /abs/path/to/dsh-plugin-workspace-spend`(开发调试用,`link:` 方式)。
79
+ - **桌面版**:Desktop 的包操作由 Desktop shell 负责;Web 侧栏 Plugins 页的安装入口同样可用。
80
+
81
+ ## 发布后自检
82
+
83
+ 1. 在一个干净 profile 里安装:`dsh plugin add dsh-plugin-workspace-spend`。
84
+ 2. 打开设置确认出现「支出统计」,数字非空、刷新与时间范围切换正常。
85
+ 3. 卸载再装一次,确认无残留路由与页面(`GET /api/workspace-spend` 在卸载后应 404/不可达)。
package/README.md CHANGED
@@ -1,3 +1,183 @@
1
- # Temporary Holding Version
1
+ # dsh-plugin-workspace-spend
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ 按 **工作区** 统计 DeepSeek Harness(dsh)的模型调用花费:读取会话日志里的 Token 用量,按可配置的价格表估算金额,并在 **设置 → 支出统计** 提供一页看板。
4
+
5
+ Estimated model spend per workspace for DeepSeek Harness: token usage is folded from durable session logs, priced with a configurable price table (peak / off-peak), and shown on a **Spend** page in Settings.
6
+
7
+ - 适用版本 / Requires dsh:`>=0.2.1-rc.5`(`engines.dsh`)
8
+ - 许可证 / License:MIT
9
+ - 无构建步骤、无运行时依赖、无网络请求;Host 代码在本机进程内运行,只读本地日志。
10
+
11
+ ## 功能
12
+
13
+ - **按工作区**:用 `workspaceRegistry` 的会话索引归属会话;未注册目录的会话按 cwd 单独成组并标注「未归入工作区」。
14
+ - **按时间**:全部 / 近 30 天 / 近 7 天 / 今天(按北京时间自然日切分)。
15
+ - **按模型**:每个工作区列出模型与对应金额;下方有全局「按模型」汇总。
16
+ - **计费口径**:区分缓存命中输入 / 缓存未命中输入 / 缓存写 / 输出;重试的每次计费尝试分别累计;压缩摘要请求单独计价;fork/seed 会话继承的前缀不重复计费。
17
+ - **峰谷价**:默认使用 DeepSeek 官方公开价(人民币/百万 tokens),高峰时段(北京时间工作日 9:00–12:00、14:00–18:00)用峰值价,其余时间按可配置折扣(默认 0.5 倍)计费。
18
+ - **可配置**:价格表、货币、折扣、节假日、按次计费的搜索/抓取工具都能在 profile 的 `cordis.patch.yml` 里改。
19
+ - 中英双语界面,浅色/深色主题跟随 Harness。
20
+
21
+ ## 安装
22
+
23
+ ### 从 npm(发布后)
24
+
25
+ ```sh
26
+ dsh plugin add dsh-plugin-workspace-spend
27
+ ```
28
+
29
+ 或在 Harness 的 **Plugins → Add plugin** 里填包名 `dsh-plugin-workspace-spend`。
30
+
31
+ ### 从 Git 仓库
32
+
33
+ ```sh
34
+ dsh plugin add github:MikaZou/dsh-plugin-workspace-spend
35
+ ```
36
+
37
+ 或:
38
+
39
+ ```sh
40
+ git clone git@github.com:MikaZou/dsh-plugin-workspace-spend.git
41
+ dsh plugin add ./dsh-plugin-workspace-spend
42
+ ```
43
+
44
+ ### 从本地目录或 tarball
45
+
46
+ ```sh
47
+ # 本地目录(开发时)
48
+ dsh plugin add "/path/to/dsh-plugin-workspace-spend"
49
+
50
+ # 或先打包再安装
51
+ npm pack
52
+ dsh plugin add ./dsh-plugin-workspace-spend-1.0.0.tgz
53
+ ```
54
+
55
+ 安装后 Host 行立即生效;浏览器侧通过 HMR 加载 Client 模块。如果设置面板里暂时没看到,刷新一次页面。打开 **设置 →「支出统计」** 即可。
56
+
57
+ 卸载:在 Plugins 页移除,或 `dsh plugin remove dsh-plugin-workspace-spend`。
58
+
59
+ > 第一次打开页面会回放本机全部历史会话日志(当前机器 90+ 会话约 2–3 秒),之后只增量读取变化的会话。
60
+
61
+ ## 数据口径
62
+
63
+ | 计入 | 说明 |
64
+ |---|---|
65
+ | 模型请求的输入 / 缓存命中 / 缓存写 / 输出 Token | 来自会话日志中 provider 上报的 usage |
66
+ | 重试尝试(`llm/retry-started`) | 每次计费尝试分别累计;同一 (turn, step) 的流式样本会被最终样本替换,不会重复 |
67
+ | 压缩(compaction)摘要请求 | `compaction/summary` 事件带 provider/model 与 usage,单独计价 |
68
+ | fork/seed 会话的继承前缀 | **跳过**,避免与源会话重复计费 |
69
+
70
+ 不计入:
71
+
72
+ - 自动生成会话标题等不记录 usage 的模型调用;
73
+ - 图片/文件附件的单独计费(只按 token 用量算);
74
+ - 网页搜索 / 抓取(Search/Fetch)的按次费用——默认关闭,可在 `perCallFees` 里开启;
75
+ - 赠送余额、免费额度、失败请求退费。
76
+
77
+ 页面数字是**估算**,不是账单。
78
+
79
+ ### 与平台账单对账
80
+
81
+ - **平台「用量信息」页有延迟**(官方标注 5 分钟,实测常更久),而本页是实时读取本地会话日志的。因此同一时刻两边数字不同很正常——请对齐**同一时间点**再比。
82
+ - 实测例子:DeepSeek 平台显示「今天 115 次请求 / ¥1.13」时,本机日志累计到第 115 次请求的估算恰好是 **¥1.12–1.13**;之后会话继续运行到 178 次请求,页面变成 ¥1.86,而平台页面还没刷新。所以看起来「对不上」,其实只是截止时间不同。
83
+ - 平台卡片里的 **Tokens** 与本地日志求和口径不完全一致(缓存命中/未命中的归类、失败请求是否计入、按时间桶聚合),以平台账单为准;金额在相同时间窗口内应当接近。
84
+ - 价格表里**列出的模型只是「已配置的单价」**,不代表本机使用过(例如默认表里有 `deepseek-v4-pro`,没用它就不会产生任何金额)。页面会给每行价格标注「本机已使用 / 未使用」,实际用量只出现在「按模型」汇总里。
85
+
86
+ ## 默认价格表
87
+
88
+ 默认按 DeepSeek 官方 API 文档的**高峰价**(人民币 / 百万 tokens),取自
89
+ <https://api-docs.deepseek.com/zh-cn/quick_start/pricing/>(2026-11):
90
+
91
+ | 模型 | 输入(缓存未命中) | 输入(缓存命中) | 输出 |
92
+ |---|---|---|---|
93
+ | `deepseek-flash` | 2 | 0.04 | 8 |
94
+ | `deepseek-v4-pro` | 9 | 0.30 | 27 |
95
+
96
+ - 高峰时段:北京时间周一至周五 09:00–12:00、14:00–18:00;其余时间(含周末)按 `offPeakDiscount`(默认 0.5 倍)计费。
97
+ - 法定节假日默认未内置(`holidays: []`);需要精确时把日期加进配置。
98
+ - 退役模型名 `deepseek-v4-flash`、`deepseek-v4-flash-vision-exp` 通过 `modelAliases` 映射到 `deepseek-flash`。
99
+ - 使用其他 provider/模型时,把对应价格加进 `prices`(键可以是模型名或 `provider/model`);未配置价格的模型:Token 照常统计、金额按 0 计,页面会提示。
100
+
101
+ ## 配置
102
+
103
+ 默认值在 `lib/spend.js` 的 `DEFAULT_CONFIG`;用户配置写在 **profile 的 `cordis.patch.yml`**,覆盖 `workspace-spend` 行(未写字段与默认表逐字段合并)。例如:
104
+
105
+ ```yaml
106
+ - id: workspace-spend
107
+ config:
108
+ currency: CNY
109
+ currencySymbol: "¥"
110
+ offPeakDiscount: 0.5
111
+ prices:
112
+ deepseek-flash:
113
+ input: 2
114
+ cacheRead: 0.04
115
+ cacheWrite: 0
116
+ output: 8
117
+ deepseek-v4-pro:
118
+ input: 9
119
+ cacheRead: 0.3
120
+ cacheWrite: 0
121
+ output: 27
122
+ # 其他 provider/模型:
123
+ # "openrouter/deepseek-chat": { input: 1, cacheRead: 0.1, output: 2 }
124
+ modelAliases:
125
+ deepseek-v4-flash: deepseek-flash
126
+ deepseek-v4-flash-vision-exp: deepseek-flash
127
+ holidays:
128
+ - "2026-10-01"
129
+ trackCompaction: true
130
+ # 可选:按次计费的搜索/抓取工具(单位同 currency,每次成功调用)
131
+ perCallFees:
132
+ web_search: 0.005
133
+ web_fetch: 0.005
134
+ ```
135
+
136
+ ## 隐私与安全
137
+
138
+ - **完全本地**:Host 半边只读本机会话日志(`sessionPersistence` / `workspaceRegistry`),只做计算,不发网络请求、不上报遥测;页面数据来自 `GET /api/workspace-spend`,该路由走 Harness 的浏览器 cookie 鉴权(未鉴权返回 401)。
139
+ - 插件不写 profile 配置、不改会话日志、不注入消息、不注册模型可见工具。
140
+ - 页面上只出现工作区名称/路径与聚合金额,不含提示词或会话内容。
141
+ - `tools/verify-real-logs.mjs` 是可选的自测脚本,默认读 `~/.dsh`,只在本地运行。
142
+
143
+ ## 兼容性
144
+
145
+ - 在 dsh `0.2.1-rc.5`(desktop profile)上开发与验证;`package.json` 声明 `engines.dsh: ">=0.2.1-rc.5"`。
146
+ - 如果 Harness 的版本兼容检查拒绝了较新的预发布版本,可以等插件更新范围,或用插件页的版本豁免(`allow-version`)在自担风险下安装。
147
+ - Host 服务名与浏览器 Slot 名来自 DSH 公共扩展点;若未来 DSH 调整这些契约,插件需要跟随更新。
148
+
149
+ ## 开发与验证
150
+
151
+ ```sh
152
+ npm test # node test/spend.test.mjs
153
+ npm run check # node --check index.js client.js lib/spend.js
154
+ node tools/verify-real-logs.mjs # 对照本机真实日志与 tokenUsage 投影的独立复核
155
+ ```
156
+
157
+ - `test/spend.test.mjs` 覆盖峰谷计价、缓存价、重试/替换、fork 前缀、压缩、模型别名、区间过滤、工作区路径归属、按次费用等。
158
+ - `tools/verify-real-logs.mjs` 解码本机会话日志,用同一份 `lib/spend.js` 折叠后与 Harness 持久化的 `tokenUsage` 投影逐会话比对;实测 90/92 个历史会话的 Token 总量完全一致,剩余 2 个是仍在写入的实时会话(缓存落后于日志)。
159
+ - 端到端实测:`sessionPersistence` 扫描 92 个历史会话、0 失败;Host 行与 `settings.section` 注册均 active。
160
+
161
+ ## 已知限制
162
+
163
+ - 金额是按配置价格计算的**估算**,不是账单;DeepSeek 价格与峰谷规则可能调整。
164
+ - 峰谷判定使用事件写入时间(请求结束附近),跨越峰谷边界的超长请求会有几分钟误差。
165
+ - 时间范围按北京时间自然日切分;其他时区用户的「今天」按北京时间计算。
166
+ - 首次加载需要回放全部历史日志;日志特别多时首次加载会慢一些。
167
+ - 卸载后统计不落盘(每次从日志重算)。
168
+
169
+ ## 实现
170
+
171
+ ```
172
+ package.json # dsh.bundle.patch + dsh.client(platform: web, immediately)
173
+ cordis.patch.yml # insert: workspace-spend → dsh-plugin-workspace-spend
174
+ index.js # Host:读 sessionPersistence + workspaceRegistry,注册 GET /api/workspace-spend
175
+ lib/spend.js # 纯函数:会话事件折叠、价格解析、区间聚合
176
+ client.js # 浏览器:settings.section 页面
177
+ test/spend.test.mjs # 单元测试
178
+ tools/verify-real-logs.mjs # 对照真实日志的复核脚本
179
+ ```
180
+
181
+ ## License
182
+
183
+ [MIT](LICENSE)