dsh-advisor-group 0.1.0 → 0.1.2
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 +132 -100
- package/README.zh.md +135 -100
- package/lib/client.js +855 -116
- package/lib/index.d.mts +108 -1
- package/lib/index.mjs +3191 -479
- package/package.json +42 -28
package/README.md
CHANGED
|
@@ -1,100 +1,132 @@
|
|
|
1
|
-
# dsh-advisor-group
|
|
2
|
-
|
|
3
|
-
> A [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH) plugin that lets the main model consult **multiple expert advisor models** in a retro chat-group card — for professional, long-tail world-knowledge, high-risk, or uncertain questions.
|
|
4
|
-
|
|
5
|
-
[](https://github.com/topics/dsh-plugin)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
18
|
-
- **
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
|
67
|
-
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
| `
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
##
|
|
99
|
-
|
|
100
|
-
|
|
1
|
+
# dsh-advisor-group
|
|
2
|
+
|
|
3
|
+
> A [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH) plugin that lets the main model consult **multiple expert advisor models** in a retro chat-group card — for professional, long-tail world-knowledge, high-risk, or uncertain questions.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/topics/dsh-plugin)
|
|
6
|
+
|
|
7
|
+
📖 [中文文档 / Chinese: README.zh.md](README.zh.md)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<img width="865" height="983" alt="1788679983177" src="https://github.com/user-attachments/assets/dad2f2be-acf6-41d7-b61a-c11596e48408" />
|
|
12
|
+
|
|
13
|
+
## ✨ Features
|
|
14
|
+
|
|
15
|
+
- **Auto-deepen consultation pipeline** — one `ask_advisors` call runs up to `maxRounds` rounds automatically: each round is a *driver deep-question → advisor A → advisor B (sees A) → advisor C (sees A+B) → …* sequential relay, closed by a driver-generated synthesis conclusion.
|
|
16
|
+
- **Zero-config driver model** — the driver formulation of deep follow-ups reuses the current agent's provider/model, so no extra API key or model setup is needed; it falls back to `discussion.driverModel` when the session header is unavailable.
|
|
17
|
+
- **Three ways to activate** — `@顾问群` mention (force-start), same question repeated 3 times without resolution, or main-model self-assessed confidence below the threshold.
|
|
18
|
+
- **Optional Jev semantic pre-classification (off by default)** — when `trigger.jev.enabled` is on, a configured Jev model judges non-force-started consultations first (escalation / high-risk / web-search fit, thresholds under `trigger.jev.*`); if Jev is unavailable the local rules-based classifier still decides. With `trigger.jev.useEnglishState`, the judge reads the caller-supplied English gist (`questionEn`) instead of the Chinese question — display and session records stay Chinese.
|
|
19
|
+
- **Retro CRT chat cards** — green/amber/blue CRT themes, scanlines, LIVE/DONE headers, auto-expanded thinking panel with auto-scroll; advisor Markdown rendered with a link-protocol whitelist (headings, lists, code, quotes, links, tables).
|
|
20
|
+
- **Ask another session (`ask_session`)** — hand one question to another live session — by exact session id, exact title, or a natural partial name such as the workspace name (`极简遥控器`) — and read what that session said between the delivery receipt and its next whole-session idle. The result is explicitly **not** a one-to-one reply, and the asking side renders the exchange in the same retro chat-group card. Guards: hop ≤ 2, no self/subagent target, one wait per session, a 32 KB payload budget; the target's turn is never cancelled.
|
|
21
|
+
- **Provider presets (11 platforms · 26 presets)** — DeepSeek, Moonshot Kimi, Kimi Code, Aliyun Bailian, Zhipu AI, OpenAI, Claude, Gemini, SiliconFlow, AIHubMix, OpenRouter (OpenAI/Anthropic-compatible variants included).
|
|
22
|
+
- **Security-minded by design** — API keys use official `SecretField` semantics (never returned to the browser; `apiKeysByProvider` key history is server-side only), SSRF-guarded diagnostics (https-only / loopback, no IP literals, no redirects), per-boot token auth on `/advisor-group/*` routes, and an atomic **configurable daily consultation cap** (default 50, can be disabled) persisted across restarts.
|
|
23
|
+
- **Runtime toggle** — `toggle_advisor_group` enables/disables the plugin and persists the flag to settings.
|
|
24
|
+
|
|
25
|
+
## ✅ Compatibility
|
|
26
|
+
|
|
27
|
+
| Surface | Status |
|
|
28
|
+
|---|---|
|
|
29
|
+
| Harness | DeepSeek Harness `0.1.7-rc.2` → `0.2.x` (incl. `0.2.0-rc.1`) |
|
|
30
|
+
| Node | `^22.19.0 \|\| >=24.0.0` |
|
|
31
|
+
| Platforms | DSH Web and the desktop app (same client bundle) + headless host logic |
|
|
32
|
+
|
|
33
|
+
## 📦 Installation
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
# 1. Install the plugin (one package, everything included)
|
|
37
|
+
dsh plugin --profile web add dsh-advisor-group
|
|
38
|
+
|
|
39
|
+
# 2. Restart DSH web
|
|
40
|
+
npx @deepseek-ai/dsh web
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
> **From source (development)**
|
|
44
|
+
> ```sh
|
|
45
|
+
> npm install --legacy-peer-deps --no-audit --no-fund
|
|
46
|
+
> npm run build
|
|
47
|
+
> dsh plugin --profile web add ./dsh-advisor-group-<version>.tgz # after npm pack (version from package.json)
|
|
48
|
+
> ```
|
|
49
|
+
|
|
50
|
+
> **Desktop app**: the desktop app owns its own profile — `dsh plugin --profile desktop …` is refused by design, not by permissions. Install from inside the app instead: **Plugins** in the sidebar → **Add plugin** → enter the package name or the absolute path of a local tarball.
|
|
51
|
+
|
|
52
|
+
## 🚀 Quick start
|
|
53
|
+
|
|
54
|
+
<img width="791" height="797" alt="image" src="https://github.com/user-attachments/assets/5fba07bc-8c36-40f1-b423-d206aa495192" />
|
|
55
|
+
|
|
56
|
+
1. Restart DSH web and hard-refresh the browser (`Ctrl+Shift+R`).
|
|
57
|
+
2. Go to **Settings → Plugins → Advisor Group**: configure your advisors (provider route + model; use *获取模型列表* to pull the authoritative model list) and tune `maxRounds`, thresholds, and the UI theme.
|
|
58
|
+
3. Just start a conversation:
|
|
59
|
+
- type `@顾问群` in your question to force a consultation, or
|
|
60
|
+
- ask a professional/uncertain question — the plugin escalates automatically when appropriate.
|
|
61
|
+
|
|
62
|
+
`ask_advisors` tools available to the model: `ask_advisors`, `toggle_advisor_group`, `ask_session`.
|
|
63
|
+
|
|
64
|
+
## ⚙️ Configuration
|
|
65
|
+
|
|
66
|
+
| Key | Type | Default | Description |
|
|
67
|
+
|---|---|---|---|
|
|
68
|
+
| `enabled` | boolean | `true` | Enable advisor group |
|
|
69
|
+
| `discussion.maxRounds` | number | `2` | Total rounds of the auto-deepen pipeline (each round = driver question + all advisors in relay) |
|
|
70
|
+
| `discussion.maxAdvisorsPerCall` | number | `3` | Max advisors per call (1–10) |
|
|
71
|
+
| `discussion.autoDeepen` | boolean | `true` | Run the auto-deepen pipeline (driver follow-ups + final synthesis) |
|
|
72
|
+
| `discussion.driverModel` | object | – | Fallback driver model `{provider, model}` when the session header cannot be read |
|
|
73
|
+
| `discussion.advisorTimeoutMs` | number | `600000` | Per-advisor call timeout (ms, 1000–600000), applied to both channels |
|
|
74
|
+
| `discussion.driverTimeoutMs` | number | `600000` | Driver generation timeout (deep-question / conclusion; ms, 1000–1200000) |
|
|
75
|
+
| `discussion.advisorTools` | string | `'readonly'` | Global default advisor tool scope when an advisor sets no own `tools`: `readonly` / `all` (every session-visible tool incl. writable — elevated risk, see Security) / `off`. Tool calling needs the direct-http (OpenAI/Anthropic) channel. |
|
|
76
|
+
| `quota.enabled` | boolean | `true` | Enable the daily new-consultation cap (cost safety valve) |
|
|
77
|
+
| `quota.maxPerDay` | number | `50` | Max new consultations per UTC day (1–100000); ignored when `quota.enabled` is `false` |
|
|
78
|
+
| `trigger.requireClassifier` | boolean | `true` | Run the pre-classifier before starting |
|
|
79
|
+
| `trigger.allowWebFallback` | boolean | `true` | Allow classifier to recommend web search |
|
|
80
|
+
| `trigger.confidenceThreshold` | number | `0.6` | Escalate when main-model confidence is below this |
|
|
81
|
+
| `trigger.jev.enabled` | boolean | `false` | Use the external Jev model for semantic pre-classification of non-forced consultations; falls back to the local rules-based classifier when Jev is unavailable |
|
|
82
|
+
| `trigger.jev.provider` / `trigger.jev.model` | string | `'typesafe'` / `'jev-latest'` | Jev route (`typesafe` or `openrouter`) and model; key via `trigger.jev.apiKey` (secret) or `trigger.jev.apiKeyEnv`; optional `baseURL`, `timeoutMs` (default `10000`) |
|
|
83
|
+
| `trigger.jev.confidenceThreshold` | number | `0.6` | Escalate when Jev answers `needsAdvisor` yes (or its 0–1 score reaches this value) |
|
|
84
|
+
| `trigger.jev.highRiskThreshold` | number | follows `jev.confidenceThreshold` | Flag high-risk when Jev answers `high_risk` yes (or its 0–1 score reaches this value); unset = follows `trigger.jev.confidenceThreshold` |
|
|
85
|
+
| `trigger.jev.useEnglishState` | boolean | `false` | Judge using the caller-supplied English gist (`questionEn`) instead of the Chinese question; display and session records stay Chinese |
|
|
86
|
+
| `ui.theme` | string | `retro-green` | Chat card theme (`retro-green` / `retro-amber` / `retro-blue`) |
|
|
87
|
+
| `ui.showTimestamps` | boolean | `true` | Show timestamps |
|
|
88
|
+
| `ui.autoExpand` | boolean | `true` | Auto-expand card |
|
|
89
|
+
| `advisors[].tools` | string | – | Per-advisor tool-scope override (`readonly`/`all`/`off`; unset follows the global default) |
|
|
90
|
+
| `advisors` | array | `[]` | Advisor list (provider/model/baseURL/apiKey/apiKeyEnv/protocol…, keys are `role('secret')`) |
|
|
91
|
+
|
|
92
|
+
> `discussion.parallel` and `discussion.stopOnConsensus` are deprecated leftovers kept only for stored-config compatibility.
|
|
93
|
+
|
|
94
|
+
## 🧮 Daily quota
|
|
95
|
+
|
|
96
|
+
The plugin ships a cost safety valve: it counts **new consultations** per UTC calendar day, default cap 50, changeable or switchable on the settings page. Only new consultations count — resuming (「▶ continue」) and follow-ups never consume quota. The check and the increment happen inside one synchronous block, so two consultations cannot slip through the same window; the counter is written atomically to `$DSH_HOME/storages/advisor-group/daily-guard.json`, survives restarts, and resets at the UTC day boundary. When the cap is reached `ask_advisors` does not start and returns a one-line explanation; the settings page shows "today's remaining consultations X / Y", and with the cap off the plugin still counts for display without blocking.
|
|
97
|
+
|
|
98
|
+
## 💸 Usage and cost
|
|
99
|
+
|
|
100
|
+
One consultation is not one call but a chain of them. With the defaults (`maxRounds = 2`, at most 3 advisors) a new consultation costs roughly 9 model calls: 2 rounds × (1 driver follow-up + 1 per advisor) + 1 driver synthesis. Advisors that use tools add one more model call per tool round (at most 4 rounds per advisor plus one forced text-only round), so the real count can be noticeably higher than 9.
|
|
101
|
+
|
|
102
|
+
Billing follows each channel: advisors bill on the route and model you gave them, while the driver bills on the current session's model. To keep costs down, lower `maxRounds`, configure fewer advisors, set `tools: 'off'` for advisors, and pick a daily cap you are comfortable with. Resuming after an interruption ("▶ continue") only asks the advisors that had not finished, so it costs less than starting over.
|
|
103
|
+
|
|
104
|
+
`ask_session` is outside the consultation quota: it wakes the target session, which answers with one ordinary turn billed on that session's own model, and it never counts as a new consultation.
|
|
105
|
+
|
|
106
|
+
## 🔒 Security & privacy
|
|
107
|
+
|
|
108
|
+
- Direct API keys can be stored in the DSH `settings.yaml` (marked secret, never returned to the browser by `describe`); prefer `apiKeyEnv` (env-var mode) if you don't want keys on disk.
|
|
109
|
+
- `/advisor-group/*` routes use a per-boot shared token for local single-user use — **not** multi-user auth. Add a reverse-proxy auth layer before LAN exposure.
|
|
110
|
+
- Diagnostics endpoints resolve the real key server-side and validate the target URL against an https-only / loopback SSRF guard; DNS-rebinding protection is a documented out-of-scope limitation.
|
|
111
|
+
- The daily consultation cap (configurable via `quota.*`; default 50; can be disabled) is persisted to `$DSH_HOME/storages/advisor-group/daily-guard.json` (UTC day key), so restarts don't reset it.
|
|
112
|
+
- Classifier shadow mode appends one observation sample per non-forced classification (read-only `/advisor-group/shadow`), used for threshold tuning only — never influences behavior.
|
|
113
|
+
- **`advisorTools: 'all'` is an elevated-risk scope.** It exposes every session-visible tool to the advisor models, including writable/execution ones (`pwsh`, `bash`, `write`, config/SSH tools), executed through the official guarded pipeline. Only enable it for advisors you trust (e.g., your own local models), keep them on the direct-http channel, and note that every non-read-only invocation is logged with `console.warn` for audit. Prefer the default `readonly` (read/grep/glob/web_search/web_fetch/scan_discover/list_imported_sessions) or `off`.
|
|
114
|
+
|
|
115
|
+
## ⚠️ Known limitations
|
|
116
|
+
|
|
117
|
+
- A hard crash of the DSH host can leave an already-open card showing **LIVE** until the page is refreshed (a disconnect notice now appears); refresh restores the true state from the session log.
|
|
118
|
+
- Risk notes are **fact-based, never text-based**: a consultation reports truncation (an advisor stream cut off by timeout or network) and cancellation/stop. Users see them on **stopped or completed** cards and in the session log, and the main model receives them in the `ask_advisors` result. Advisor prose is not scanned for keywords — the earlier text heuristic was removed in 0.1.1 because it also fired on plain negations such as 「没有任何风险」.
|
|
119
|
+
- Cross-session asking (`ask_session`) has no settings switch yet, so the tool is visible in every session and relies on its own description to keep use to explicit user requests; two sessions asking each other at the same time is not detected.
|
|
120
|
+
|
|
121
|
+
## 🛠️ Development
|
|
122
|
+
|
|
123
|
+
```sh
|
|
124
|
+
npm install --legacy-peer-deps --no-audit --no-fund
|
|
125
|
+
npm run typecheck
|
|
126
|
+
npm test # vitest suite, incl. provider streaming contracts against a local fake LLM server
|
|
127
|
+
npm run build # tsdown; client bundle must NOT be built with minify: true
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## 📄 License
|
|
131
|
+
|
|
132
|
+
[Apache License 2.0](LICENSE) © 2026 dsh-advisor-group contributors.
|
package/README.zh.md
CHANGED
|
@@ -1,100 +1,135 @@
|
|
|
1
|
-
# dsh-advisor-group
|
|
2
|
-
|
|
3
|
-
> [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH)插件:主模型在遇到**专业、长尾世界知识、高风险或不确定**的问题时,召集多位**专家顾问模型**,在复古 CRT 聊天组卡片中真流式对话。
|
|
4
|
-
|
|
5
|
-
[](https://github.com/topics/dsh-plugin)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
|
70
|
-
|
|
71
|
-
| `
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
1
|
+
# dsh-advisor-group
|
|
2
|
+
|
|
3
|
+
> [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH)插件:主模型在遇到**专业、长尾世界知识、高风险或不确定**的问题时,召集多位**专家顾问模型**,在复古 CRT 聊天组卡片中真流式对话。
|
|
4
|
+
|
|
5
|
+
[](https://github.com/topics/dsh-plugin)
|
|
6
|
+
|
|
7
|
+
[English: README.md](README.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
|
+
| 键 | 类型 | 默认 | 说明 |
|
|
70
|
+
|---|---|---|---|
|
|
71
|
+
| `enabled` | boolean | `true` | 启用顾问群 |
|
|
72
|
+
| `discussion.maxRounds` | number | `2` | 自动深挖流水线总轮数(每轮 = 驱动追问 + 全体顾问接力) |
|
|
73
|
+
| `discussion.maxAdvisorsPerCall` | number | `3` | 单次咨询最大顾问数(1–10) |
|
|
74
|
+
| `discussion.autoDeepen` | boolean | `true` | 启用自动深挖流水线(驱动追问 + 综合结论) |
|
|
75
|
+
| `discussion.driverModel` | object | – | 兜底驱动模型 `{provider, model}`(会话头信息不可读时) |
|
|
76
|
+
| `discussion.advisorTimeoutMs` | number | `600000` | 单顾问调用超时(毫秒,1000–600000),双通道均生效 |
|
|
77
|
+
| `discussion.driverTimeoutMs` | number | `600000` | 驱动模型生成超时(深挖追问/综合结论;毫秒,1000–1200000) |
|
|
78
|
+
| `discussion.advisorTools` | string | `'readonly'` | **未单独设置时的全局默认**顾问工具调用范围:`readonly`(只读白名单 read/grep/glob/web_search/web_fetch…)|`all`(全部会话可见工具,含可写,慎用)|`off`(关闭)。仅直连通道(OpenAI/Anthropic)支持工具调用,DSH 内置通道的顾问需配 `baseURL`/`apiKey`/`apiKeyEnv` 直连(详情见「功能特性」)。 |
|
|
79
|
+
| `advisors[].tools` | string | – | 每个顾问的**单独**工具调用范围覆盖(`readonly`/`all`/`off`;未设置时跟随全局默认);设置卡片上:可直连的顾问显示下拉,DSH 内置通道顾问显示“不可配置”。 |
|
|
80
|
+
| `quota.enabled` | boolean | `true` | 启用每日咨询上限(成本安全阀) |
|
|
81
|
+
| `quota.maxPerDay` | number | `50` | 每日 UTC 日周期内最多新咨询次数(1–100000);`quota.enabled=false` 时不生效 |
|
|
82
|
+
| `trigger.requireClassifier` | boolean | `true` | 发起前先跑前置分类器 |
|
|
83
|
+
| `trigger.allowWebFallback` | boolean | `true` | 分类器建议联网搜索时返回该提示 |
|
|
84
|
+
| `trigger.confidenceThreshold` | number | `0.6` | 主模型置信度低于该值时升级 |
|
|
85
|
+
| `trigger.jev.enabled` | boolean | `false` | 用外部 Jev 模型对非强制咨询做语义前置分类;Jev 不可用时回退本地规则分类器 |
|
|
86
|
+
| `trigger.jev.provider` / `trigger.jev.model` | string | `'typesafe'` / `'jev-latest'` | Jev 路由(`typesafe` 或 `openrouter`)与模型;密钥用 `trigger.jev.apiKey`(secret)或 `trigger.jev.apiKeyEnv`;可选 `baseURL`、`timeoutMs`(默认 `10000`) |
|
|
87
|
+
| `trigger.jev.confidenceThreshold` | number | `0.6` | Jev 判「该找顾问」为是(或 0–1 分数达到该值)时升级 |
|
|
88
|
+
| `trigger.jev.highRiskThreshold` | number | 跟随 `jev.confidenceThreshold` | Jev 判「高风险」为是(或 0–1 分数达到该值)时标记高风险;未设置则跟随 `trigger.jev.confidenceThreshold` |
|
|
89
|
+
| `trigger.jev.useEnglishState` | boolean | `false` | 判定改用主模型附带的英文概要(`questionEn`)而非中文原问;展示与会话记录仍为中文 |
|
|
90
|
+
| `ui.theme` | string | `retro-green` | 卡片主题(retro-green / retro-amber / retro-blue) |
|
|
91
|
+
| `ui.showTimestamps` | boolean | `true` | 显示时间戳 |
|
|
92
|
+
| `ui.autoExpand` | boolean | `true` | 自动展开卡片 |
|
|
93
|
+
| `advisors` | array | `[]` | 顾问列表(provider/model/baseURL/apiKey/apiKeyEnv/protocol…,key 均标 `role('secret')`) |
|
|
94
|
+
|
|
95
|
+
> `discussion.parallel` 与 `discussion.stopOnConsensus` 为弃用遗留项,仅保留以兼容已存配置。
|
|
96
|
+
|
|
97
|
+
## 🧮 每日配额
|
|
98
|
+
|
|
99
|
+
插件自带一个成本安全阀:按 UTC 日历日统计**新咨询**次数,默认上限 50,可在设置页改数字或者直接关掉。它只拦新咨询——「▶ 继续聊天」续跑与追问都不计数。判断与自增在同一个同步块内完成,所以两个会话不可能同时挤过窗口;计数原子落盘在 `$DSH_HOME/storages/advisor-group/daily-guard.json`,重启不归零,UTC 日切自动清零。额度用尽时 `ask_advisors` 不启动,只返回一行说明;设置页实时显示「今日剩余咨询次数 X / Y」,关掉上限后仍然计数,只是不拦截。
|
|
100
|
+
|
|
101
|
+
## 💸 用量与成本
|
|
102
|
+
|
|
103
|
+
一次咨询不是「一次调用」,而是一串调用。默认配置(`maxRounds = 2`、最多 3 位顾问)下,一次新咨询约 9 次模型调用:2 轮 ×(1 次驱动模型追问 + 3 位顾问各 1 次)+ 1 次驱动模型综合结论。顾问若使用工具,每次工具往返还会再加一次模型调用(单个顾问上限 4 轮,另加一次强制文字作答),实际次数可能明显高于 9。
|
|
104
|
+
|
|
105
|
+
费用分别结算:顾问按你给它们配的通道与模型计费,驱动模型按当前会话的模型计费。想控成本,可以降 `maxRounds`、减少顾问数、给顾问设 `tools: 'off'`,再把每日上限设成你能接受的数字。中断后用「▶ 继续聊天」续跑只补问没答完的顾问,不会整场重来,代价低于重开一次。
|
|
106
|
+
|
|
107
|
+
`ask_session` 不走咨询配额:它唤醒目标会话,对方用一次普通回合作答、按其自身模型计费,也不会被算作一次新咨询。
|
|
108
|
+
|
|
109
|
+
## 🔒 安全与隐私
|
|
110
|
+
|
|
111
|
+
- 直连 API Key 可存于 DSH `settings.yaml`(标 secret,官方 `describe` 绝不回传浏览器);不想落盘请用 `apiKeyEnv` 环境变量模式。
|
|
112
|
+
- `/advisor-group/*` 路由为**单机共享 token**(本地单用户使用),不是多用户鉴权;暴露局域网必须外层加反代鉴权。
|
|
113
|
+
- 诊断端点服务端按存档 key 解析真实值再打供应商,并对目标 URL 做 https-only/loopback SSRF 校验;DNS rebinding 记为文档化已知边界。
|
|
114
|
+
- 每日咨询上限(`quota.*` 可配置,默认 50、可关闭)持久化在 `$DSH_HOME/storages/advisor-group/daily-guard.json`(UTC 日切),重启不再归零。
|
|
115
|
+
- 分类器影子模式:每次非强制分类追加一条观测样本(只读 `/advisor-group/shadow`),仅用于阈值调优,绝不干预行为。
|
|
116
|
+
- **`advisorTools: 'all'` 属于高风险作用域**:会把会话可见的**全部工具**(含 `pwsh`/`bash`/`write`、配置/SSH 等可写/执行类)暴露给顾问模型(经官方守卫管线执行)。仅建议为可信的本地模型启用,并保证走 direct-http 通道;每次**非只读**工具调用都会以 `console.warn` 留审计痕迹。默认请用 `readonly`(read/grep/glob/web_search/web_fetch/scan_discover/list_imported_sessions)或 `off`。
|
|
117
|
+
|
|
118
|
+
## ⚠️ 已知限制
|
|
119
|
+
|
|
120
|
+
- DSH 宿主进程硬崩溃时,已打开的卡片在刷新前可能仍显示 **LIVE**(现在会先出现断线提示);刷新后按会话日志恢复真实状态。
|
|
121
|
+
- 风险提示**只看事实、不看措辞**:截断(顾问输出被超时或网络中断)与取消(本轮咨询被停止)两种。用户可在**已停止或已完成**的卡片与会话日志中看到,主模型随 `ask_advisors` 返回收到。顾问正文不做关键词扫描——早期那套「凭字眼猜有没有保留意见」的启发式已在 0.1.1 移除,原因是它连「没有任何风险」这样的否定句也会当成风险提示(盲测里 4 条纯否定句全部误报)。
|
|
122
|
+
- 跨会话提问(`ask_session`)目前**没有设置开关**,工具在所有会话里可见,靠工具说明把使用限制在「用户明确要求时」;两个会话互相等待的情况尚未检测。
|
|
123
|
+
|
|
124
|
+
## 🛠️ 开发
|
|
125
|
+
|
|
126
|
+
```sh
|
|
127
|
+
npm install --legacy-peer-deps --no-audit --no-fund
|
|
128
|
+
npm run typecheck
|
|
129
|
+
npm test # vitest 单测(含本地假 LLM 服务器上的供应商流式契约)
|
|
130
|
+
npm run build # tsdown;客户端 bundle 禁用 minify: true
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## 📄 许可证
|
|
134
|
+
|
|
135
|
+
[Apache License 2.0](LICENSE) © 2026 dsh-advisor-group contributors.
|