deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
DeepSeek Harness 费用与余额插件:定时拉取官方定价、缓存感知的会话/消息级费用估算(峰谷定价兼容),以及账户余额查询。
api-docs.deepseek.com/zh-cn/quick_start/pricing/),解析后写入 $DSH_HOME/prices/official-prices.json;失败时保留旧价格并记录错误。peakPricing: on/off 强制开启/关闭。GET https://api.deepseek.com/user/balance 查询账户余额,凭证复用 DSH 凭证服务里的 DEEPSEEK_API_KEY(web「设置 → 模型」页写入的那个),API key 只在 host 端使用,不会下发到浏览器。conversation.composer.dock,悬停显示分模型明细)、设置页「费用与余额」面板(余额卡片 + 跨会话费用汇总 + 当前/峰谷价格表)。# 1. 安装到 web profile(已发布到 npm,直接用包名;本地开发可改用 link: 指向本地目录)
dsh plugin --profile web add dsh-my-cost
# 2. 在 ~/.dsh/profiles/web/cordis.patch.yml 追加:
# - insert:
# - id: my-cost
# name: 'dsh-my-cost'
# config:
# currency: CNY # 显示币种
# pollIntervalMs: 3600000 # 价格轮询周期(默认 1 小时)
# balanceIntervalMs: 3600000 # 余额刷新周期
# peakPricing: auto # auto | on | off
# 3. 重启 dsh web,浏览器硬刷新
说明:也可以从 GitHub 源码安装:
dsh plugin --profile web add github:hehe1111/dsh-my-cost。lib/为构建产物(不入 git),git 安装会触发prepare构建脚本;pnpm ≥10 默认拦截 git 依赖的 prepare,需按 dsh 提示把dsh-my-cost加入 profile 的pnpm-workspace.yamlallowBuilds(key 含冒号,写入时加引号)后重装。推荐直接用 npm 包安装(发布时已构建)。
lib/ 是纯构建产物(.gitignore 忽略、不入库):src/(host 端,Node)与 client/
(浏览器端,React 19 + JSX)经 Vite 8(编程式构建脚本)产出 lib/index.js 与
lib/client.js。prepare 脚本会在 npm install/npm publish 时自动构建:
npm install # 安装 devDependencies(vite ^8、vitest ^4、@deepseek-ai/schemastery;react/react-dom 运行时由 dsh 的 seed 词表提供,不声明)
npm run build # node scripts/build.mjs → 构建 host + client 两个目标到 lib/
npm test # vitest:单测(定价核心/投影/格式化/组件渲染)+ 集成(apply 接线、/my-cost/status 路由)+ 构建产物契约
lib/index.js(ESM):src/ 源码,zod/@deepseek-ai/schemastery/node:* 保持
external(由 profile pnpm 闭包注入)。lib/client.js(CJS):符合 DSH 官方 client 契约——
window.__ModuleLoader__.load({ id, factory }) 包装,react/react/jsx-runtime/
react-dom/react-dom/client 为平台 seed 词、不打进包(低余额 toast 用 createRoot
渲染在插槽之外的独立容器)。client/styles/,渲染为 style={{...}})。
为什么必须这样、官方怎么写、限制在哪,见下方「样式编写」小节。client/ 或 src/ 源码 → 重新 npm run build:client 改动重装 + 刷新页面即可;
host(src/)改动需重启 web(ESM 缓存)。限制(硬约束,实测确认)
/plugins/<id>/client.js
(+ .map),浏览器加载不到任何独立 .css 文件。Vite lib 模式遇到 CSS 导入必然提取成
独立 .css(cssCodeSplit: false 也不内联)——所以 Less/CSS Modules/Tailwind/UnoCSS 的
默认产物在这里会静默丢失样式。references/gotchas.md
第 4 条):宿主全局 CSS 可能覆盖插件注入的 <style> 规则或命中同名 class;关键样式必须
用 JS 内联 style 属性(内联优先级最高,宿主无法覆盖),不要依赖 CSS class 注入。原因
style 属性无法被覆盖;官方写法
<style> 标签,例如
const css$9 = ".lXshSW_root{...}" + document.createElement("style") + data-plugin-css
去重标记;client-modules 的 claimStyles() 跟踪这些标签,插件卸载时自动清理。本插件写法
client/styles/*.js 定义样式对象,组件以 style={{...}}
渲染;不注入任何 <style> 标签、零 CSS 工具链、零额外依赖。<style>),
因"class 可被宿主覆盖 + 额外工具链 + preflight 风险"最终回归纯内联。{ ...baseStyle, color: xxx } 在组件内合并。结论:除非未来出现官方的 CSS 资源通道,否则新样式一律写成
client/styles/里的样式对象 并用style={{...}}内联,不要引入 CSS 文件、class 体系或工具类框架。
| 字段 | 默认 | 说明 |
|---|---|---|
currency |
CNY |
显示币种 |
pricesDir |
$DSH_HOME/prices |
价格文件目录 |
pricesUrl |
官方定价页 | 轮询源 |
balanceUrl |
https://api.deepseek.com/user/balance |
余额 API |
apiKeyRef |
DEEPSEEK_API_KEY |
凭证引用(走 ctx.credentials) |
pollIntervalMs |
3600000 |
价格轮询周期(最小 60s) |
balanceIntervalMs |
3600000 |
余额自动刷新周期 |
balanceCacheMs |
300000 |
余额缓存时长(?refreshBalance=1 可强制) |
peakPricing |
auto |
auto:生效日之后自动启用峰谷;on/off 强制 |
价格覆盖:$DSH_HOME/prices/local-prices.json(可选)可覆盖官方价,格式:
{ "prices": { "deepseek-v4-flash": { "inputPerM": 1.5, "outputPerM": 3, "cacheReadPerM": 0.03 } } }
GET /my-cost/status[?refreshBalance=1]:返回当前合并价格、峰谷时段/生效状态、以及(缓存的)账户余额。仅绑定在本机 dsh web 服务上。
dsh-my-cost/
├── package.json # 包元数据:入口/exports、dsh.client 声明、构建脚本、peerDependencies
├── README.md # 本文档
├── LICENSE # MIT 许可
├── .gitignore # 忽略 node_modules/、.temp/ 等
│
├── scripts/
│ └── build.mjs # Vite 构建脚本:src/ → lib/index.js(Node ESM),client/ → lib/client.js
│
├── src/ # 【host 端】Node 侧源码(纯 ESM,无中间产物)
│ ├── index.js # host 插件入口:注册 myCost 会话费用统计、每小时价格轮询、
│ │ # GET /my-cost/status 路由、余额查询(凭证走 ctx.credentials,key 不下发)
│ └── pricing-core.js # 定价纯函数核心:官方定价页解析、峰谷计价、costOf 费用计算、默认价表
│
├── client/ # 【浏览器端】React 19 + JSX 源码
│ ├── index.jsx # 浏览器插件入口:apply(ctx) 注册字典、3 个插槽、低余额轮询
│ ├── toast.jsx # 低余额 toast:React 组件 + createRoot 挂载(渲染在插槽之外)
│ ├── status.js # useStatus 钩子(拉 /my-cost/status)+ 低余额轮询逻辑
│ ├── format.js # 金额/token/时间/价格格式化纯函数
│ ├── locales.js # myCost 命名空间的中英文案
│ ├── components/ # 三个插槽组件
│ │ ├── MessageCost.jsx # 每条消息的估算费用 chip(conversation.chat.assistant-actions)
│ │ ├── SessionCostLine.jsx # 输入框底部信息栏:会话总花费 + 跨会话总计 + 余额(composer.dock)
│ │ └── MyCostSection.jsx # 设置页「费用与余额」面板(settings.section)
│ └── styles/ # 内联样式对象(无 .css 文件,见「样式编写」小节)
│ ├── section.js # MyCostSection 的样式对象
│ ├── dock.js # SessionCostLine 的样式对象
│ ├── message.js # MessageCost 的样式对象
│ └── toast.js # 低余额 toast 的样式对象
│
└── lib/ # 【构建产物】Vite 输出(.gitignore,不入 git;npm 发布时由 prepare 构建)
├── index.js # host bundle(Node ESM;zod/官方包/node:* 为 external)
└── client.js # 浏览器 bundle(CJS + window.__ModuleLoader__.load 包装)
补充说明("会话投影"是什么):dsh 有个叫 session projection(会话投影) 的机制——框架把 每个会话的 token 用量事件依次回放给插件的统计逻辑,插件累计后产出费用数据,界面再用
useProjection("myCost")读取。插件本身不用存数据,投影值会随会话持久化。
交互式架构图(由 Archify 生成):
flowchart LR
subgraph ext["外网"]
pp["DeepSeek 定价页<br/>api-docs.deepseek.com"]
ba["DeepSeek 余额 API<br/>api.deepseek.com/user/balance"]
end
subgraph host["Host(Node)"]
runtime["DSH 框架运行时<br/>webServer · credentials · timer · 投影重放"]
plugin["myCost Host 插件<br/>src/index.js"]
core["定价核心<br/>src/pricing-core.js"]
prices["$DSH_HOME/prices<br/>official/local JSON"]
sessions["DSH 会话存储<br/>事件日志 + 投影值"]
end
subgraph browser["Browser(Web)"]
shell["dsh Web Shell<br/>seed 词表 · __ModuleLoader__"]
client["myCost Client 插件<br/>client/ · 3 插槽 + toast"]
end
plugin -->|"每小时抓取"| pp
plugin -->|"GET /user/balance · Bearer key"| ba
plugin -->|"解析 / 计价"| core
plugin -->|"写 JSON"| prices
plugin -.->|"注册投影"| runtime
runtime -->|"回放用量事件"| plugin
runtime -->|"持久化"| sessions
client -->|"通道 A · GET /my-cost/status(价格 + 余额)"| plugin
client -->|"通道 B · useProjection(费用)"| shell
client -.->|"__ModuleLoader__.load 注册"| shell
核心设计是两条互不重叠的数据通道:
GET /my-cost/status —— 价格表、峰谷状态、账户余额。API key 只在
host 侧解析(ctx.credentials),绝不下发浏览器。useProjection("myCost") / projectionValues.myCost —— 费用数据。
框架回放每次请求的 token 用量事件,插件纯函数累计计价,结果随会话持久化。在线打开 https://hehe1111.github.io/dsh-my-cost/architecture.html(或本地
docs/architecture.html)可交互查看:聚焦节点、追踪路径、切换主题/预设。
重新生成:安装 Archify 的 DSH 集成(dsh plugin --profile web add @tt-a1i/archify-dsh@0.1.0)
后用 archify skill 按 docs/architecture.json 规格 validate + deliver。
src/(host 端:index.js + pricing-core.js)与 client/(浏览器端,React 19);
lib/ 为 Vite 构建产物。MIT
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。