dsh-dock 0.14.0 → 0.16.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/README.md CHANGED
@@ -17,16 +17,18 @@
17
17
  | 功能 | 说明 |
18
18
  |---|---|
19
19
  | **用量记录** | 记录全部 LLM API 调用:秒级时间筛选、Token/费用统计(**可配置各模型单价、持久保存并按自填单价计费**,支持多段分时价与周末/节假日谷价,内置峰谷计价 + 官网价目自动同步作兜底)、分组汇总、明细检索与 CSV 导出 |
20
- | **模型设置** | 编辑各 Provider 模型目录:输入类型(文本/图片 + 标注)与思考强度档位;自定义 Provider 的增删改在「模型提供商」子页面(排版同官方模型管理),图片能力可由你手动声明,新增 Provider 自动刷新加载,写回官方配置热生效 |
20
+ | **模型设置** | 编辑各 Provider 模型目录:输入类型(文本/图片 + 标注)与思考强度档位;图片能力可由你手动声明,新增 Provider 后进入页面自动重读目录,写回官方配置热生效 |
21
+ | **模型提供商** | 管理自定义模型 Provider 本身:新增 / 编辑 / 删除(OpenAI 兼容、Anthropic Messages 等)、API Key 写入本机凭据库、拉取上游 `{baseURL}/models` 列表;排版同官方模型管理页。**独立功能,可单独停用**——停用后写配置与出站拉取的路由一并关闭 |
21
22
  | **模型余额** | 展示所有模型 Provider 账户余额(5 分钟自动刷新) |
22
23
  | **任务动画** | 19 种任务运行动画(含星际远征、星云潮汐、曲速航道、量子雷达、星座网络、深海脉动、神经电路等),速度随任务活动联动,配置全部持久化 |
23
24
  | **任务通知** | 任务完成 / 异常 / 需确认通知:页内卡片、6 种提示音、浏览器系统通知、钉钉/飞书群机器人推送(宿主直发,浏览器关着也能推);与动画互相独立、各自启停 |
24
25
  | **运行状态** | 任务运行状态一览:进行中任务的阶段 / 耗时 / 回合 / 步骤 / 工具 / Token、等待确认提醒(等待的工具与说明)与最近完成记录(只读,与动画/通知共用同一份宿主侧追踪) |
26
+ | **语音朗读** | 把会话回复读出来(浏览器 Web Speech API 语音合成,不消耗 token、不经过服务器):每条已完成回复下方一个 🔊 喇叭——点一下读这条、播放中再点暂停、继续就地续读(不重头),另有重新朗读/停止;也可开「自动朗读」,任务结束时直接读最后一条回复。音色/语速/音调/音量可调,Markdown 自动清洗(代码块、表格、思考过程不念),支持「只读前 N 句 / 字数上限」 |
25
27
 
26
28
  | **趣味游戏** | 任务等待时消磨时间的十款小游戏(五子棋、中国象棋、俄罗斯方块、推箱子、贪吃蛇、打砖块、极速赛车、坦克大战、星际躲避、反应堆解谜);浮动窗口可拖动/缩放/最小化,不遮挡会话,靠屏幕侧边隐藏 |
27
29
  | **图片理解代理** | 图片识别等(visionproxy);原图候选默认折叠展示,图片能力以你的声明为准 |
28
30
  | **远程访问** | 账号密码登录的远程入口:网关监听 `0.0.0.0` 独立端口,手机/平板/局域网设备访问同一实例,会话与任务进度实时一致;主实例保持仅监听 `127.0.0.1`,结构上不存在绕开登录的直连路径;LAN 非安全上下文自动补 crypto.randomUUID。手机端排版不在此列——统一归「手机适配」。 |
29
- | **手机适配** | 手机/窄屏排版与触控兜底:输入类控件 16px 防 iOS 聚焦缩放、纯图标按钮触控面积兜底 ≥36px、代码块横向滚动、viewport-fit=cover 安全区、滚动体 touch-action:pan-y + iOS 惯性滚动、设置弹层 min-height:0 滚动兜底;手机端 chrome 含底部 Tab 栏(会话/插件/设置,等待确认角标红色脉冲)+ 侧栏抽屉遮罩 + 软键盘让位 + 设置弹层纵排(宿主经 tapIndex 注入,客户端自建同款互斥) |
31
+ | **手机适配** | 手机/窄屏排版与触控兜底:输入类控件 16px 防 iOS 聚焦缩放、纯图标按钮触控面积兜底 ≥36px、代码块横向滚动、viewport-fit=cover 安全区、滚动体 touch-action:pan-y + iOS 惯性滚动、设置弹层 min-height:0 滚动兜底;手机端 chrome 含左上角「三条横线」汉堡菜单(点击展开左侧会话抽屉,不占页面空间)+ 侧栏抽屉遮罩 + 软键盘让位 + 设置弹层纵排(宿主经 tapIndex 注入,客户端自建同款互斥) |
30
32
  | **心跳监视 / 主题信息** | 示例功能(纯 Client) |
31
33
 
32
34
  **会话区随身小控件**:启用后,在会话输入区工具行(模型选择器左侧)显示——
@@ -187,8 +189,8 @@ dsh plugin --profile web add dsh-dock # 换回 npm 版
187
189
  ![任务通知:通知事件 / 提醒方式 / 提示音试听 / 钉钉与飞书群机器人推送(Webhook 已脱敏)](screenshots/dock-notify.png)
188
190
 
189
191
  1. 打开功能坞 → 任务通知:
190
- - **通知事件**:完成通知 / 异常通知 / **需确认提醒**(工具等待你批准,如沙箱越界执行命令时弹常驻卡片 + 确认音)各自独立开关
191
- - **提醒方式**:卡片停留时长(4 / 8 / 15 / 30 秒或常驻)、浏览器系统通知(仅页面后台时推送,首次开启会请求授权)、**提示音** 6 种 WebAudio 合成音效可选(完成 / 异常 / 确认各配一音,可单独试听)
192
+ - **通知事件**:完成通知 / 异常通知 / **需确认提醒**(工具等待你批准,如沙箱越界执行命令时弹卡片 + 确认音;审批处理完卡片自动收起,没处理完就一直显示,点卡片直达该会话)各自独立开关
193
+ - **提醒方式**:结束卡片(完成/异常)**常驻到「看过」**——没有任何超时自毁,后台跑完的任务切回来一定还在;**点卡片直达对应会话**(跳转成功即收起),点进那个会话看结果也会自动收起,手动 ✕ 照旧;卡片 ≥3 张自动**叠放**成标题条,鼠标移上去整体展开。浏览器系统通知(仅页面后台时推送,首次开启会请求授权)、**提示音** 6 种 WebAudio 合成音效可选(完成 / 异常 / 确认各配一音,可单独试听)
192
194
  - **钉钉推送**(可选):任务结束由宿主直发 markdown 消息到钉钉群机器人(浏览器关着也能推)——填入 Webhook 地址保存,「发送测试消息」验证连通;机器人安全设置选「自定义关键词」填「任务」或「dsh」
193
195
  - **飞书推送**(可选):与钉钉同款消息以卡片形式推送到飞书群机器人——填入 Webhook 地址(`https://open.feishu.cn/open-apis/bot/v2/hook/…`)保存,「发送测试消息」验证连通;可与钉钉同时开启
194
196
  2. 通知与动画**互不依赖**:停用「任务动画」后通知照常工作,反之亦然(动画 / 通知 / 运行状态共用同一份宿主侧任务追踪,只有一份开销)
@@ -205,31 +207,40 @@ dsh plugin --profile web add dsh-dock # 换回 npm 版
205
207
  2. 面板打开时自动刷新(有任务 2 秒、空闲 8 秒、出错 15 秒),也可手动「刷新」;本模块没有常驻浮层,关掉面板即零开销
206
208
  3. 本页只读、**不写任何配置**:数据来自宿主侧会话级任务追踪(与动画 / 通知共用一份);动效在「任务动画」,结束 / 需确认提醒在「任务通知」
207
209
 
210
+ **语音朗读**
211
+
212
+ 1. 打开功能坞 → 语音朗读(启用后生效):
213
+ - **每条已完成回复的下方**(复制/分支那一排之前)出现一个 🔊 喇叭,三态控制:**没在读点一下读这条;正在读再点=暂停**(停在当前这句的当前字上);**暂停后再点=就地继续,不重头**。播放中旁边另有「重新朗读」(回第一句)与「停止」两枚按钮;换一条朗读时上一条**立即让位**(等浏览器把旧队列冲刷空再开播,不会先听完上一条的尾巴);行尾还有一个 **⚙ 快设**:就地弹语速/音量滑杆(播放中拖动下一句起生效),「更多设置」直达功能坞面板;
214
+ - **自动朗读**:任务结束时自动读该会话最后一条回复(与「任务通知」共用同一份宿主侧任务追踪做触发源——冷读历史会话不会把老回复补读一遍)。可单独设置「出错 / 中止也读」「新内容打断当前朗读」;宿主进程是旧版本(还没注册 `/dsh-dock/tts` 路由)时自动降级为**本地兜底**:你正在看的会话照常读,后台会话要重启 `dsh web` 后才覆盖——面板底部黄条会说明这一点;
215
+ - **声音**:音色下拉(读本机浏览器的 `speechSynthesis.getVoices()`;音色是**设备相关**的,选中的音色在本机不存在时自动按语言回落)、强制语言、语速 / 音调 / 音量,「试听」「停止」按钮;
216
+ - **念什么**:回复正文是 Markdown,默认**跳过代码块与表格**(只留一句「此处有代码/表格,略」)、思考过程永远不读、链接只念锚文字;「只读前 N 句」「字数上限」适合只听结论的场景。
217
+ 2. 朗读完全发生在**你自己的浏览器**里(Web Speech API):不消耗 token、不经过服务器;声音从当前这台设备的扬声器出来。浏览器不支持时(如部分 Linux Chromium)按钮会给出原因提示;配置经宿主 settings 持久化(`tts` 段),跨浏览器共享,宿主路由不可用时降级为本浏览器 localStorage。
218
+ 3. 长回复自动按句分片顺序播放(Chrome 对超长 utterance 会静默停住,这是标准解法)。浏览器策略要求页面有过用户手势才允许出声:刚打开页面就开自动朗读可能被拦,点一下页面即可。
219
+
208
220
  **模型设置**
209
221
 
210
- ![模型设置:模型提供商入口卡 + 各 Provider 模型目录编辑器(输入类型 / 思考强度 / 图片能力声明)](screenshots/dock-modelconfig.png)
222
+ ![模型设置:各 Provider 模型目录编辑器(输入类型 / 思考强度 / 图片能力声明)](screenshots/dock-modelconfig.png)
211
223
 
212
224
  1. 打开功能坞 → 模型设置
213
- 2. 编辑各 Provider 的模型目录:输入类型(文本 / 图片)、思考强度档位;新建 Provider 后进入页面会自动重读目录,顶部和底部都可手动刷新
225
+ 2. 编辑各 Provider 的模型目录:输入类型(文本 / 图片)、思考强度档位;Provider 增删改后在别的页签回来会自动重读目录,顶部和底部都可手动刷新
214
226
  3. 是否可直接识图以你勾选的「图片」能力为准;运行时候选仅作辅助提示
215
227
  4. 保存后写回官方配置,即时生效(无需重启)
216
- 5. **模型提供商**:主页「模型提供商」卡片点右侧「管理」进入子页面(见下)
217
-
218
- **模型提供商(模型设置的子页面)**
228
+ 5. Provider 自身的增删改在独立功能「模型提供商」里(下方),本页不再有入口卡与子页面
219
229
 
220
- 主页不再挤着长长的 Provider 列表——「模型提供商」是一张入口卡(自定义路由数 + 密钥状态圆点 + 「管理」),点进去的子页面排版与官方「设置 → 模型」一致:
230
+ **模型提供商**(独立功能,与「模型设置」各自启停)
221
231
 
222
- ![模型提供商子页面:每个 Provider 一行卡片(显示名称 / 路由 key / 模型数 / 密钥状态徽标 + 编辑 / 删除),底部虚线新增](screenshots/dock-modelconfig-providers.png)
232
+ ![模型提供商:每个 Provider 一行卡片(显示名称 / 路由 key / 模型数 / 密钥状态徽标 + 编辑 / 删除),底部虚线新增](screenshots/dock-modelconfig-providers.png)
223
233
 
224
234
  ![编辑 Provider:一行一字段(路由 key / 显示名称 / baseURL / API 协议 / API Key),模型清单沿用官方模型行样式](screenshots/dock-modelconfig-provider-edit.png)
225
235
 
226
236
  ![新增 Provider:底部虚线入口展开的创建卡片,可「获取模型列表」勾选上游模型后批量加入](screenshots/dock-modelconfig-provider-create.png)
227
237
 
228
- - **新增 / 编辑 / 删除**自定义模型 Provider(OpenAI 兼容、Anthropic Messages 等),写入官方配置并热生效;内置 DeepSeek 官方 Provider 在该页只读,其模型目录仍在主页编辑
229
- - **API Key** 存本机凭据库(文件仅 root 可读),输入框永不回显;留空则不改动已存密钥
238
+ - **新增 / 编辑 / 删除**自定义模型 Provider(OpenAI 兼容、Anthropic Messages 等),写入官方配置并热生效;内置 DeepSeek 官方 Provider 在该页只读,其模型目录在「模型设置」里编辑
239
+ - **API Key** 存本机凭据库(文件仅 root 可读),输入框永不回显;留空则不改动已存密钥;凭据库条目名留空时按路由 key 自动推导
230
240
  - **获取模型列表**:宿主代打 `GET {baseURL}/models`,结果按可勾选清单展示(全选 / 清空 / 已选计数),勾上哪个加哪个
231
- - 删除仍是两段式确认(点一次变「确认删除?」,再点才真删);编辑/新增卡片都是行内展开,返回主页即卸载、草稿不留后台
232
- - 深链 `params.page === "providers"` 或 `params.openProviderForm`(后者直接展开新增表单)可直达该页
241
+ - 删除仍是两段式确认(点一次变「确认删除?」,再点才真删);编辑/新增卡片都是行内展开
242
+ - 深链 `params.openProviderForm` 可直接展开新增表单
243
+ - **可停用**:不需要改 Provider 的部署(例如只用官方 DeepSeek 端点)把它关掉,写官方配置、写凭据库、发起出站拉取的那三条路由会随功能一起卸载
233
244
 
234
245
  **图片理解代理(visionproxy)**
235
246
  - 用于图片内容识别等场景。原图直发候选默认折叠,模型设置中勾选「图片」输入类型的模型即可走该通道;请按实际 Provider 能力选择,端点不支持时取消该标记即可恢复代理识别。
@@ -244,11 +255,11 @@ dsh plugin --profile web add dsh-dock # 换回 npm 版
244
255
  - **异地组网**:Tailscale/ZeroTier 等虚拟组网内直接用组网 IP 访问同一入口,效果与局域网相同。
245
256
  - 旧版「服务器模式(0.0.0.0)」与「扫码令牌接力」已被此方案取代:前者把无认证的 DSH 裸露给局域网,后者双实例任务状态不同步。开启远程访问时会自动清理旧的 0.0.0.0 webserver 补丁行(提示重启后回到仅本机)。
246
257
  2. **手机端接力体验(窄屏自动生效;由「手机适配」提供)**:
247
- - **底部 Tab 栏**:会话(拉出会话抽屉)/ **插件** / 设置。任务状态以角标显示在「插件」页签上:有任务进行中显示蓝色数量;**任务等待你确认工具调用时角标变红并脉冲**——公司电脑上跑着的任务停住等人,手机上一眼可见;此时点「插件」直达「运行状态」页处理,没有任务时进插件面板首页。
258
+ - **左上角汉堡菜单**:点「三条横线」展开左侧会话抽屉(不占页面空间,底部不再有常驻栏)。插件 / 设置 / 运行状态等入口本来就在抽屉里(原生侧栏),展开即可达;**任务等待你确认时汉堡右上角出现红色脉冲角标**(进行中为蓝色计数),一眼可见不用翻页。标题会为汉堡留出宽度(会话页头、插件页头、自动化任务页头都会内缩,标题与汉堡保持 8px 间隔),不会被压住。
248
259
  - **PWA 添加到主屏幕**:网关自带 manifest 与图标(品牌渐变 + 白色气泡,零依赖生成),手机浏览器「添加到主屏幕」后像 App 一样全屏打开,无地址栏;未登录也能先装,打开后自然进登录页。
249
260
  - **断线提示**:换网 / 锁屏久置导致连接中断时,页面顶部出现「连接已断开,正在重连…」胶囊,恢复后自动消失(连续 2 次探测失败才提示,不闪报)。
250
- - **软键盘适配**:键盘弹出时底部 Tab 栏自动让位,不再挤占键盘上方空间。
251
- - 会话入口统一在底部 Tab 栏「会话」页签(左缘浮动抽屉把手与浮动侧栏按钮均已移除,避免悬浮遮挡内容)。
261
+ - **软键盘适配**:键盘弹出时汉堡菜单自动让位,不再挤占键盘上方空间。
262
+ - 会话入口统一在左上角汉堡菜单(底部 Tab 栏、左缘浮动抽屉把手与浮动侧栏按钮均已移除,避免占用/遮挡内容)。
252
263
  - 面板「远程访问」页与首页总揽会显示当前**在线设备数**;登录页支持密码明文切换。
253
264
 
254
265
  **不开「远程访问」的直连形态**:也可以不经网关、自行经 patch 层把主实例绑 `0.0.0.0` 直连(安全自担,浏览器表层没有登录认证)。这种形态下「远程访问」功能可以整个停用,dsh-dock 仍兜住两件与功能开关无关的事:**非回环浏览器的「预览版说明」自动确认**(dsh 对远程浏览器的确认不持久化,每次刷新都会重弹;插件级注入,回环地址不介入、保留原生的一次性持久确认)与**「手机适配」的整套窄屏排版**(与远程访问完全解耦,见下)。
@@ -267,7 +278,7 @@ dsh plugin --profile web add dsh-dock # 换回 npm 版
267
278
 
268
279
  ### 常见问题
269
280
 
270
- - **插件会消耗 token 吗**:默认不会。用量记录/模型余额/任务动画/任务通知/运行状态/模型设置都是被动监听或本地查询,不调用 AI。唯一主动调 AI 的是「图片理解代理」(用视觉模型识图),它**默认关闭**,需你在模型设置里手动开启才生效;开启后每次识图按所选视觉模型计费。
281
+ - **插件会消耗 token 吗**:默认不会。用量记录/模型余额/任务动画/任务通知/运行状态/模型设置/语音朗读都是被动监听或本地查询,不调用 AI(语音朗读走浏览器自己的 Web Speech API,连服务器都不过)。唯一主动调 AI 的是「图片理解代理」(用视觉模型识图),它**默认关闭**,需你在模型设置里手动开启才生效;开启后每次识图按所选视觉模型计费。
271
282
  - **功能开关刷新后重置**:v0.5.0 起功能开关已持久化(浏览器本地存储),刷新/重启后保持。
272
283
  - **任务动画/任务通知/运行状态不生效**:三者的路由都在宿主进程内(动画/通知的配置持久化也在宿主),旧宿主需重启 `dsh web` 加载(面板页会提示「宿主进程是旧版本」)。另注意通知与运行状态已各自独立成菜单项,需在功能坞里分别开启「任务通知」「运行状态」。
273
284
  - **用量记录空白**:确认 dsh 是较新版本且插件宿主已加载(查看启动日志含 `[dsh-dock] host half loaded`);旧宿主进程需重启 dsh web 加载新路由。
@@ -314,6 +325,25 @@ export const feature = {
314
325
  每个模块可整体拎出单独打包发布(`scripts/extract-feature.mjs` 生成独立包骨架,
315
326
  独立包装回后经 **dockBridge** 注册回功能坞菜单)。
316
327
 
328
+ ### 硬约定:路由入口必须先过浏览器信任栅栏
329
+
330
+ `webServer` 的命名路由由载体直接派发给 handler,载体本身**不拥有认证或 Origin 策略**;
331
+ `/api` 的 Host/Origin 校验与会话认证由 Connection 在自己的 FetchHandler 上做,**管不到
332
+ 插件注册的命名路由**。所以任何自行注册的路由,第一件事必须是:
333
+
334
+ ```js
335
+ import { rejectUntrustedRequest } from '../../src/host-core.js'
336
+ // …
337
+ async handler(req, res) {
338
+ if (rejectUntrustedRequest(ctx, req, res)) return // 401 无会话 / 403 来源不可信
339
+ // …业务逻辑
340
+ }
341
+ ```
342
+
343
+ 不挂守卫 = 任何能连到端口的人都能直接调用它(可写配置、写凭据库、发起带着本机密钥的出站请求)。
344
+ `node scripts/test-route-trust-host.mjs` 会静态检查每一处 `webServer.register` 都挂了守卫,
345
+ 并行为验证 401/403/栅栏缺失(fail-closed)三条路径——新增路由务必让这条用例继续绿。
346
+
317
347
  ## 许可
318
348
 
319
349
  [MIT](LICENSE)