dsh-advisor-group 0.1.3 → 0.1.5

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
@@ -1,147 +1,276 @@
1
- # dsh-advisor-group
2
-
3
- > [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH)插件:主模型在遇到**专业、长尾世界知识、高风险或不确定**的问题时,召集多位**专家顾问模型**,在复古 CRT 聊天组卡片中真流式对话。
4
-
5
- [![dsh-plugin](https://img.shields.io/badge/DSH%20plugin-dsh--plugin-3f8cff)](https://github.com/topics/dsh-plugin)
6
-
7
- [English: README.en.md](README.en.md)
8
-
9
- ---
10
-
11
- <img width="865" height="983" alt="1788679983177" src="https://github.com/user-attachments/assets/5660ce94-70f0-42ed-84e4-9f926d1e2c64" />
12
-
13
- ## ✨ 功能特性
14
-
15
- - **自动深挖咨询流水线**:一次 `ask_advisors` 自动跑满 `maxRounds` 轮——每轮 = *驱动模型深挖追问 → 顾问 A → 顾问 B(看到 A)→ 顾问 C(看到 A+B)→ …* 顺序接力,最后驱动模型产出**综合结论**。
16
- - **顾问可调用会话工具(2026-09-05)**:顾问模型回答前可调用**当前 DSH 会话可见的工具**(默认只读白名单:read/grep/glob/web_search/web_fetch…)——走官方 `ctx.tools` 完整管线(作用域分发、守卫、前置/后置策略),循环上限 4 轮后强制文字作答;每次调用在卡片 💭 面板实时播报(`🔧 模型请求调用工具…`+结果摘要)。可在设置中切到「全部会话工具」或「关闭」。
17
- - **停止后可继续**:用户停止或 dsh 重启后,卡片「⏹ 停止」原位变为「▶ 继续聊天」→ `POST /advisor-group/resume` → 从断点续跑(本轮未答的顾问补答、已答的不重问、剩余轮次照常、最终照常生成综合结论);会话快照持久化到 `storages/advisor-group/sessions/<id>.json`(仅存顾问 id/消息/状态,不含任何凭据),跨重启自动恢复。
18
- - **驱动模型零配置复用**:深挖追问由驱动模型生成,直接复用会话当前 agent 的 provider/model——无需额外配 Key 或模型;会话头不可读时回退 `discussion.driverModel`。
19
- - **三种触发方式**:`@顾问群` 提及(强制启动)、同一问题重复 3 次未解决、主模型自评置信度低于阈值。
20
- - **Jev 语义前置分类(可选,默认关闭)**:开启 `trigger.jev.enabled` 后,未强制启动的咨询先由配置的 Jev 模型语义判断(是否该找顾问 / 是否高风险 / 是否更适合联网,阈值在 `trigger.jev.*`);Jev 不可用时仍由本地规则分类器判定。`trigger.jev.useEnglishState` 开启后,判定改读主模型附带的英文概要(`questionEn`),展示与会话记录仍用中文。
21
- - **复古 CRT 聊天组卡片**:绿/琥珀/蓝三主题、扫描线、LIVE/DONE 标题、💭 思考面板默认展开自动滚底;顾问正文走轻量 Markdown 渲染(链接协议白名单,支持标题/列表/代码/引用/链接/表格)。
22
- - **跨会话提问(`ask_session`)**:把一个问题交给另一个**活着的**会话——用完整会话号、一字不差的标题,或者自然的名字(例如工作目录名「极简遥控器」)都可以——并唤醒它;拿回的是**从投递回执到对方下一次整体空闲**之间它说的话,明确**不是**逐条对应的回答。提问方一侧用同一套复古聊天组卡片呈现这次对话。护栏:跳数 ≤ 2、不能问自己或子会话、同一会话同时只等一个、载荷上限 32 KB;**永不取消对方的回合**。
23
- - **供应商预设(11 平台 · 26 预设)**:DeepSeek、月之暗面 Kimi、Kimi Code、阿里云百炼、智谱 AI、OpenAI、Claude、Gemini、硅基流动、AIHubMix、OpenRouter(含 OpenAI / Anthropic 兼容变体)。
24
- - **注重安全**:API Key 采用官方 `SecretField` 语义(浏览器永不回显;`apiKeysByProvider` 供应商密钥档案仅存服务端);诊断端点 SSRF 加固(仅 https/loopback、拒绝 IP 字面量与重定向);`/advisor-group/*` 路由启动期 token 鉴权;每日新咨询**可配置原子配额**(默认 50,可关闭),持久化跨重启。
25
- - **运行时开关**:`toggle_advisor_group` 启停插件并持久化到设置。
26
-
27
- ## ✅ 兼容性
28
-
29
- | 项目 | 状态 |
30
- |---|---|
31
- | Harness | DeepSeek Harness `0.1.7-rc.2` → `0.2.x`(含 `0.2.0-rc.1`) |
32
- | Node | `^22.19.0 \|\| >=24.0.0` |
33
- | 平台 | DSH Web 与桌面端(共用同一份客户端 bundle)+ headless 宿主逻辑 |
34
-
35
- ## 📦 安装
36
-
37
- ```sh
38
- # 1. 安装插件(一个包全都有)
39
- dsh plugin --profile web add dsh-advisor-group
40
-
41
- # 2. 重启 dsh web
42
- npx @deepseek-ai/dsh web
43
- ```
44
-
45
- > **从源码开发安装**
46
- > ```sh
47
- > npm install --legacy-peer-deps --no-audit --no-fund
48
- > npm run build
49
- > dsh plugin --profile web add ./dsh-advisor-group-<版本>.tgz # 先 npm pack(版本号见 package.json)
50
- > ```
51
-
52
- > **桌面端**:桌面端应用的配置清单由应用自己管理,命令行 `dsh plugin --profile desktop …` 会被拒绝(这是官方设计,不是权限问题)。请在桌面端里安装:侧栏 **Plugins** → **Add plugin**,填入包名或本地 tarball 的绝对路径。
53
-
54
- ## 🚀 快速开始
55
-
56
- <img width="791" height="797" alt="2026_09_06_15_35_31" src="https://github.com/user-attachments/assets/52a5b9fe-1ee9-4980-9b97-73bf616f36eb" />
57
-
58
-
59
- 1. 重启 dsh web 并硬刷新浏览器(`Ctrl+Shift+R`)。
60
- 2. 打开 **设置 → 插件 → 顾问群**:配置顾问(提供商路由 + 模型,用「获取模型列表」拉取权威清单),按需调整 `maxRounds`、阈值与 UI 主题。
61
- 3. 直接开聊:
62
- - 提问时带 `@顾问群` 强制发起咨询,或
63
- - 直接提专业/不确定的问题——插件会按需自动升级。
64
-
65
- 模型可用工具:`ask_advisors`、`toggle_advisor_group`、`ask_session`。
66
-
67
- ## 🔗 跨会话提问
68
-
69
- 除了问顾问,插件还带一个工具 `ask_session`:把一个问题交给**另一个活着的会话**(同一宿主里的另一个窗口或标签),并唤醒它作答。
70
-
71
- - **怎么指定目标**:完整会话号、一字不差的标题,或者自然的名字都行——工作目录名就够(例如 `I:\极简遥控器\…` 下的会话,说「极简遥控器」即可)。唯一命中就直接问;好几个命中会列出候选(**正在运行**的、最近活跃的排前面),由你或模型挑一个;拿不准的时候它绝不猜。
72
- - **你会拿到什么**:从**投递回执**到对方会话**下一次整体空闲**之间,它产出的全部文字——这是「那段时间里对方说的话」,**不是**逐条对应的回答。超时(默认 180 秒,可调)只返回已经收到的内容,并且**不会打断对方**。
73
- - **界面上看到什么**:提问方一侧弹出聊天组卡片——先是「已投递,等待对方回应…」,然后出现对方的答案气泡和「📌 投递说明」(走的哪条通道、等到什么时候结束)。指定目标失败这类情况不弹卡片,只在工具行里如实报错。
74
- - **护栏**:跳数上限 2(防止两个会话来回接力)、不能问自己或子会话、同一会话同时只能等一个、单次载荷上限 32 KB;**任何情况下都不会取消对方的回合**。
75
- - **成本**:占用对方会话一次普通回合,按其自身模型计费;**不计入**每日咨询配额。
76
-
77
- 一句话用法:直接说「问一下极简遥控器那个会话:进度到哪了」。
78
-
79
- ## ⚙️ 配置项
80
-
81
- | 键 | 类型 | 默认 | 说明 |
82
- |---|---|---|---|
83
- | `enabled` | boolean | `true` | 启用顾问群 |
84
- | `discussion.maxRounds` | number | `2` | 自动深挖流水线总轮数(每轮 = 驱动追问 + 全体顾问接力) |
85
- | `discussion.maxAdvisorsPerCall` | number | `3` | 单次咨询最大顾问数(1–10) |
86
- | `discussion.autoDeepen` | boolean | `true` | 启用自动深挖流水线(驱动追问 + 综合结论) |
87
- | `discussion.driverModel` | object | – | 兜底驱动模型 `{provider, model}`(会话头信息不可读时) |
88
- | `discussion.advisorTimeoutMs` | number | `600000` | 单顾问调用超时(毫秒,1000–600000),双通道均生效 |
89
- | `discussion.driverTimeoutMs` | number | `600000` | 驱动模型生成超时(深挖追问/综合结论;毫秒,1000–1200000) |
90
- | `discussion.advisorTools` | string | `'readonly'` | **未单独设置时的全局默认**顾问工具调用范围:`readonly`(只读白名单 read/grep/glob/web_search/web_fetch…)|`all`(全部会话可见工具,含可写,慎用)|`off`(关闭)。仅直连通道(OpenAI/Anthropic)支持工具调用,DSH 内置通道的顾问需配 `baseURL`/`apiKey`/`apiKeyEnv` 直连(详情见「功能特性」)。 |
91
- | `advisors[].tools` | string | – | 每个顾问的**单独**工具调用范围覆盖(`readonly`/`all`/`off`;未设置时跟随全局默认);设置卡片上:可直连的顾问显示下拉,DSH 内置通道顾问显示“不可配置”。 |
92
- | `quota.enabled` | boolean | `true` | 启用每日咨询上限(成本安全阀) |
93
- | `quota.maxPerDay` | number | `50` | 每日 UTC 日周期内最多新咨询次数(1–100000);`quota.enabled=false` 时不生效 |
94
- | `trigger.requireClassifier` | boolean | `true` | 发起前先跑前置分类器 |
95
- | `trigger.allowWebFallback` | boolean | `true` | 分类器建议联网搜索时返回该提示 |
96
- | `trigger.confidenceThreshold` | number | `0.6` | 主模型置信度低于该值时升级 |
97
- | `trigger.jev.enabled` | boolean | `false` | 用外部 Jev 模型对非强制咨询做语义前置分类;Jev 不可用时回退本地规则分类器 |
98
- | `trigger.jev.provider` / `trigger.jev.model` | string | `'typesafe'` / `'jev-latest'` | Jev 路由(`typesafe` 或 `openrouter`)与模型;密钥用 `trigger.jev.apiKey`(secret)或 `trigger.jev.apiKeyEnv`;可选 `baseURL`、`timeoutMs`(默认 `10000`) |
99
- | `trigger.jev.confidenceThreshold` | number | `0.6` | Jev 判「该找顾问」为是(或 0–1 分数达到该值)时升级 |
100
- | `trigger.jev.highRiskThreshold` | number | 跟随 `jev.confidenceThreshold` | Jev 判「高风险」为是(或 0–1 分数达到该值)时标记高风险;未设置则跟随 `trigger.jev.confidenceThreshold` |
101
- | `trigger.jev.useEnglishState` | boolean | `false` | 判定改用主模型附带的英文概要(`questionEn`)而非中文原问;展示与会话记录仍为中文 |
102
- | `ui.theme` | string | `retro-green` | 卡片主题(retro-green / retro-amber / retro-blue) |
103
- | `ui.showTimestamps` | boolean | `true` | 显示时间戳 |
104
- | `ui.autoExpand` | boolean | `true` | 自动展开卡片 |
105
- | `advisors` | array | `[]` | 顾问列表(provider/model/baseURL/apiKey/apiKeyEnv/protocol…,key 均标 `role('secret')`) |
106
-
107
- > `discussion.parallel` 与 `discussion.stopOnConsensus` 为弃用遗留项,仅保留以兼容已存配置。
108
-
109
- ## 🧮 每日配额
110
-
111
- 插件自带一个成本安全阀:按 UTC 日历日统计**新咨询**次数,默认上限 50,可在设置页改数字或者直接关掉。它只拦新咨询——「▶ 继续聊天」续跑与追问都不计数。判断与自增在同一个同步块内完成,所以两个会话不可能同时挤过窗口;计数原子落盘在 `$DSH_HOME/storages/advisor-group/daily-guard.json`,重启不归零,UTC 日切自动清零。额度用尽时 `ask_advisors` 不启动,只返回一行说明;设置页实时显示「今日剩余咨询次数 X / Y」,关掉上限后仍然计数,只是不拦截。
112
-
113
- ## 💸 用量与成本
114
-
115
- 一次咨询不是「一次调用」,而是一串调用。默认配置(`maxRounds = 2`、最多 3 位顾问)下,一次新咨询约 9 次模型调用:2 轮 ×(1 次驱动模型追问 + 3 位顾问各 1 次)+ 1 次驱动模型综合结论。顾问若使用工具,每次工具往返还会再加一次模型调用(单个顾问上限 4 轮,另加一次强制文字作答),实际次数可能明显高于 9。
116
-
117
- 费用分别结算:顾问按你给它们配的通道与模型计费,驱动模型按当前会话的模型计费。想控成本,可以降 `maxRounds`、减少顾问数、给顾问设 `tools: 'off'`,再把每日上限设成你能接受的数字。中断后用「▶ 继续聊天」续跑只补问没答完的顾问,不会整场重来,代价低于重开一次。
118
-
119
- `ask_session` 不走咨询配额:它唤醒目标会话,对方用一次普通回合作答、按其自身模型计费,也不会被算作一次新咨询。
120
-
121
- ## 🔒 安全与隐私
122
-
123
- - 直连 API Key 可存于 DSH `settings.yaml`(标 secret,官方 `describe` 绝不回传浏览器);不想落盘请用 `apiKeyEnv` 环境变量模式。
124
- - `/advisor-group/*` 路由为**单机共享 token**(本地单用户使用),不是多用户鉴权;暴露局域网必须外层加反代鉴权。
125
- - 诊断端点服务端按存档 key 解析真实值再打供应商,并对目标 URL 做 https-only/loopback SSRF 校验;DNS rebinding 记为文档化已知边界。
126
- - 每日咨询上限(`quota.*` 可配置,默认 50、可关闭)持久化在 `$DSH_HOME/storages/advisor-group/daily-guard.json`(UTC 日切),重启不再归零。
127
- - 分类器影子模式:每次非强制分类追加一条观测样本(只读 `/advisor-group/shadow`),仅用于阈值调优,绝不干预行为。
128
- - **`advisorTools: 'all'` 属于高风险作用域**:会把会话可见的**全部工具**(含 `pwsh`/`bash`/`write`、配置/SSH 等可写/执行类)暴露给顾问模型(经官方守卫管线执行)。仅建议为可信的本地模型启用,并保证走 direct-http 通道;每次**非只读**工具调用都会以 `console.warn` 留审计痕迹。默认请用 `readonly`(read/grep/glob/web_search/web_fetch/scan_discover/list_imported_sessions)或 `off`。
129
-
130
- ## ⚠️ 已知限制
131
-
132
- - DSH 宿主进程硬崩溃时,已打开的卡片在刷新前可能仍显示 **LIVE**(现在会先出现断线提示);刷新后按会话日志恢复真实状态。
133
- - 风险提示**只看事实、不看措辞**:截断(顾问输出被超时或网络中断)与取消(本轮咨询被停止)两种。用户可在**已停止或已完成**的卡片与会话日志中看到,主模型随 `ask_advisors` 返回收到。顾问正文不做关键词扫描——早期那套「凭字眼猜有没有保留意见」的启发式已在 0.1.1 移除,原因是它连「没有任何风险」这样的否定句也会当成风险提示(盲测里 4 条纯否定句全部误报)。
134
- - 跨会话提问(`ask_session`)目前**没有设置开关**,工具在所有会话里可见,靠工具说明把使用限制在「用户明确要求时」;两个会话互相等待的情况尚未检测。
135
-
136
- ## 🛠️ 开发
137
-
138
- ```sh
139
- npm install --legacy-peer-deps --no-audit --no-fund
140
- npm run typecheck
141
- npm test # vitest 单测(含本地假 LLM 服务器上的供应商流式契约)
142
- npm run build # tsdown;客户端 bundle 禁用 minify: true
143
- ```
144
-
145
- ## 📄 许可证
146
-
147
- [Apache License 2.0](LICENSE) © 2026 dsh-advisor-group contributors.
1
+ # dsh-advisor-group
2
+
3
+ > 让 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH)的一个会话,既能**向其他模型借智慧**,也能**向其他会话借记忆**。
4
+
5
+ [English](README.en.md) · [安装](#兼容性与安装) · [快速开始](#快速开始) · [核心功能](#核心功能) · [配置参考](#配置参考) · [开发](#开发)
6
+
7
+ [![npm version](https://img.shields.io/npm/v/dsh-advisor-group.svg)](https://www.npmjs.com/package/dsh-advisor-group)
8
+ [![DSH plugin](https://img.shields.io/badge/DSH%20plugin-dsh--plugin-3f8cff)](https://github.com/topics/dsh-plugin)
9
+ [![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
10
+
11
+ | 能力 | 它帮你做什么 |
12
+ | --- | --- |
13
+ | **多模型会诊(顾问群)** | 面对专业、高风险或没有把握的问题,让多位专家模型接力回答,再由驱动模型汇总结论。 |
14
+ | **跨会话协作(全局蜂群)** | 直接询问另一个已有会话,复用它读过的代码、做过的排查和定下的约定,不必从零再来。 在本会话子代理功能之外,提供模型跨项目写作的能力。|
15
+ | **顾问团角色卡** | 给会话分配姓名和职责。之后直接说“去问小明”,不必记会话标题或 sessionId。 |
16
+
17
+ ## 兼容性与安装
18
+
19
+ | 项目 | 说明 |
20
+ | --- | --- |
21
+ | DSH | 当前开发基线为 `0.2.1-rc.3`;声明可安装的版本范围(peer)为 `>=0.1.7-rc.2 <0.3.0` |
22
+ | Node.js | 从源码构建时需要 `^22.19.0 || >=24.0.0` |
23
+ | 使用端 | DSH Web 与桌面端,共用同一份客户端代码包 |
24
+
25
+ 声明范围内的更早版本没有逐一实装验证。跨会话功能还需要宿主提供会话控制服务 `sessionController`;缺少该服务时,相关工具会明确报错,多模型会诊不受影响。
26
+
27
+ ### 安装 npm 发布版
28
+
29
+ DSH Web:
30
+
31
+ ```sh
32
+ dsh plugin --profile web add dsh-advisor-group
33
+ ```
34
+
35
+ 安装后按你原来的方式重启 DSH Web,并硬刷新浏览器(`Ctrl+Shift+R`)。
36
+
37
+ **桌面端**:在应用内打开 **Plugins → Add plugin**,输入 `dsh-advisor-group`。桌面端的配置清单由应用管理,`dsh plugin --profile desktop …` 会被官方拒绝,这不是权限不足。
38
+
39
+ ### 从源码安装 main
40
+
41
+ ```sh
42
+ git clone https://github.com/xingzhen199186/dsh-advisor-group.git
43
+ cd dsh-advisor-group
44
+ npm install --legacy-peer-deps --no-audit --no-fund
45
+ npm run build
46
+ npm pack
47
+
48
+ # 以 npm pack 实际生成的文件名为准
49
+ # 当前 package.json 版本为 0.1.5,因此文件名如下:
50
+ dsh plugin --profile web add ./dsh-advisor-group-0.1.5.tgz
51
+ ```
52
+
53
+ 桌面端安装源码包时,在 **Plugins → Add plugin** 中填写这个 `.tgz` 文件的绝对路径。安装后重启相应的 DSH 端。
54
+
55
+ ## 快速开始
56
+
57
+ ### 路径一:让多位模型一起会诊
58
+
59
+ 1. 打开 **设置 → 插件 → 顾问群**。
60
+ 2. 至少添加一位顾问,选择供应商路由和模型;可用「获取模型列表」读取该线路的模型清单。
61
+ 3. 在问题前加上 `@顾问群`,并交代必要背景。例如:
62
+
63
+ ```text
64
+ @顾问群 请评审这个插件的跨会话协作方案。
65
+ 背景:DSH Web 与桌面端共用一份代码,要求不自动投递、不猜测目标会话。
66
+ ```
67
+
68
+ `@顾问群` 会强制发起会诊。普通专业问题也可以由主模型按规则升级;同一问题连续三次未解决,或主模型给出的置信度低于阈值,也会触发会诊。
69
+
70
+ <img width="720" alt="顾问群设置页:按使用路径分为启用与每日配额、顾问列表、会诊行为、触发与分类、全局蜂群和高级,默认全部折叠" src="https://raw.githubusercontent.com/xingzhen199186/dsh-advisor-group/main/docs/images/advisor-group-settings.png" />
71
+
72
+ 设置页按使用路径分区,默认全部折叠;展开哪一节,就在那一节底部保存。
73
+
74
+ ### 路径二:按名字询问另一个会话
75
+
76
+ 1. 打开任意会话里的 **「顾问团」**标签页;标签栏空间不足时,它可能位于「…」菜单中。
77
+ 2. 给目标会话填写「身份姓名」和「主要负责」,再点「加入顾问团」或「保存」。也可以点「用主模型生成」,检查建议后逐条保存,或用「保存全部更改」一次提交。
78
+ 3. 回到对话,直接说:
79
+
80
+ ```text
81
+ 去问一下小明:顾问团角色卡今天完成了哪些改动?
82
+ ```
83
+
84
+ 也可以一次问多位成员:
85
+
86
+ ```text
87
+ 同时问小明和阿龙:分别检查这个方案在桌面端和 Web 端有没有遗漏,并汇总两边结论。
88
+ ```
89
+
90
+ 自动生成的内容只会填入草稿;**保存后才生效,已有卡不会被覆盖**。原来的会话标题、目录名和 sessionId 仍然可用。
91
+
92
+ ## 核心功能
93
+
94
+ ### 多模型会诊:自动深挖,而不是只问一遍
95
+
96
+ 一次 `ask_advisors` 会完成整场讨论:
97
+
98
+ ```text
99
+ 原问题
100
+ → 第 1 轮:顾问 A → 顾问 B(看过 A)→ 顾问 C(看过 A、B)
101
+ → 后续轮:驱动模型提出更深追问 → 顾问按同样顺序接力
102
+ → 驱动模型生成综合结论
103
+ ```
104
+
105
+ <img width="865" height="983" alt="顾问群会诊卡片:按行动、思考、工具调用和正文逐步展示顾问回答" src="https://github.com/user-attachments/assets/5660ce94-70f0-42ed-84e4-9f926d1e2c64" />
106
+
107
+ - **讨论轮数可控**:`maxRounds` 为 1–5,默认 2。关闭 `autoDeepen` 后,后续轮次重复使用原问题,综合结论仍会生成。
108
+ - **驱动模型复用当前会话线路**:负责深挖追问与综合结论,不需要另配一套模型;无法读取当前线路时使用 `discussion.driverModel` 兜底。
109
+ - **顾问可以使用会话工具**:默认只允许只读工具,调用过程进入卡片;最多 4 轮工具交互后必须用文字作答。工具范围可全局设置,也可按顾问覆盖。
110
+ - **流式卡片保留过程**:绿色 CRT 卡片按 `📋 行动 → 💭 思考 → ⛭ 工具 → 📄 正文`展示。思考和工具详情默认折叠,正文默认展开。
111
+ - **停止后可以从断点继续**:人工停止或宿主重启后,「▶ 继续聊天」只补未完成的顾问和轮次,不重新询问已经完成的顾问。
112
+ - **可选 Jev 前置判断**:默认关闭。开启后可判断是否该找顾问、是否高风险、是否更适合联网;Jev 不可用时回退到本地规则分类器。
113
+ - **12 个平台、28 个供应商预设**:DeepSeek、月之暗面 Kimi、Kimi Code、阿里云百炼、智谱 AI、OpenAI、Claude、Gemini、硅基流动、AIHubMix、OpenRouter、OpenCode Go。
114
+
115
+ ### 顾问团:给会话一个稳定身份
116
+
117
+ 会话标题适合描述窗口,却不一定适合长期称呼。顾问团把「姓名 + 职责」绑定到会话 id,并保存在本机 `$DSH_HOME/storages/advisor-group/corps.json`;它不会改写会话标题。
118
+
119
+ <img width="760" alt="顾问团面板:每个可见会话一行,显示角色姓名、职责、复制姓名和保存按钮" src="https://raw.githubusercontent.com/xingzhen199186/dsh-advisor-group/main/docs/images/advisor-corps-panel.png" />
120
+
121
+ - 姓名全局唯一,不区分大小写;最长 40 个字符。职责最长 200 个字符。
122
+ - 「用主模型生成」使用**当前打开会话的模型**,每次最多为 12 个未分配会话生成建议,只填草稿,不自动保存。
123
+ - 可逐条修改、复制姓名、批量保存或移除。已归档、被排除、离开工作区或已不存在的会话,其角色卡会归入「未挂接」,可保留或删除。
124
+ - `list_sessions` 会显示角色姓名和职责;`ask_session`、`ask_sessions` 可以直接使用这个角色名,精确角色名优先于同名会话标题。
125
+
126
+ ### 跨会话协作:问一个,也可以问一组
127
+
128
+ - **单人会话提问**:`ask_session` 默认同步等待,也可用 `detach: true` 立即返回 `askId`,稍后通过 `ask_result` 读取。
129
+ - **批量提问**:`ask_sessions` 一次向 1–8 个明确目标发送同一个问题。`mode: 'all'` 等全部目标结束;`mode: 'any'` 在首个目标结束后返回,其余目标继续完成并写入各自记录。
130
+ - **答案自动回送**:`swarm.deliverBack` 默认开启。完成(`done`)的答案会回送到提问会话;超时和出错不会自动回送。批量提问把完成答案合并为一条回送消息。
131
+ - **结果可追查**:每个被投递的目标都有独立 `askId`。异步记录可能是 `waiting`、`done`、`timeout`、`error` 或 `interrupted`;最后一个状态表示宿主重启使等待未能完成。
132
+ - **不猜目标**:`ask_session` 未点名时,路由只返回候选,不自动投递。`ask_sessions` 不做路由;无法解析、同名歧义或被排除的目标会列出跳过原因。
133
+ - **有明确的协作护栏**:最多 2 跳中转;不能问自己或子代理会话;同一提问会话同时只等待一个 `ask_session` 请求;问题和背景合计上限 32,000 字节;等待超时不会取消目标会话的回合。
134
+
135
+ > **返回内容的准确含义**:工具取得的是目标会话从「投递回执」到「下一次整体空闲」之间说过的全部内容,不保证是逐条对应你那个问题的一段答案。结果中的 `status`(`ok` / `partial` / `failed`)用于说明这次收集的可靠性。
136
+
137
+ ## 模型工具参考
138
+
139
+ 这些工具由主模型在会话中调用,**不是斜杠命令,也不需要你手写工具参数**。跨会话工具只应在你明确要求询问其他会话或窗口时使用。
140
+
141
+ | 工具 | 用途 |
142
+ | --- | --- |
143
+ | `ask_advisors` | 发起多模型会诊,或用 `sessionId + followUp` 追加一轮讨论 |
144
+ | `ask_session` | 询问一个已有会话;支持同步等待、异步投递和候选路由 |
145
+ | `ask_sessions` | 向 1–8 个明确目标批量提问;支持 `all` / `any` 两种收集方式 |
146
+ | `list_sessions` | 只读列出会话标题、目录、活跃状态及顾问团姓名和职责;不唤醒会话 |
147
+ | `ask_result` | 按 `askId` 读取异步结果,或查看当前会话最近发起的提问 |
148
+ | `toggle_advisor_group` | 启停多模型会诊功能,并持久化开关状态 |
149
+
150
+ ## 配置参考
151
+
152
+ 日常使用时,通常只需要调整以下几项:
153
+
154
+ | 配置键 | 默认值 | 什么时候调整 |
155
+ | --- | --- | --- |
156
+ | `discussion.maxRounds` | `2` | 想减少成本时调低;想讨论更深时调高,最高 5 |
157
+ | `discussion.maxAdvisorsPerCall` | `3` | 控制每次参与会诊的顾问人数,范围 1–10 |
158
+ | `discussion.advisorTools` | `'readonly'` | 改为 `'off'` 禁止顾问用工具;`'all'` 仅用于充分信任的场景 |
159
+ | `quota.enabled` / `quota.maxPerDay` | `true` / `50` | 设置每日新会诊上限;关闭上限后仍统计次数 |
160
+ | `swarm.defaultMode` | `'wait'` | 改为 `'detach'`,让跨会话提问默认异步投递 |
161
+ | `swarm.defaultWaitMs` | `180000` | 调整默认等待上限,范围 1000–600000 毫秒 |
162
+ | `swarm.deliverBack` | `true` | 关闭后,完成答案只通过 `ask_result` 读取,不自动回送 |
163
+
164
+ <details>
165
+ <summary><strong>展开完整配置键参考</strong></summary>
166
+
167
+ ### 讨论与顾问
168
+
169
+ | 配置键 | 类型 | 默认值 | 说明 |
170
+ | --- | --- | --- | --- |
171
+ | `enabled` | boolean | `true` | 启用多模型会诊 |
172
+ | `discussion.maxRounds` | number | `2` | 会诊总轮数,1–5 |
173
+ | `discussion.maxAdvisorsPerCall` | number | `3` | 单次会诊最大顾问数,1–10 |
174
+ | `discussion.autoDeepen` | boolean | `true` | 后续轮次是否由驱动模型生成更深追问;关闭后重复原问题,结论仍生成 |
175
+ | `discussion.driverModel` | object | – | 当前会话线路不可读时使用的 `{ provider, model }` |
176
+ | `discussion.advisorTimeoutMs` | number | `600000` | 单顾问超时,1000–600000 毫秒 |
177
+ | `discussion.driverTimeoutMs` | number | `600000` | 深挖追问或综合结论的超时,1000–1200000 毫秒 |
178
+ | `discussion.advisorTools` | string | `'readonly'` | 顾问工具默认范围:`readonly` / `all` / `off` |
179
+ | `advisors` | array | `[]` | 顾问列表;包含 `provider`、`model`、`systemPrompt`,以及可选的 `baseURL`、`apiKey`、`apiKeyEnv`、`protocol` 等 |
180
+ | `advisors[].tools` | string | – | 单顾问工具范围,覆盖全局默认;未设置时跟随 `discussion.advisorTools` |
181
+ | `advisors[].thinking` | string | – | `enabled` / `disabled`;未设置时跟随供应商默认 |
182
+ | `advisors[].reasoningEffort` | string | – | `off` / `low` / `high` / `max`;未设置时跟随供应商或模型默认 |
183
+ | `advisors[].temperature` | number | – | 采样温度,0–2 |
184
+ | `advisors[].maxTokens` | number | – | 单次回答的 token 上限,至少 1 |
185
+ | `advisors[].authMode` | string | – | Anthropic 直连的鉴权头:`x-api-key` / `bearer` |
186
+ | `advisors[].avatar` | string | – | 卡片上的短头像,可使用 emoji 或 ASCII |
187
+
188
+ 顾问工具调用仅直连的 OpenAI / Anthropic 通道支持。DSH 内置通道可复用宿主凭据进行普通回答,但不支持这里的顾问工具循环。
189
+
190
+ ### 触发判断与 Jev
191
+
192
+ | 配置键 | 类型 | 默认值 | 说明 |
193
+ | --- | --- | --- | --- |
194
+ | `trigger.requireClassifier` | boolean | `true` | 非强制会诊发起前先进行前置分类 |
195
+ | `trigger.allowWebFallback` | boolean | `true` | 分类器认为更适合联网时,返回不启动会诊的提示 |
196
+ | `trigger.confidenceThreshold` | number | `0.6` | 主模型置信度低于此值时允许升级,范围 0–1 |
197
+ | `trigger.jev.enabled` | boolean | `false` | 使用 Jev 做语义前置分类;失败时回退本地规则 |
198
+ | `trigger.jev.provider` / `trigger.jev.model` | string | `'typesafe'` / `'jev-latest'` | Jev 线路与模型;线路也可设为 `openrouter` |
199
+ | `trigger.jev.baseURL` | string | – | 可选自定义 Jev 地址 |
200
+ | `trigger.jev.apiKey` / `trigger.jev.apiKeyEnv` | string | – | Jev 密钥或保存密钥的环境变量名;密钥字段按 secret 处理 |
201
+ | `trigger.jev.timeoutMs` | number | `10000` | Jev 请求超时,1000–60000 毫秒 |
202
+ | `trigger.jev.confidenceThreshold` | number | `0.6` | 判定需要顾问的阈值 |
203
+ | `trigger.jev.highRiskThreshold` | number | 跟随上一项 | 高风险判定阈值;未设置时跟随 `trigger.jev.confidenceThreshold` |
204
+ | `trigger.jev.useEnglishState` | boolean | `false` | 开启后,Jev 使用调用方提供的英文概要 `questionEn`;卡片和会话记录仍保留原始问题 |
205
+
206
+ ### 全局蜂群
207
+
208
+ | 配置键 | 类型 | 默认值 | 说明 |
209
+ | --- | --- | --- | --- |
210
+ | `swarm.enabled` | boolean | `true` | 跨会话总开关;关闭后四个跨会话工具会明确拒绝调用 |
211
+ | `swarm.defaultMode` | string | `'wait'` | `ask_session` 默认同步等待或异步投递:`wait` / `detach` |
212
+ | `swarm.defaultWaitMs` | number | `180000` | 默认等待上限,1000–600000 毫秒 |
213
+ | `swarm.resultTtlHours` | number | `24` | 异步结果保留时间,1–720 小时 |
214
+ | `swarm.deliverBack` | boolean | `true` | 自动回送 `done` 答案;`timeout` / `error` 不自动回送 |
215
+ | `swarm.rosterIncludeSubagents` | boolean | `false` | 名录是否显示子代理;这不改变投递工具禁止以子代理为目标的规则 |
216
+ | `swarm.routingEnabled` | boolean | `true` | `ask_session` 未点名时是否按问题给出候选;只给候选,不自动投递 |
217
+ | `swarm.routingTopN` | number | `3` | 候选数量,1–8 |
218
+ | `swarm.routingEngine` | string | `'local'` | `local` 本地排序,或 `jev` 重排闭合候选;Jev 失败时回退本地 |
219
+ | `swarm.routingAsk` | string | `'gated'` | 是否建议跨会话提问:`off` / `gated` / `always`;建议不等于投递 |
220
+ | `swarm.routingExclude` | string[] | `[]` | 不参与蜂群的会话;不出现在名录或候选中,被点名也会拒绝 |
221
+
222
+ ### 历史兼容项
223
+
224
+ `discussion.parallel` 与 `discussion.stopOnConsensus` 已弃用,只为读取旧配置保留。
225
+
226
+ `ui.theme`、`ui.showTimestamps`、`ui.autoExpand` 同样是历史配置字段;当前客户端没有读取它们,修改这些值不会改变卡片外观或展开行为。当前卡片为绿色 CRT 样式,思考与工具详情默认折叠。
227
+
228
+ </details>
229
+
230
+ ## 用量、配额与成本
231
+
232
+ 完成 `R` 轮讨论、每轮有 `N` 位顾问且没有工具调用时,一场会诊通常包含 **`R × (N + 1)` 次模型调用**:`R × N` 次顾问回答、`R - 1` 次深挖追问,以及 1 次综合结论。按默认轮数 `R = 2`、每场实际有 3 位顾问参与计算时为 8 次。
233
+
234
+ 实际费用还取决于以下行为:
235
+
236
+ - 顾问的工具往返会增加模型调用;驱动模型与各位顾问按各自线路分别计费。
237
+ - 「用主模型生成」角色卡会对当前会话模型发起调用;Jev 分类或路由开启后也按相应线路计费。
238
+ - 跨会话提问不占用顾问会诊配额,但会唤醒目标会话,消耗目标会话自己的模型额度。批量提问按各个目标分别计算。
239
+
240
+ 每日配额按 **UTC 日历日**统计新发起的会诊,默认 50 次。续跑、后续追问和跨会话提问不占用这项配额。计数保存在 `$DSH_HOME/storages/advisor-group/daily-guard.json`;关闭上限后仍计数,但不拦截。需要控制成本时,可减少轮数或顾问人数、关闭顾问工具,并设置每日上限。
241
+
242
+ ## 安全与隐私
243
+
244
+ - **密钥不回显**:直连 API Key 保存在本机 DSH 配置中,按 `SecretField` 语义处理,不返回浏览器。不希望密钥写入配置时,可使用 `apiKeyEnv`。
245
+ - **本地路由有令牌**:`/advisor-group/*` 使用每次启动生成的共享 token,面向本地单用户场景。需要暴露到局域网或公网时,必须在外层增加反向代理鉴权。
246
+ - **诊断请求有限制**:模型列表和连接测试在服务端请求供应商,并校验目标 URL、协议和重定向。DNS rebinding 仍是已知的架构边界。
247
+ - **谨慎使用 `advisorTools: 'all'`**:它会把当前会话所有可见工具交给顾问,包括写文件和执行命令;调用仍经过 DSH 的工具管线与权限守卫。日常使用建议保持 `readonly` 或 `off`,非只读工具调用会写入警告日志。
248
+ - **跨会话内容会留痕**:问题和背景会永久写入目标会话日志,因此只发送必要信息。角色卡生成会把会话标题、工作目录和活跃提示交给当前主模型;角色卡本身保存在本机,不包含 API Key。
249
+ - **本地状态集中保存**:会诊快照、异步提问记录、角色卡和配额数据位于 `$DSH_HOME/storages/advisor-group/`。分类器影子日志仅用于阈值调优,不参与运行决策。
250
+
251
+ ## 已知限制
252
+
253
+ - DSH 宿主突然崩溃时,未刷新的卡片可能仍显示 **LIVE**;页面刷新后会根据持久化日志恢复真实状态。前端已有断线提示。
254
+ - 风险提示只根据客观状态生成:超时或网络中断造成的截断,以及人工停止造成的取消。插件不再通过扫描顾问正文里的“风险”“不确定”等词来猜测风险。
255
+ - 跨会话工具目前没有按单个会话独立隐藏的开关。`swarm.enabled` 开启时四个工具对会话可见,关闭后调用会明确拒绝;两个会话互相等待的死锁目前也不会被专门检测。
256
+ - 角色卡面板最多显示 50 个可见会话;自动生成每次最多处理 12 个未分配会话,可以再次生成以继续补齐。
257
+
258
+ ## 开发
259
+
260
+ ```sh
261
+ npm install --legacy-peer-deps --no-audit --no-fund
262
+ npm run typecheck
263
+ npm test
264
+ npm run build
265
+ npm pack --dry-run
266
+ ```
267
+
268
+ 测试使用 Vitest,包含供应商流式协议、跨会话投递与等待、角色卡、设置脱敏和恢复边界。构建使用 tsdown;客户端 bundle **不能使用 `minify: true`**,否则会破坏启动守卫所依赖的插件 id 形式。
269
+
270
+ - [更新记录](CHANGELOG.md)
271
+ - [问题反馈](https://github.com/xingzhen199186/dsh-advisor-group/issues)
272
+ - [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)
273
+
274
+ ## 许可证
275
+
276
+ [Apache License 2.0](LICENSE) © 2026 dsh-advisor-group contributors.