dsh-plugin-rollout-scout 1.3.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/LICENSE +21 -0
- package/README.en.md +134 -0
- package/README.md +132 -0
- package/_wrap-client.mjs +32 -0
- package/cordis.patch.yml +3 -0
- package/lib/client.js +1319 -0
- package/lib/fixtures.js +145 -0
- package/lib/index.js +1583 -0
- package/package.json +54 -0
- package/plugin.client.js +1295 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SpookySandwich
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# dsh-plugin-rollout-scout
|
|
2
|
+
|
|
3
|
+
English | [简体中文](README.md)
|
|
4
|
+
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
7
|
+
[](https://github.com/SpookySandwich/dsh-plugin-rollout-scout/stargazers)
|
|
8
|
+
|
|
9
|
+
Providers sometimes roll a new conversation model out gradually, so which one you get is luck of the draw. Rollout Scout opens throwaway conversations on your own account, reads each one's chain-of-thought **as it streams**, and scores how the reasoning is written — cancelling the ones that read like the model you already have, and keeping the ones that don't.
|
|
10
|
+
|
|
11
|
+
It is a curiosity tool built on phrase heuristics, not an oracle. Everything it does, you could do by hand: start a chat, glance at the reasoning, close the tab.
|
|
12
|
+
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
## How it decides
|
|
16
|
+
|
|
17
|
+
The signal is in **how each paragraph opens** — not how often a phrase appears overall. A running tally of "Let me" drifts negative with length alone, so a long, perfectly good chain-of-thought eventually accumulates enough of them to look bad. Counting openings keeps the measure per-paragraph.
|
|
18
|
+
|
|
19
|
+
Only the first 48 characters of a paragraph are ever read. The phrase rarely sits at character zero:
|
|
20
|
+
|
|
21
|
+
> **The directory is empty. Let me create** a 3D cyberpunk scene.
|
|
22
|
+
> **To avoid conflicts, I'll keep** I18n.cs edits under one change.
|
|
23
|
+
|
|
24
|
+
Two signals are decisive, and they are deliberately **asymmetric**:
|
|
25
|
+
|
|
26
|
+
| Signal | Effect |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| `Let me` opening any paragraph | Old model — cancel the turn immediately |
|
|
29
|
+
| `I'll` opening the **whole** chain-of-thought | Rollout model — let it finish and keep it |
|
|
30
|
+
|
|
31
|
+
`I'll` counts as proof only at the very start, because old-model reasoning happily opens a *middle* paragraph with "I'll create a single HTML file…" and then says "Let me build…" three paragraphs later. Treating every `I'll` as proof produced false positives.
|
|
32
|
+
|
|
33
|
+
When neither fires, the remaining openings feed a score:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
bonus = (even paragraphs ? 1 : 0) + (any stall ? 1 : 0)
|
|
37
|
+
confidence = (positive openings + bonus + 1) / (classified openings + bonus + 2)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The bonus counts the summariser's shape as evidence in its own right, so a
|
|
41
|
+
chain-of-thought with even paragraphs and a stall reads above 50% before a single
|
|
42
|
+
opening has been classified. It only moves the number: keeping still needs
|
|
43
|
+
`Min. openings` real openings behind it.
|
|
44
|
+
|
|
45
|
+
A paragraph opening is scored as soon as 48 characters have arrived, even if the model never inserts a newline. `Let me` later in the chain-of-thought **overrides** an earlier keep.
|
|
46
|
+
|
|
47
|
+
The rollout path often uses a **small model to summarise** the chain-of-thought. That summariser commonly starts `We need to…` (so a first-paragraph `we` is only a negative opening, not a kill), writes **even, essay-sized paragraphs**, and streams in **bursts with stalls** in between. Those three are positive evidence of the new pipeline. The old model is irregular — one blob, or mixed tiny `Let me` lines.
|
|
48
|
+
|
|
49
|
+
Positive openings are the first-person **singular** planning voice — `I'm`, `I am`, `I've`, `I have`, `I need`, `I think`, `I also`, `I will`, and a leading `For`. Negative openings are `Let me` / `Let's` and **any** first-person plural in the opening (`we`, `we need`, `we will`, `we'll`, …). The rollout model reasons in "I", not "we". The add-one prior keeps a thin sample near 50% instead of swinging to a confident verdict off one word:
|
|
50
|
+
|
|
51
|
+
| Evidence | Confidence | Verdict |
|
|
52
|
+
| --- | --- | --- |
|
|
53
|
+
| nothing yet | 50% | keep watching |
|
|
54
|
+
| 1 positive, 10 negative | 15% | discard |
|
|
55
|
+
| 5 positive, 0 negative | 86% | keep |
|
|
56
|
+
|
|
57
|
+
A probe is discarded below `discard below` (0.35) and kept above `keep above` (0.7), but only once `min. openings` (4) have been classified. One that opens ten paragraphs without a single positive is given up on, and a chain-of-thought that is **mostly Chinese** (80%+ of its letters) is discarded on sight — quoting a Chinese prompt inside English reasoning does not count.
|
|
58
|
+
|
|
59
|
+
To leverage latency and throughput characteristics of rollout pipelines, two early-discard filters are available:
|
|
60
|
+
- **Maximum TPS limit**: Rollout models often generate at ~40–50 chunks/s, whereas old models stream significantly faster. Once streaming throughput exceeds the limit (default 60 chunks/s), the probe is discarded immediately.
|
|
61
|
+
- **Minimum First-Token Latency (TTFT)**: Old models often start streaming very quickly (< 1–2s). Set a minimum TTFT threshold (default 2.0s) to discard probes that respond too fast right on the first token.
|
|
62
|
+
|
|
63
|
+
The classifier is covered by tests over hand-labelled transcripts, alongside tests for the route guards, the launch loop's failure behaviour, and the rules about deleting sessions:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm test
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## The console
|
|
70
|
+
|
|
71
|
+
**Rollout Scout** sits at the sidebar foot, beside Settings, and opens the full-frame console described below. It is a `sidebar.footer.action` entry, so it matches the shell's own rows and collapses to a single icon when the sidebar folds to the rail.
|
|
72
|
+
|
|
73
|
+
**Left** — the probe prompt, model (default V4-Pro / High), concurrency, folder, and the four scoring thresholds. Below them sits the self-check, then the switches: TPS speed limit, first-token latency window, auto-pause on a strong match, discard Chinese reasoning, delete old-model probes from disk. The long explanation of the scoring rules folds away behind **How scoring works** rather than sitting between the controls.
|
|
74
|
+
|
|
75
|
+
The actions live in a footer under the column, so they stay put while the settings scroll, and are ordered by weight: **Start** / **Pause** on its own, **Force stop** and **Clear finished** beside each other, and **Delete all sessions** as plain text — it should not look like something you press by accident.
|
|
76
|
+
|
|
77
|
+
Under the scoring thresholds sits a **self-check**: `Self-check 13/13 · known rollout samples kept 5/5`. It runs thirteen hand-labelled chains-of-thought through the same classifier a live probe goes through, under whatever settings are currently in the form — no tokens, no probes. Tighten `Keep above` past what a labelled catch can reach and it turns amber and names the samples you just excluded. It is how you tell *nothing found* apart from *nothing findable*, which otherwise look identical from the console.
|
|
78
|
+
|
|
79
|
+
**Right** — launched / live / kept / discarded / best score, above a queue in launch order that never jumps. Each row has a score meter, matched phrases, and a preview. Click a card to open the conversation — it keeps running. Hover means you need it: putting the mouse on a fading card rescues it.
|
|
80
|
+
|
|
81
|
+
**Start** asks you to check your notifications first — a run opens a lot of conversations, and DSH Desktop can announce every one of them. Probe prompts are sent as plugin messages so they raise no toast of their own, and the dialog shows whether desktop notifications are on and offers to switch them off. Tick **Do not show this again** to skip it in future.
|
|
82
|
+
|
|
83
|
+
**Start** becomes **Pause**, which stops launching, cancels the probes already judged as the old model, and lets the undecided ones reach their own verdict. Then **Resume**. **Force stop** aborts everything still in flight.
|
|
84
|
+
|
|
85
|
+
A probe judged old fades for about 3 seconds (a thin line at the bottom of the card) while the turn is still running, then cancels. Hover or click during the fade keeps it.
|
|
86
|
+
|
|
87
|
+
**Keep** on any card takes that conversation out of reach of everything else in the console: it is never faded, cancelled, swept or deleted, and the promise survives a plugin reload. Probes that finish as a confident catch are kept automatically. Click **Kept** again to hand one back to the ordinary rules.
|
|
88
|
+
|
|
89
|
+
Probes are named in the sidebar as you go — `Rollout probe 12` while running, and `★ Rollout catch 12 · 87%` once one is caught, so a hit is obvious in a list full of probes. **Rename** on a kept card lets you name it yourself; naming one keeps it.
|
|
90
|
+
|
|
91
|
+
**Clear finished** removes completed probes from the list *and* deletes those conversations from disk. **Delete all sessions** wipes every probe in the folder — including ones already cleared from the list — and resets numbering so the next run starts at probe 1.
|
|
92
|
+
|
|
93
|
+
If probe conversations turn up in the folder that the console is not tracking — left by a plugin reload, an upgrade, or an app restart — a banner offers to **sweep** them. Those are the ones that otherwise sit in the sidebar with no way to remove them, since the shell's own menu offers Archive but not Delete.
|
|
94
|
+
|
|
95
|
+
Both refuse to touch a probe that is still streaming, except a kept one — that stays live on purpose, so it does not hold up a delete. Pause stops launching but leaves probes in flight, so **Delete all sessions** asks you to **Force stop** first rather than unlinking a log that is still being written to. The probe folder may not be your home directory, a drive root, or anywhere inside `~/.dsh` — deleting is scoped to that folder, and those would put unrelated conversations in its path.
|
|
96
|
+
|
|
97
|
+
If three probes in a row fail to even start — provider unreachable, folder unwritable — the run stops itself and reports the error instead of relaunching into the same failure forever. **Resume** tries again.
|
|
98
|
+
|
|
99
|
+
The run lives on the host, so it keeps going when you close the console — the sidebar row carries a status pip on its icon (pulsing while scouting, grey when paused, green on a catch), a live count in the wide column, a green badge with the number caught, and the tried count and best confidence so far on hover. In the rail the pip is the whole signal, which is why it sits on the icon rather than in the label.
|
|
100
|
+
|
|
101
|
+
## Install
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
dsh plugin --profile web add github:SpookySandwich/dsh-plugin-rollout-scout
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Restart DSH afterwards: the host half loads with the server. The interface follows DSH's display language (English / 中文).
|
|
108
|
+
|
|
109
|
+
`web` is the profile name — use whichever profile you actually run. The standalone harness boots `web`; DSH Desktop uses `desktop`. `~/.dsh/profiles/` lists the ones you have, and the installed bundle ends up in that profile's `package.json`.
|
|
110
|
+
|
|
111
|
+
Not on npm yet, so install from the repository. `lib/client.js` is a generated bundle but it is **committed**, so the install works without running any build step — `dsh plugin add` is pnpm underneath and does not run dependency lifecycle scripts by default. If you edit `plugin.client.js`, run `npm run build` to regenerate it (`npm test` does this too), and commit the result.
|
|
112
|
+
|
|
113
|
+
## How it works
|
|
114
|
+
|
|
115
|
+
- The host half serves `/rollout-scout` and creates each probe as a brand-new session with `ctx.agents.create` (no seed), setting model and reasoning effort through `installModelSelection`.
|
|
116
|
+
- Probe prompts are sent as plugin-sourced messages, which is what keeps a run from announcing itself once per probe.
|
|
117
|
+
- It subscribes to `session/event` scoped to that one agent and reads `reasoning-delta` chunks off `assistant/chunk` — the chain-of-thought as it streams — classifying on every chunk.
|
|
118
|
+
- A verdict against calls `agent.cancel` to interrupt the turn; a verdict for lets it run to `turn/end`. While streaming, the last paragraph is withheld because its opening may be half-written; at turn end the complete text is re-classified.
|
|
119
|
+
- Probes are created in the folder you choose, which becomes a workspace. Old-model probes can be deleted from disk.
|
|
120
|
+
- `/rollout-scout` listens on a local port, so it is guarded like one: writes require an `application/json` content type (which forces a CORS preflight that is never answered) and a cross-origin `Origin` is refused. A page you happen to be visiting cannot make it start or delete anything.
|
|
121
|
+
|
|
122
|
+
Implementation notes live in [`docs/`](docs/) — [architecture](docs/architecture.md) and the [harness behaviour this depends on](docs/dsh-host-notes.md).
|
|
123
|
+
|
|
124
|
+
## Compatibility
|
|
125
|
+
|
|
126
|
+
The launcher takes a `sidebar.footer.action` seat (a list slot, so it sits beside any other footer action rather than displacing one) and the console renders on the frame-wide `shell.overlay` layer. Neither is per-session, so it conflicts with no session plugin. Requires a DSH whose sidebar declares that seat; without it the console has no way in. Part of the same family as [dsh-plugin-smooth-stream](https://github.com/SpookySandwich/dsh-plugin-smooth-stream), [dsh-plugin-no-workspace](https://github.com/SpookySandwich/dsh-plugin-no-workspace) and [dsh-plugin-message-edit](https://github.com/SpookySandwich/dsh-plugin-message-edit).
|
|
127
|
+
|
|
128
|
+
## A note on cost
|
|
129
|
+
|
|
130
|
+
Every probe is a real turn against your own quota. Discarded ones are cancelled within a second or two, but a run left going will keep launching until you stop it. Concurrency and the thresholds are yours to tune.
|
|
131
|
+
|
|
132
|
+
## License
|
|
133
|
+
|
|
134
|
+
MIT © SpookySandwich
|
package/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# dsh-plugin-rollout-scout
|
|
2
|
+
|
|
3
|
+
[English](README.en.md) | 简体中文
|
|
4
|
+
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
7
|
+
[](https://github.com/SpookySandwich/dsh-plugin-rollout-scout/stargazers)
|
|
8
|
+
|
|
9
|
+
服务商有时会灰度发布新的对话模型,你分到哪一个全看运气。灰度侦察会用你自己的账号开启一批临时会话,**在思维链流式输出的同时**读取它,并按「推理是怎么写的」打分——读起来像你手上这个旧模型的立刻中止,不像的留下来。
|
|
10
|
+
|
|
11
|
+
它是基于措辞的启发式小工具,不是权威判据。它做的每件事你都可以手动完成:开一个新会话、扫一眼思维链、关掉。
|
|
12
|
+
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
## 判定方式
|
|
16
|
+
|
|
17
|
+
信号在于 **每个段落是怎么开头的**,而不是某个短语在全文出现了多少次。若按全文累计,「Let me」会单纯因为篇幅变长而越积越多,一段本来很好的长思维链最终也会被判为差。只看开头,度量才稳定。
|
|
18
|
+
|
|
19
|
+
每段只读前 48 个字符。而关键短语往往并不在第 0 个字符:
|
|
20
|
+
|
|
21
|
+
> **The directory is empty. Let me create** a 3D cyberpunk scene.
|
|
22
|
+
> **To avoid conflicts, I'll keep** I18n.cs edits under one change.
|
|
23
|
+
|
|
24
|
+
有两个决定性信号,且刻意 **不对称**:
|
|
25
|
+
|
|
26
|
+
| 信号 | 效果 |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| 任意段落以 `Let me` 开头 | 旧模型——立即中止该轮 |
|
|
29
|
+
| **整条思维链** 以 `I'll` 开头 | 灰度模型——放行跑完并保留 |
|
|
30
|
+
|
|
31
|
+
`I'll` 只有出现在最开头才算证据:旧模型也会在 **中间某段** 写「I'll create a single HTML file…」,然后隔几段又说「Let me build…」。把每个 `I'll` 都当证据会造成误判。
|
|
32
|
+
|
|
33
|
+
两者都没触发时,其余开头进入评分:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
加成 = (规整段落 ? 1 : 0) + (有停顿 ? 1 : 0)
|
|
37
|
+
置信度 = (正向开头数 + 加成 + 1) / (已分类开头数 + 加成 + 2)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
加成把总结链的形态本身也算作证据,因此段落规整、又有停顿的思维链在还没有任何
|
|
41
|
+
开头被分类时就会高于 50%。它只影响这个数字:真正保留仍需要凑满「最少开头数」。
|
|
42
|
+
|
|
43
|
+
段落开头写满 48 个字符就会打分,即使模型从不换行。后出现的 `Let me` **会推翻** 先前的保留。
|
|
44
|
+
|
|
45
|
+
灰度链路常常用一个 **小模型总结思维链**。总结模型经常以 `We need to…` 开头(所以段首 `we` 只记负分,不直接判死),写出 **规整、一段一段的长段落**,并且 **输出一阵、卡住、再输出一阵**。这三条都是新链路的正面证据。旧模型不规律——整段糊成一块,或夹着很短的 `Let me` 行。
|
|
46
|
+
|
|
47
|
+
正向开头是第一人称**单数**的计划语气——`I'm`、`I am`、`I've`、`I have`、`I need`、`I think`、`I also`、`I will`,以及位于开头的 `For`。负向开头是 `Let me` / `Let's`,以及开头里出现的**任何**第一人称复数(`we`、`we need`、`we will`、`we'll` …)。灰度模型用 “I”,不用 “we”。加一的先验让证据稀少时分数停在 50% 附近,不会因为一个词就给出自信判断:
|
|
48
|
+
|
|
49
|
+
| 证据 | 置信度 | 判定 |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| 暂无 | 50% | 继续观察 |
|
|
52
|
+
| 1 正 / 10 负 | 15% | 丢弃 |
|
|
53
|
+
| 5 正 / 0 负 | 86% | 保留 |
|
|
54
|
+
|
|
55
|
+
低于 `低于此分即丢弃`(0.35)丢弃,高于 `高于此分即保留`(0.7)保留,但都要先累计到 `最少开头数`(4)。若连续开了十段一个正向开头都没有,则放弃;思维链 **以中文为主**(字母中 80% 以上为汉字)则直接丢弃——英文推理里引用一句中文提示词不算。
|
|
56
|
+
|
|
57
|
+
针对灰度链路的速度与时延特征,还支持两项前置早停开关:
|
|
58
|
+
- **生成速度 (TPS) 上限**:灰度模型流式吐字速度常在 40~50 字/秒左右(旧模型通常显著更快)。开启后一旦流式 TPS 超过指定上限(默认 60 字/秒),立刻中止该轮,在开头几秒内挽救 Token。
|
|
59
|
+
- **首字延迟 (TTFT) 下限**:旧模型常在极短时间内(< 1~2 秒)开始输出。可设置首字延迟下限(默认 2 秒),低于此阈值立即在首个字符到达时判定为旧模型并丢弃。
|
|
60
|
+
|
|
61
|
+
分类器有基于人工标注样本的测试,此外还覆盖了接口防护、发起失败时的行为,以及删除会话的规则:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npm test
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 控制台
|
|
68
|
+
|
|
69
|
+
**灰度侦察** 位于侧边栏底部、「设置」旁边,点开就是下述整屏控制台。它注册在 `sidebar.footer.action` 座位上,因此与外壳自带的条目样式一致;侧边栏收起为窄栏时,它也会收成一个图标。
|
|
70
|
+
|
|
71
|
+
**左栏** —— 探测提示词、模型(默认 V4-Pro / High)、并发数、存放目录,以及四项评分阈值。阈值下方是自检,再往下是各项开关:TPS 速度上限、首字延迟区间、命中强匹配时自动暂停、思维链以中文为主时丢弃、从磁盘删除旧模型会话。评分规则的长说明收在 **评分是怎么算的** 里,不再夹在控件中间。
|
|
72
|
+
|
|
73
|
+
操作按钮固定在左栏底部,设置滚动时不会跟着走,并按分量排列:**开始** / **暂停** 单独一行,**强制停止** 与 **清空已结束** 并排,**删除全部会话** 则是一行纯文字——它不该长得像顺手就会点到的东西。
|
|
74
|
+
|
|
75
|
+
评分阈值下方有一条**自检**:`自检 13/13 · 已知灰度样本保留 5/5`。它用当前表单里的设置,把十三条人工标注的思维链跑一遍——走的是真实探测同一套分类器,不消耗 Token、不发起探测。把「高于此分即保留」调到标注样本都够不着,它会变成橙色并列出被排除的样本。这是分辨「没找到」和「根本找不到」的办法,否则这两种情况在控制台里长得一模一样。
|
|
76
|
+
|
|
77
|
+
**右栏** —— 已发起 / 进行中 / 已保留 / 已丢弃 / 最高分,下方队列按发起顺序排列、不随分数跳动。每行带分数条、命中短语与思维链预览。点击整张卡片打开会话,会话继续跑。鼠标放在卡片上视为需要它:淡出过程中移上去会救回来,点进去也不会停。
|
|
78
|
+
|
|
79
|
+
**开始** 前会先提醒你确认通知设置——一次运行会开启大量会话,而 DSH Desktop 可能逐个弹通知。探测提示词以插件消息发送,本身不会触发通知;弹窗会显示桌面通知当前是否开启,并可一键关闭。勾选 **不再提示** 即可跳过。
|
|
80
|
+
|
|
81
|
+
**开始** 会变为 **暂停**:停止发起新探测,中止已判定为旧模型的探测,尚未判定的各自跑完。再变为 **继续**。**强制停止** 会中止所有进行中的会话。
|
|
82
|
+
|
|
83
|
+
判旧的探测先淡出约 3 秒(卡片底边一条细线收掉),期间会话还在跑;淡完才取消。鼠标放上去或点进去会留下。
|
|
84
|
+
|
|
85
|
+
卡片上的 **保留** 会让该会话不受本控制台其它任何操作影响:不淡出、不中止、不清理、不删除,且该标记在插件重载后依然有效。判定为灰度并跑完的探测会自动保留。再次点击 **已保留** 可交回常规规则处理。
|
|
86
|
+
|
|
87
|
+
探测会话在侧边栏里会自动命名:运行时叫 `灰度探测 12`,命中后改为 `★ 灰度命中 12 · 87%`,在一堆探测里一眼就能认出。已保留的卡片上有 **重命名**,可以自己起名字;起了名字就等于保留。
|
|
88
|
+
|
|
89
|
+
**清空已结束** 会从列表移除已完成的探测,并删除这些会话文件。**删除全部会话** 会清空该目录下所有探测(包括已经从列表清掉的),并把编号从 1 重新计。
|
|
90
|
+
|
|
91
|
+
如果目录下出现了本控制台并未跟踪的探测会话——插件重载、升级或应用重启都会留下这类残留——顶部会出现提示条,可一键 **清理**。这些正是平时在侧边栏里删不掉的会话:外壳自带的菜单只有归档,没有删除。
|
|
92
|
+
|
|
93
|
+
两者都不会动仍在流式输出的探测;已保留的除外——它本就该一直跑着,因此不会挡住删除。暂停只是停止发起,进行中的探测仍在跑,所以此时 **删除全部会话** 会要求你先 **强制停止**,以免删掉正在写入的会话文件。存放目录不能是主目录、磁盘根目录,也不能位于 `~/.dsh` 之内——删除以该目录为范围,这些位置会把无关会话卷进去。
|
|
94
|
+
|
|
95
|
+
若连续三个探测连启动都失败(服务不可达、目录不可写等),运行会自行停止并报出错误,而不是一直重复同一个失败。点 **继续** 可以重试。
|
|
96
|
+
|
|
97
|
+
运行状态在宿主端,因此关掉控制台后仍会继续——侧边栏那一行的图标上带一个状态小点(侦察中呼吸闪烁、暂停为灰、命中转绿),宽栏里还会显示进行中的数量、命中后带绿色角标,悬停可看已试数量与目前最高置信度。收成窄栏后只剩这个小点可看,所以它长在图标上而不是文字里。
|
|
98
|
+
|
|
99
|
+
## 安装
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
dsh plugin --profile web add github:SpookySandwich/dsh-plugin-rollout-scout
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
安装后请重启 DSH:宿主端随服务器加载。界面跟随 DSH 显示语言(中文 / English)。
|
|
106
|
+
|
|
107
|
+
`web` 是 profile 名称,请换成你实际使用的那个。独立版启动的是 `web`,DSH Desktop 用的是 `desktop`。`~/.dsh/profiles/` 下就是你现有的 profile,安装结果落在对应 profile 的 `package.json` 里。
|
|
108
|
+
|
|
109
|
+
尚未发布到 npm,因此从仓库安装。`lib/client.js` 是构建产物,但已**提交进仓库**,所以安装时无需任何构建步骤——`dsh plugin add` 底层是 pnpm,默认不会执行依赖的生命周期脚本。若你修改了 `plugin.client.js`,请运行 `npm run build` 重新生成(`npm test` 也会顺带生成),并把结果一并提交。
|
|
110
|
+
|
|
111
|
+
## 工作原理
|
|
112
|
+
|
|
113
|
+
- 宿主端提供 `/rollout-scout` 接口,用 `ctx.agents.create`(不带 seed)把每个探测创建为全新会话,并通过 `installModelSelection` 设置模型与思考强度。
|
|
114
|
+
- 探测提示词以插件消息发送,这样一次运行才不会逐个探测地弹出系统通知。
|
|
115
|
+
- 订阅该 agent 作用域内的 `session/event`,从 `assistant/chunk` 读取 `reasoning-delta`(流式思维链),每收到一块就重新分类。
|
|
116
|
+
- 判为旧模型时调用 `agent.cancel` 中止该轮;判为灰度则放行至 `turn/end`。流式过程中最后一段会被暂时忽略(开头可能只写了一半),turn 结束后再用完整文本重新分类。
|
|
117
|
+
- 探测会话创建在你指定的目录下(作为一个工作区),判为旧模型的会话可选择从磁盘删除。
|
|
118
|
+
- `/rollout-scout` 监听在本地端口上,因此按本地接口的方式做了防护:写操作必须带 `application/json` 内容类型(这会强制浏览器发起 CORS 预检,而预检永远不会被放行),跨源的 `Origin` 一律拒绝。你恰好打开的某个网页无法借此发起探测或删除数据。
|
|
119
|
+
|
|
120
|
+
实现细节见 [`docs/`](docs/):[架构说明](docs/architecture.md),以及[所依赖的宿主行为](docs/dsh-host-notes.md)。
|
|
121
|
+
|
|
122
|
+
## 兼容性
|
|
123
|
+
|
|
124
|
+
入口占用 `sidebar.footer.action` 座位(list 类型,会与其它底部操作并排,而不是把谁挤掉),控制台本体渲染在全局 `shell.overlay` 层。两者都不属于会话作用域,因此不与任何会话内插件冲突。需要侧边栏声明了该座位的 DSH 版本;否则控制台将没有入口。与 [dsh-plugin-smooth-stream](https://github.com/SpookySandwich/dsh-plugin-smooth-stream)、[dsh-plugin-no-workspace](https://github.com/SpookySandwich/dsh-plugin-no-workspace)、[dsh-plugin-message-edit](https://github.com/SpookySandwich/dsh-plugin-message-edit) 同族。
|
|
125
|
+
|
|
126
|
+
## 关于额度
|
|
127
|
+
|
|
128
|
+
每个探测都是一次真实的对话轮次,消耗你自己的额度。被丢弃的通常一两秒内就中止,但只要不停止,运行中的任务会一直发起新探测。并发数与各项阈值都可自行调整。
|
|
129
|
+
|
|
130
|
+
## 许可
|
|
131
|
+
|
|
132
|
+
MIT © SpookySandwich
|
package/_wrap-client.mjs
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
|
|
3
|
+
const body = fs.readFileSync(new URL('./plugin.client.js', import.meta.url), 'utf8');
|
|
4
|
+
const out = [
|
|
5
|
+
"window.__ModuleLoader__.load({",
|
|
6
|
+
" id: 'dsh-plugin-rollout-scout',",
|
|
7
|
+
" factory: (require) => {",
|
|
8
|
+
" const React = require('react');",
|
|
9
|
+
" const styles = {",
|
|
10
|
+
" insert(css) {",
|
|
11
|
+
" if (typeof document === 'undefined') return function () {};",
|
|
12
|
+
" const prev = document.querySelector('style[data-plugin=\"dsh-plugin-rollout-scout\"]');",
|
|
13
|
+
" if (prev) {",
|
|
14
|
+
" prev.textContent = css;",
|
|
15
|
+
" return function () { prev.remove(); };",
|
|
16
|
+
" }",
|
|
17
|
+
" const tag = document.createElement('style');",
|
|
18
|
+
" tag.dataset.plugin = 'dsh-plugin-rollout-scout';",
|
|
19
|
+
" tag.textContent = css;",
|
|
20
|
+
" document.head.appendChild(tag);",
|
|
21
|
+
" return function () { tag.remove(); };",
|
|
22
|
+
" }",
|
|
23
|
+
" };",
|
|
24
|
+
" return (function () {",
|
|
25
|
+
body,
|
|
26
|
+
" })();",
|
|
27
|
+
" }",
|
|
28
|
+
"});",
|
|
29
|
+
"",
|
|
30
|
+
].join('\n');
|
|
31
|
+
fs.writeFileSync(new URL('./lib/client.js', import.meta.url), out);
|
|
32
|
+
console.log('wrote lib/client.js', out.length);
|
package/cordis.patch.yml
ADDED