dsh-dock 0.4.0 → 0.4.1

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 CHANGED
@@ -3,238 +3,96 @@
3
3
  [![npm version](https://img.shields.io/npm/v/dsh-dock)](https://www.npmjs.com/package/dsh-dock)
4
4
  [![license](https://img.shields.io/npm/l/dsh-dock)](LICENSE)
5
5
 
6
- **DeepSeek Harness 功能坞插件(dsh-dock)**:用一张管理面板,统一注册、开关所有小功能。
6
+ **DeepSeek Harness 功能坞插件**:用一张管理面板,统一注册、开关所有小功能。
7
7
 
8
- 模型余额、用量记录、任务动画……这些散落的小功能,全部收进一个「功能坞」:
8
+ 模型余额、用量记录、模型设置、图片理解代理……这些散落的小功能,全部收进一个「功能坞」:
9
9
  每个功能是独立模块,有注册表、有开关、有错误隔离。新功能按模块追加,老功能互不牵连。
10
10
 
11
- > **v0.4.0 起为模块化架构**:功能坞 = hub + 一个个独立功能模块(像 dsh 本身由小包组成)。
12
- > 每个功能是一个 `features/<id>/` 目录(宿主半部 + 客户端视图),**可整体拎出单独打包发布**
13
- > (`scripts/extract-feature.mjs` 生成独立包骨架);独立发布的功能包装回后,经
14
- > **dockBridge** 注册进功能坞菜单——「单独成包」与「完美集成」两全。
15
- >
16
- > 前身:本地原型 `feature-hub`(已安装验证),本包为其正式发布的 npm 版本。
17
- > 相关功能包:`@wycto/dsh-balance-panel`、`@wycto/dsh-token-usage`、`@wycto/dsh-task-pulse`
18
- > (余额功能已于 0.2.0 吸收为中枢内模块;用量记录已于 0.4.0 以模块化方式重吸收)。
19
- > 开发背景与决策见 [docs/session-notes.md](docs/session-notes.md)。
11
+ ![功能坞首页总揽](screenshots/dock-home.png)
20
12
 
21
13
  ---
22
14
 
23
- ## 当前状态(v0.4.0 · 模块化架构 + 用量记录已接入)
24
-
25
- - ✅ **模块化架构(0.4.0)**:功能代码从两个大文件拆进 `features/<id>/` 模块目录;
26
- 宿主半部 `index.js` 与客户端外壳 `src/client.jsx` 只做组装,不含功能逻辑;
27
- 每个模块可单独提取成包(见下文「提取一个功能成独立包」)
28
- - ✅ **用量记录(0.4.0)**:记录全部 LLM API 调用并统计——
29
- - 秒级时间范围 + 会话/提供商/模型(联动)/状态/推理强度筛选,条件本地暂存(下次打开恢复);
30
- - 9 张 KPI 卡(调用次数 / 总 Token / 输入 / 缓存命中 / 命中率 / 输出 / 金额($) / 金额(¥) / 累计耗时);
31
- - 分组统计(无/provider/model/status/effort 维度切换);
32
- - 明细表 15 列可排序、100 行/页上下双分页、会话 ID 点击即筛选、行详情弹窗、CSV 导出;
33
- - 定价引擎:内置 DeepSeek 峰谷价目 + 官网价目每日自动抓取 + `dsh-dock-tokenlog` 命名空间覆盖;
34
- - 首页总揽「今日调用/Token/花费」卡片;面板打开期间每 5 秒自动刷新
35
- - ✅ 设置页「功能坞」面板(侧栏底部 → 设置 → 功能坞)
36
- - ✅ **侧栏入口按钮**:侧栏底部动作区右端「功能坞」按钮,弹出**功能面板**(居中模态:左导航 = 首页总揽 + 各功能模块按 order 排序,右内容区)
37
- - ✅ **弹层窗口化**:默认大窗(1080×700 自适应),最大化/最小化/还原、标题栏拖动、右下角缩放;几何页内记忆
38
- - ✅ **模型设置(0.3.0,集成官方链路)**:编辑各 Provider 模型目录(输入类型 + 思考强度档位),`settings.mutate` 写回官方配置热生效
39
- - ✅ **模型余额(0.2.0)**:枚举全部已配置 Provider,内置策略表查询余额/配额/控制台链接,5 分钟自动刷新
40
- - ✅ 每功能独立开关 + 错误隔离:单个功能出错只降级自己(外部包视图另有错误边界保护)
41
- - ✅ 示例功能:心跳监视、主题信息(纯 Client,开箱可用)
42
- - ✅ **会话区随身小控件(0.4.0)**:启用后在会话输入区工具行(模型选择器左侧)显示——
43
- - **模型余额**:当前选中 Provider 的账户余额(随余额刷新更新),点击打开功能坞并高亮该 Provider 行;
44
- - **用量记录**:当前会话总 Token 与估算花费(10s 静默刷新),点击打开功能坞并按该会话筛选;
45
- - 每个功能可单独设置「会话页显示/隐藏」(面板页脚与设置页均有开关,localStorage 持久化)
46
- - 🚧 功能开关为浏览器内存态,刷新重置(持久化在 0.6.0)
47
- - 🚧 任务动画已登记为规划占位(0.5.0)
48
-
49
- ### 模块化架构(0.4.0)
15
+ ## 功能一览
50
16
 
51
- ```
52
- dsh-dock/
53
- ├── index.js # 宿主半部入口(纯 ESM,零构建):import 各模块组装注册表与生命周期
54
- ├── client.js # 客户端 bundle(构建产物,提交仓库;源码见 src/ + features/)
55
- ├── src/
56
- │ ├── client.jsx # 客户端外壳:入口按钮/弹层/设置页/首页总揽/slots 注册/外部功能桥
57
- │ ├── shared.js # 共享工具(外部视图错误边界等)
58
- │ └── host-core.js # 宿主共享内核(DOCK_NS 命名空间、sendJson/readBody/walkPath)
59
- ├── features/ # ★ 一个目录 = 一个功能模块(整体可拎出单独打包)
60
- │ ├── balance/ # host.js + view.js
61
- │ ├── modelconfig/ # host.js + view.js(含图片理解代理配置面板)
62
- │ ├── visionproxy/ # host.js(纯宿主功能,UI 在 modelconfig 页内)
63
- │ ├── tokenlog/ # host.js + view.jsx(用量记录)
64
- │ ├── heartbeat/ # view.js(纯客户端功能)
65
- │ └── theme/ # view.js(纯客户端功能)
66
- ├── scripts/
67
- │ ├── build-client.mjs # esbuild bundle → client.js(改视图后需重跑)
68
- │ ├── extract-feature.mjs # 功能提取脚手架:features/<id> → 独立包目录
69
- │ └── publish.sh # 一键发布
70
- └── docs/session-notes.md # 会话总结与决策记录
71
- ```
72
-
73
- **模块契约**:
74
-
75
- - 宿主模块 `features/<id>/host.js` 导出 `feature = { id, name, description, defaultEnabled, setup(ctx) → disposer }`;
76
- - 视图模块 `features/<id>/view.js(x)` 导出 `feature = { id, name, order, accent, description, css, View, HomeStat? }`;
77
- `order` 决定菜单次序(首页固定第一;modelconfig=100 → 第二菜单,tokenlog=110 第三);
78
- 视图收到 `{ ctx, feature, params }` props(`params` 来自导航总线:chips 点击可带入
79
- `{ provider }` 高亮余额行、`{ sessionId }` 按会话筛选用量);
80
- 可选 `Chip` 组件(`{ ctx, session, sessionId, input, feature }` props):启用且「会话页显示」
81
- 时渲染在会话输入区工具行左端(`conversation.input.left`,模型选择器左侧),点击通常经
82
- `openPanel(id, params)` 打开功能坞定位到对应功能页;
83
- 每模块自带 `css`(类名前缀隔离:dkb-/dkm-/dtok- …),外壳统一注入;
84
- - 客户端外壳 `src/client.jsx`:import 模块 → 组装导航/首页/设置页;导出
85
- `apply` / `inject` / **`dockBridge`**(外部功能回装通道)。
86
-
87
- **为什么客户端引入了构建**(v0.4.0 决策,宿主半部仍是零构建纯 ESM):
88
- 功能模块用真实源码文件 + JSX 组织,esbuild 打成单文件 `client.js`
89
- (`react`/`react/jsx-runtime` 由运行时 seed,外部化;与 `@wycto/dsh-token-usage`
90
- 已在线上验证的构建模式同款)。改客户端代码后跑 `node scripts/build-client.mjs`。
91
-
92
- ## 面板入口
93
-
94
- ```
95
- ① 快捷入口:侧栏底部「功能坞」按钮(与设置按钮同底对齐)→ 弹出功能面板(首页总揽 + 模块导航 + 内容区,窗口可最大化/最小化/拖动/缩放)
96
- ② 完整面板:设置(侧栏底部)→ 功能坞
97
- ```
98
-
99
- 入口按钮与功能弹层挂载在 shell 的 `sidebar.footer.action` / `shell.overlay` 座位;
100
- 弹层与完整面板共用各功能的模块级共享快照
101
- (余额 `/dsh-dock/balance`、模型目录 `/dsh-dock/models`、用量 `/dsh-dock/tokenlog/*`,首页总揽概要与各视图同源)。
102
-
103
- ### 用量记录(0.4.0)
104
-
105
- - **数据源**:DSH 会话日志(`sessionQuery` 服务)。宿主实时监听 `session/event` 增量记账,
106
- 启动时全量扫描历史(`sessionId:seq` 幂等去重,实时与扫描重叠不双计);
107
- 记录含五类 token 桶、状态/错误码(`turn/end` 两遍式回填)、耗时(step/start → assistant/message)。
108
- - **定价与金额(估算)**:内置 DeepSeek-V4 峰谷刊例(高峰每日 9:00–14:00 双倍)等;
109
- 每 24h 自动抓取官网价目页(失败静默回退内置);汇率与价目可在 settings.yaml 覆盖:
110
-
111
- ```yaml
112
- dsh-dock-tokenlog:
113
- usdCnyRate: 7.2
114
- pricingUrl: 'https://api-docs.deepseek.com/zh-cn/quick_start/pricing'
115
- pricingFetchIntervalHours: 24
116
- pricing:
117
- deepseek-v4-flash: { input: 1.5, output: 4.5, cacheRead: 0.05, cacheWrite: 0 }
118
- ```
119
-
120
- 改价即时生效(查询/导出时按当前价目重算历史)。
121
- - **RPC**:`POST /dsh-dock/tokenlog/query|export|scan`(同源 webServer 路由)。
122
- - 已知口径:金额为估算;失败调用(无 `assistant/message`)不产生 token 行,状态反映回合结局。
17
+ | 功能 | 说明 |
18
+ |---|---|
19
+ | **用量记录** | 记录全部 LLM API 调用:秒级时间筛选、Token/费用统计(峰谷计价 + 官网价目自动同步)、分组汇总、明细检索与 CSV 导出 |
20
+ | **模型设置** | 编辑各 Provider 模型目录:输入类型(文本/图片 + 标注)与思考强度档位;写回官方配置热生效 |
21
+ | **模型余额** | 展示所有模型 Provider 账户余额(5 分钟自动刷新) |
22
+ | **图片理解代理** | 图片识别等(visionproxy) |
23
+ | **心跳监视 / 主题信息** | 示例功能(纯 Client) |
123
24
 
124
- ### 模型余额支持情况(0.2.0)
25
+ **会话区随身小控件**:启用后,在会话输入区工具行(模型选择器左侧)显示——
125
26
 
126
- 内置余额策略表覆盖:**DeepSeek**(官方余额接口)、**StepFun**、**Kimi Coding**(配额)、**OpenRouter**、**MiniMax**、**xAI/grok**;
127
- 按 provider id(含别名)或 baseURL 家族自动匹配;`qwen-token-plan-*`(阿里云百炼)等无 API 余额接口的 Provider 显示"需登录"并提供控制台跳转链接;
128
- 其余未知 Provider 显示"不支持"。自定义余额接口可在 Provider profile 里配 `balance.endpoint` 覆盖(沿用 `dsh-balance-panel` 约定)。
27
+ - **模型余额**:当前选中 Provider 的账户余额(跟随模型切换实时更新),点击打开功能坞并定位到该 Provider 的余额详情;
28
+ - **用量记录**:当前会话的总 Token 与估算花费(10 秒静默刷新),点击打开功能坞并跳转到该会话的用量记录。
129
29
 
130
- 密钥全程留在 Host 进程内:只按 `apiKeyEnv` 解析凭证使用,不出 Host、不下发到浏览器。
131
- 数据经回环 webServer 路由同源下发(Client `fetch` 拉取,不依赖 typert RPC,详见 [docs/session-notes.md](docs/session-notes.md))。
30
+ ![会话区余额/用量小控件](screenshots/dock-chips.png)
132
31
 
133
- ### 模型设置怎么生效(0.3.0)
32
+ 勾选「启用」即显示,点芯片跳转;每个功能可在面板页脚或设置页单独设置「会话页显示/隐藏」。
134
33
 
135
- 面板保存 → Host 经 `settings.mutate` 写入官方配置(`llm-pi-ai.providers.<route>.models[].reasoningEfforts/input/dockTags`
136
- 或 `llm-deepseek.models[]/thinking/reasoningEffort`)→ 适配器热加载(无需重启)→
137
- **会话窗口的模型选择器重新打开后,每个模型即可选择配置的强度档**(官方链路按 `model.reasoning.efforts` 展示)。
138
- 输入类型中仅文本/图片为官方真实模态(请求路由生效);视频/音频/文档为面板标注(持久化但不参与路由)。
34
+ ## 界面
139
35
 
140
- > **思考兼容兜底(0.3.0 修复)**:不在 pi-ai 内置目录里的模型(如部分第三方路由模型)启用思考后,
141
- > 适配器默认会把 system 改写成 `developer` 角色,百炼等 OpenAI 兼容端点直接 400。面板在启用思考档时
142
- > 自动写入 `compat.supportsDeveloperRole: false`;qwen/百炼家族再补 `thinkingFormat: qwen`,与官方目录内模型一致。
143
- > 保存时原条目上的未知字段(含用户自配 compat)原样保留,不会被面板清掉。
36
+ 点击侧栏底部「功能坞」按钮,弹出功能面板:左侧导航 = 首页总揽 + 各功能模块,右侧内容区。
144
37
 
145
- ### 图片理解代理(0.3.1)
38
+ ![用量记录页](screenshots/dock-tokenlog.png)
146
39
 
147
- 纯文本模型也能"看图":在 设置 → 功能坞 → 模型设置 顶部(或弹层同页)启用**图片理解代理**并点选一个
148
- **视觉模型**(候选 = 模型目录中支持图片输入的全部模型,跨 Provider)后:
40
+ 面板支持最大化 / 最小化 / 还原、标题栏拖动、右下角缩放。
149
41
 
150
- - 发给**纯文本模型**的消息带图片时,自动先调用所选视觉模型识别,识别文本以 `[图片内容(由视觉模型 … 识别):…]` 注入请求;
151
- - **多模态模型不受影响**,按官方链路原样自识别;
152
- - 识别失败自动降级(注入说明文本,不影响主请求);同一张图 10 分钟识别缓存;
153
- - 配置存插件自有 `dsh-dock` 命名空间,保存即热生效。
154
-
155
- ## 新增一个功能(两步)
156
-
157
- 1. 建 `features/<id>/`:
158
- - `view.js(x)` 导出 `feature = { id, name, order, accent, description, css, View, HomeStat? }`
159
- (纯客户端功能到这就够了);
160
- - 需要宿主逻辑的加 `host.js` 导出 `feature = { id, name, description, defaultEnabled, setup(ctx) → disposer }`;
161
- 2. 在 `src/client.jsx` 的 `BUILTIN_FEATURES` import 一行;宿主功能再在 `index.js` 的 `FEATURES` import 一行;
162
- 改完跑 `node scripts/build-client.mjs`。
42
+ ---
163
43
 
164
- 需要从 Host 拿数据的功能:在模块 `setup(ctx)` 里用 `ctx.get('webServer').register`
165
- 注册同源路由(纯 JSON),视图 `fetch('/dsh-dock/<id>')` 拉取——密钥只进 Host,
166
- 绝不下发浏览器。详见 [docs/session-notes.md](docs/session-notes.md) 8.3。
44
+ ## 安装
167
45
 
168
- ## 提取一个功能成独立包
46
+ dsh-dock 是 DeepSeek Harness(dsh)的插件,通过 dsh 的插件市场安装:
169
47
 
170
- ```sh
171
- node scripts/extract-feature.mjs tokenlog --out ../dsh-dock-tokenlog
48
+ ```bash
49
+ # 在 dsh 配置中启用插件(或通过 dsh 插件命令)
50
+ npx @deepseek-ai/dsh plugin add dsh-dock
172
51
  ```
173
52
 
174
- 生成独立包骨架(镜像本仓库布局,模块内相对导入不变):宿主入口、独立客户端入口
175
- (**双形态**:装了 dsh-dock → `ctx.modules.import('dsh-dock')` 成功 → `dockBridge.register`
176
- 注册进功能坞菜单;没装 → 自己的侧栏入口 + 全屏面板)、构建脚本、`cordis.patch.yml`、`package.json`。
177
- 发布前裁剪依赖 → 构建 → 实测两种形态(含与功能坞共存时的菜单合并,独立入口应隐藏)。
53
+ 或手动在 dsh 的 `cordis.patch.yml` 中声明后重启。
178
54
 
179
- ## 路线图(后面要干嘛)
55
+ 要求:DeepSeek Harness 环境(dsh),Node.js 18+。
180
56
 
181
- | 版本 | 内容 | 状态 |
182
- | --- | --- | --- |
183
- | **0.2.0** | 接入**模型余额**:策略表查询各 Provider 余额/配额;侧栏入口 + 功能弹层 | ✅ 已接入 |
184
- | **0.3.0** | 接入**模型设置**:官方目录链路集成,写回热生效;弹层窗口化 | ✅ 已接入 |
185
- | **0.4.0** | **模块化架构**(features/ 模块目录 + 客户端构建 + dockBridge 回装通道)+ 接入**用量记录** + **会话区随身小控件**(余额/用量 chips,模型选择器左侧,可单独开关) | ✅ 已接入(本版) |
186
- | **0.5.0** | 接入**任务动画**:任务进度动画、完成/卡住通知 | 纯 Client 功能模块;如需挂对话区,在模块内注册对应 slot(如 `conversation.composer.dock`) |
187
- | **0.6.0** | 开关状态**持久化**、Host↔Client 双侧注册表打通 | 状态写入持久化服务;Host 侧开关与 Client 面板同步;外部功能包的可选依赖注册(面板不在,功能照跑) |
57
+ ## 使用方法
188
58
 
189
- 后续新增功能遵循同一模式:**模块目录 + 注册表一行 import**,即插即用。
59
+ 1. 启动 dsh:`npx @deepseek-ai/dsh web`
60
+ 2. 打开左侧边栏底部的 **功能坞** 按钮
61
+ 3. 在 **设置 → 功能坞** 面板中启用/停用各功能模块
62
+ 4. 每个功能页内可进行具体操作(余额查询、用量统计、模型目录编辑等)
190
63
 
191
- ## 安装
192
-
193
- 开发期(link 模式):
64
+ > 功能开关为浏览器内存态,刷新页面后重置(持久化在规划中)。
194
65
 
195
- ```sh
196
- dsh plugin --profile web add dsh-dock # npm 版安装
197
- # 或本地路径:dsh plugin --profile web add /path/to/dsh-dock
198
- ```
66
+ ## 开发:新增一个功能模块
199
67
 
200
- 查看/卸载:
68
+ 每个功能是一个 `features/<id>/` 目录,由两部分组成:
201
69
 
202
- ```sh
203
- dsh web --dump-config # 查看合成层(含 dsh-dock)
204
- dsh plugin --profile web remove dsh-dock # 卸载
205
70
  ```
206
-
207
- ### 从 feature-hub 迁移
208
-
209
- 本包是 feature-hub 原型的正式发布版,面板与功能几乎一致:
210
-
211
- ```sh
212
- dsh plugin --profile web remove dsh-feature-hub
213
- dsh plugin --profile web add dsh-dock
71
+ features/<id>/
72
+ host.js # 宿主半部:注册 RPC 路由 / 定时任务(纯 ESM,零构建)
73
+ view.js(x) # 客户端视图:渲染面板内容(自带样式,CSS 类名带前缀隔离)
214
74
  ```
215
75
 
216
- (两个插件共存亦可,只是面板重复;建议迁移后移除旧版。)
217
-
218
- ## 开发与发布
219
-
220
- - **开发提交**:Gitea 开发仓库(本仓库)
221
- `ssh://git@172.18.99.124:9022/wycto/dsh-dock.git`
222
- - **发版**:GitHub 仓库(`github.com/wycto/dsh-dock`,待建)打 tag 发 Release
223
- - **npm 发布**(无作用域名先到先得,已占用后归本账号所有):
224
-
225
- ```sh
226
- cd dsh-dock
227
- npm login # 首次:登录你的 npm 账号(wycto)
228
- scripts/publish.sh # 预览 → 登录检查 → 发布
76
+ 在视图模块导出功能描述符:
77
+
78
+ ```js
79
+ export const feature = {
80
+ id: "my-feature",
81
+ name: "我的功能",
82
+ order: 160, // 菜单排序(首页固定第一,数值越大越靠后)
83
+ accent: "#22c55e", // 品牌色
84
+ description: "…",
85
+ css: "…",
86
+ View: MyView, // 面板内容组件,收到 { ctx, feature, params }
87
+ HomeStat: MyStat, // 可选:首页总揽卡片统计
88
+ Chip: MyChip, // 可选:会话输入区小控件
89
+ };
229
90
  ```
230
91
 
231
- > 若发布时报 `EPERM`(npm 缓存目录里有 root 属主文件的历史 bug):
232
- > 修复一次 `sudo chown -R 501:20 ~/.npm`,或临时绕过
233
- > `CACHE_DIR=/tmp/dsh-dock-npm-cache ./scripts/publish.sh`。
234
-
235
- > 注:`package.json` 中 repository 指向 GitHub(发版仓库),Gitea 建好后
236
- > 建议把两个地址都确认一遍。
92
+ 外壳只做组装:宿主半部在 `index.js` 注册,客户端在外壳 `src/client.jsx` 装配。
93
+ 每个模块可整体拎出单独打包发布(`scripts/extract-feature.mjs` 生成独立包骨架,
94
+ 独立包装回后经 **dockBridge** 注册回功能坞菜单)。
237
95
 
238
- ## License
96
+ ## 许可
239
97
 
240
- MIT
98
+ [MIT](LICENSE)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-dock",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "DeepSeek Harness 功能坞插件(dsh-dock):模块化功能中枢——每个功能一个 features/ 模块(可单独提取成包发布,又可经 dockBridge 装回面板)。含用量记录(LLM 调用记账/费用统计)、模型设置、图片理解代理、模型余额;侧栏入口 + 可拖拽弹窗(最大化/最小化/缩放)。",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -9,7 +9,8 @@
9
9
  "client.js",
10
10
  "src/",
11
11
  "features/",
12
- "cordis.patch.yml"
12
+ "cordis.patch.yml",
13
+ "screenshots"
13
14
  ],
14
15
  "exports": {
15
16
  ".": "./index.js",
@@ -53,4 +54,4 @@
53
54
  "@deepseek-ai/dsh-settings": "^0.1.1-rc.2",
54
55
  "@deepseek-ai/schemastery": "^3.18.1"
55
56
  }
56
- }
57
+ }
Binary file
Binary file
Binary file