dsh-stall-guard 0.0.0-stage → 0.1.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/CHANGELOG.md +79 -0
- package/LICENSE +21 -0
- package/PROVENANCE.md +33 -0
- package/README.md +266 -3
- package/client.js +1948 -0
- package/cordis.patch.yml +8 -0
- package/icon.svg +38 -0
- package/index.js +85 -0
- package/lib/classify.js +235 -0
- package/lib/config.js +232 -0
- package/lib/download.js +319 -0
- package/lib/fallback.js +357 -0
- package/lib/guard.js +342 -0
- package/lib/presets.js +268 -0
- package/lib/routes.js +130 -0
- package/lib/state.js +241 -0
- package/lib/supervisor.js +127 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +61 -5
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# 更新日志
|
|
2
|
+
|
|
3
|
+
本项目的所有重要变更都记录在此文件。
|
|
4
|
+
|
|
5
|
+
格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
|
|
6
|
+
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-10-20
|
|
9
|
+
|
|
10
|
+
首个版本。核心用途:**下载卡住时自动掐掉,并把换源提示写给智能体看**。
|
|
11
|
+
|
|
12
|
+
### 新增
|
|
13
|
+
|
|
14
|
+
- **下载检测与换源提示**:识别 `git clone/fetch/pull/submodule update`、
|
|
15
|
+
`pnpm/npm/yarn install/add`、`pip/uv install`、`cargo install/fetch`、
|
|
16
|
+
`go get/mod download`、`curl/wget/Invoke-WebRequest/aria2c` 六类下载渠道。
|
|
17
|
+
超时后中止命令,并返回一段**给智能体读的工具结果**:说明是网络到源不通、
|
|
18
|
+
列出候选镜像(明确标注未验证)、提醒清理半成品、附上原始命令。
|
|
19
|
+
- **独立下载预算**:`downloadSeconds`(默认 30 秒),不占用 `exec` 类的 30 秒。
|
|
20
|
+
等死掉的镜像和等慢编译代价不同,所以分开算。
|
|
21
|
+
- **按工具类型分档超时**:抓取/搜索 15 秒、读取 20 秒、写入/执行 30 秒、
|
|
22
|
+
长任务 120 秒、其他 30 秒;每档可改(1–3600 秒),也可单工具覆盖。
|
|
23
|
+
- **只读调用自动换路**:`web_fetch` 超时改搜索同主题;`web_search` 超时重试一次。
|
|
24
|
+
- **只掐下载,不掐写入**:`write`/`edit` 与普通 `bash` 命令超时只提示、绝不中止,
|
|
25
|
+
避免写坏用户文件;下载中止是安全的,因为删掉重下即可。
|
|
26
|
+
- **DeepSeek 监督员**:三种形态(状态栏小点 / 跳动图标 / 蓝鲸角色),
|
|
27
|
+
只在 `alert` 状态动画。可配监督模型,只发工具元信息,失败降级为手写文案,可完全关闭。
|
|
28
|
+
- **最近 10 条卡顿记录**:时间、工具、类型、耗时/超时、动作、备选、成功与否。
|
|
29
|
+
- **设置持久化**:`$DSH_HOME/stall-guard/config.json`,原子写入;损坏自动重建;
|
|
30
|
+
非法值夹取或回退并在保存时以警告列出。
|
|
31
|
+
|
|
32
|
+
### 不误报
|
|
33
|
+
|
|
34
|
+
`curl --version`、`wget --help`、`git status`、`git log`、`ls`、`node -v`
|
|
35
|
+
等不触网的命令不会被当成下载(有回归测试固定)。
|
|
36
|
+
|
|
37
|
+
### 安全设计
|
|
38
|
+
|
|
39
|
+
- 原调用若在被中止后仍成功返回真实结果,**采用真实结果**,不用备选覆盖可用答案。
|
|
40
|
+
- 备选与监督模型调用都有独立 deadline(`Promise.race`,非仅 abort),
|
|
41
|
+
即使 provider 忽略取消信号也不会挂住。
|
|
42
|
+
- 监督模型输出强制清洗:单行、去 markdown、截断 120 字。
|
|
43
|
+
- 请求体上限 64 KiB;只注册三条 exact 路由。
|
|
44
|
+
|
|
45
|
+
### 自定义预设(不碰模型)
|
|
46
|
+
|
|
47
|
+
- **直接写发给智能体的原文**:三个场景(下载 / 抓取 / 搜索)× 中英双语,各一份模板。
|
|
48
|
+
只做 `{{占位符}}` 替换,**不调用任何模型**;设了预设就跟 `useModel` 无关。
|
|
49
|
+
- **十个占位符**:`label` `channel` `target` `host` `command` `seconds` `elapsed`
|
|
50
|
+
`hints`(内置镜像清单)`query` `sources`。面板里每个都是可点按钮,一键插入。
|
|
51
|
+
- **空着 = 用内置文案**,不是"什么都不发"——清空不会让插件失声。
|
|
52
|
+
- **拼错的占位符原样保留**(如 `{{labl}}`),方便发现笔误,而不是静默变空字符串。
|
|
53
|
+
- 上限 4000 字,超了截断并提示;`${...}` 之类原样输出,不执行任何东西。
|
|
54
|
+
- 清理半成品的提醒**始终追加**(即使自定义预设),因为少了它重试会撞 `already exists`。
|
|
55
|
+
- Client 与 Host 各存一份默认文案(面板要秒开),有测试固定两份必须逐字节相同。
|
|
56
|
+
|
|
57
|
+
### 面板修复
|
|
58
|
+
|
|
59
|
+
- **保存按钮固定到底部**:原来在滚动区最末尾,改完超时表要滚很久才看得到。
|
|
60
|
+
现在面板分为「滚动内容区 + 固定操作栏」。
|
|
61
|
+
- **未保存改动不再静默丢弃**:原来点关闭 / Esc / 点面板外会直接丢掉修改。
|
|
62
|
+
现在弹出内联确认条「放弃未保存的修改?[放弃][继续编辑]」。
|
|
63
|
+
不用 `window.confirm`:在本机 Electron 里不可靠(实测不弹窗、且永久阻塞关闭),
|
|
64
|
+
会让面板在有改动时**永远关不掉**。
|
|
65
|
+
|
|
66
|
+
### 移除模型(不兼容变更)
|
|
67
|
+
|
|
68
|
+
- **删除了「用模型生成提示」功能**。那句提示是给**人看的**,而它要传达的事实
|
|
69
|
+
(哪个工具、跑了多久、阈值多少、做了什么)守卫已经完全知道;模型只能换个说法,
|
|
70
|
+
不能更准,却每次卡顿花约 300 token。现在提示来自内置中英文案表,**零 token**。
|
|
71
|
+
- 随之移除 `supervisor.useModel` / `provider` / `model` / `timeoutMs` / `cooldownMs`
|
|
72
|
+
与 `scenes.*.useModel`。旧配置里的这些键会被**忽略而不报错**,不影响升级。
|
|
73
|
+
- 插件现在**在任何情况下都不调用模型**,唯一的上下文成本是换源提示本身。
|
|
74
|
+
|
|
75
|
+
### 测试
|
|
76
|
+
|
|
77
|
+
182 个用例:下载检测(六渠道 + 不误报)、换源文案内容、下载超时端到端、
|
|
78
|
+
分类表、配置校验与持久化、状态机、备选切换、模型降级、
|
|
79
|
+
真实 `setTimeout` + abort 的 guard 集成、真实 HTTP server 路由测试。
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 1250589385
|
|
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/PROVENANCE.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# 素材来源与许可范围(PROVENANCE)
|
|
2
|
+
|
|
3
|
+
本仓库的**代码**按 MIT 许可(见 [`LICENSE`](LICENSE)),覆盖
|
|
4
|
+
`index.js`、`lib/**`、`client.js`、`cordis.patch.yml`、`package.json`、
|
|
5
|
+
`locale/**`、文档与测试。
|
|
6
|
+
|
|
7
|
+
## 许可范围
|
|
8
|
+
|
|
9
|
+
| 范围 | 许可 |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `index.js`、`lib/**`、`client.js`、`cordis.patch.yml`、`package.json`、文档、测试 | **MIT**(见 `LICENSE`) |
|
|
12
|
+
| `locale/en.json`、`locale/zh.json`(文案) | **MIT**(随代码一并授权) |
|
|
13
|
+
| `icon.svg`(插件列表图标) | **原创作品**,作者为本仓库维护者,按 **MIT** 一并授权 |
|
|
14
|
+
|
|
15
|
+
## 逐项来源
|
|
16
|
+
|
|
17
|
+
| 文件 | 来源 / 说明 |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `icon.svg` | 维护者手写的原创 SVG(盾牌 + 秒表意象),无第三方素材、无嵌入元数据。 |
|
|
20
|
+
| `client.js` 里的监督员形象 | 维护者用内联 SVG / CSS 手绘的蓝色鲸鱼轮廓,**未引用任何图片文件**,不含第三方美术素材。 |
|
|
21
|
+
| `locale/en.json`、`locale/zh.json` | 维护者撰写,仅含插件标题与描述。 |
|
|
22
|
+
| `index.js`、`lib/**` | 维护者原创;仅使用 DeepSeek Harness 公开的插件接口(`tools/execute` 事件、`webServer.register`、`web` / `llm` / `agentDefaultModel` 服务、slot 与 locale 注册),未复制任何宿主组件源码。 |
|
|
23
|
+
| 监督员的兜底文案(中英对照表) | 维护者撰写。 |
|
|
24
|
+
|
|
25
|
+
## 无第三方素材
|
|
26
|
+
|
|
27
|
+
本仓库**不包含**任何第三方图片、动图、音频或字体文件,
|
|
28
|
+
因此不存在素材授权范围的划分问题;整仓内容统一为 MIT。
|
|
29
|
+
|
|
30
|
+
## 权利主张 / Takedown
|
|
31
|
+
|
|
32
|
+
如果你认为本仓库的内容侵犯了你的权利,请在本仓库开一条 issue,
|
|
33
|
+
说明**文件名**与**依据**,我们会在核实后**立即替换或移除**,不附加其它条件。
|
package/README.md
CHANGED
|
@@ -1,3 +1,266 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# 卡顿守卫 · dsh-stall-guard
|
|
2
|
+
|
|
3
|
+
**下载卡住了?自动掐掉,然后告诉智能体「换个源重试」。**
|
|
4
|
+
|
|
5
|
+
GitHub 在国内时通时不通,`git clone` 挂在那儿几分钟不动,智能体就一直干等。
|
|
6
|
+
这个插件盯着下载类命令,超过阈值直接中止,并把一句**智能体能读懂的换源提示**写进工具结果里。
|
|
7
|
+
|
|
8
|
+
> 注意:这是给**智能体**看的,不是给人看的。你看到的 UI(监督员形象)只是顺便。
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 它到底做了什么
|
|
13
|
+
|
|
14
|
+
一条命令超时后,智能体收到的**不是**一句干巴巴的 `timeout`,而是:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
下载卡住了:git repository github.com/nodejs/node.git 在 30 秒内没完成(已经跑了 30 秒,已中止)。
|
|
18
|
+
|
|
19
|
+
这条命令被终止了。原因多半是到这个源的网络不通,而不是命令本身写错。
|
|
20
|
+
换一个源重试,不要用同一个源继续硬等:
|
|
21
|
+
1. 在 GitHub 地址前加代理前缀,例如 https://gh-proxy.com/https://github.com/<owner>/<repo>.git
|
|
22
|
+
2. 备选前缀:https://ghfast.top/ https://kkgithub.com/ https://gitclone.com/github.com/
|
|
23
|
+
3. 不改全局配置的一次性写法:git -c url."https://gh-proxy.com/https://github.com/".insteadOf="https://github.com/" clone <owner>/<repo>
|
|
24
|
+
4. 如果只需要源码不需要提交历史,改用下载 tarball 通常更快:curl -L https://gh-proxy.com/https://codeload.github.com/<owner>/<repo>/tar.gz/refs/heads/main
|
|
25
|
+
|
|
26
|
+
上面这些镜像只是候选,没有验证过能不能用 —— 一个不行就换下一个。
|
|
27
|
+
|
|
28
|
+
注意:被中止的 git clone 可能留下半成品目录,重试前先删掉它(或在新的空目录里重试)。
|
|
29
|
+
|
|
30
|
+
卡住的命令:git clone https://github.com/nodejs/node.git
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
四个关键点,每个都有用:
|
|
34
|
+
|
|
35
|
+
1. **说明了是「网络到源不通」,不是命令写错** —— 否则智能体会去改命令,白费时间。
|
|
36
|
+
2. **给了候选源** —— 但**明确说是没验证过的候选**。镜像可用性每小时都在变,写一份「已验证可用」的清单只会骗到智能体。
|
|
37
|
+
3. **提醒清理半成品** —— 被掐掉的 `git clone` 会留下半个目录,直接重试会报 `already exists` 然后卡第二轮。
|
|
38
|
+
4. **附上原始命令** —— 智能体不用回翻上下文找它刚才跑的是什么。
|
|
39
|
+
|
|
40
|
+
## 覆盖哪些下载
|
|
41
|
+
|
|
42
|
+
| 渠道 | 认得出的命令 | 换源提示 |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| `git` | `git clone` `git fetch` `git pull` `git submodule update` `git remote add` | 代理前缀 / insteadOf / tarball |
|
|
45
|
+
| `npm` | `pnpm install|add` `npm i|install` `yarn add` `bun` | `--registry https://registry.npmmirror.com` |
|
|
46
|
+
| `pip` | `pip install` `pip download` `uv sync` | `-i https://pypi.tuna.tsinghua.edu.cn/simple` |
|
|
47
|
+
| `cargo` | `cargo install|fetch|build` | tsinghua / ustc crates 镜像 |
|
|
48
|
+
| `go` | `go get` `go mod download` | `GOPROXY=https://goproxy.cn,direct` |
|
|
49
|
+
| `http` | `curl` `wget` `Invoke-WebRequest` `aria2c` `Start-BitsTransfer` | 换主机 / gh-proxy / 断点续传 |
|
|
50
|
+
|
|
51
|
+
**不误报**:`curl --version`、`wget --help`、`git status`、`git log`、`ls`、`node -v` 都不会被当成下载。
|
|
52
|
+
|
|
53
|
+
## 快速开始
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
dsh plugin --profile <你的profile> add dsh-stall-guard
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
不知道 profile 叫什么:
|
|
60
|
+
|
|
61
|
+
```powershell
|
|
62
|
+
$env:DSH_PROFILE # 桌面版一般是 desktop
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
装完**刷新页面**即可。默认就生效,不用额外配置。
|
|
66
|
+
|
|
67
|
+
## 默认超时
|
|
68
|
+
|
|
69
|
+
| 类型 | 默认 | 卡住后 |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| **下载** | **30 秒** | **中止 + 给智能体换源提示** |
|
|
72
|
+
| 抓取 `web_fetch` | 15 秒 | 中止 + 改用搜索 |
|
|
73
|
+
| 搜索 `web_search` | 15 秒 | 中止 + 重试一次 |
|
|
74
|
+
| 读取 | 20 秒 | 只提示 |
|
|
75
|
+
| 写入 | 30 秒 | 只提示,**不中止**(防写坏文件) |
|
|
76
|
+
| 执行 | 30 秒 | 只提示(除非判定为下载) |
|
|
77
|
+
| 长任务 | 120 秒 | 只提示 |
|
|
78
|
+
| 其他 | 30 秒 | 只提示 |
|
|
79
|
+
|
|
80
|
+
下载有**独立预算**(`downloadSeconds`,默认 30 秒),不占用 `exec` 的 30 秒。
|
|
81
|
+
原因很直接:等一个死掉的镜像 30 秒和等一个慢编译 30 秒,代价完全不同。
|
|
82
|
+
|
|
83
|
+
## 为什么只掐下载,不掐写文件
|
|
84
|
+
|
|
85
|
+
| 操作 | 中止后的后果 | 策略 |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| `git clone` / `curl` | 留下半个文件/目录,**删掉重来就行** | ✅ 中止 |
|
|
88
|
+
| `write` / `edit` 写文件 | 可能写坏用户的文件 | ❌ 绝不中止 |
|
|
89
|
+
| 普通 `bash` 命令 | 可能跑到一半改了状态 | ❌ 不中止 |
|
|
90
|
+
|
|
91
|
+
中止下载是安全的,因为它没有副作用——重新下就是了。写文件不是。
|
|
92
|
+
|
|
93
|
+
## 配置
|
|
94
|
+
|
|
95
|
+
面板里点监督员形象打开,或直接编辑 `$DSH_HOME/stall-guard/config.json`:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"version": 1,
|
|
100
|
+
"enabled": true,
|
|
101
|
+
"watchDownloads": true,
|
|
102
|
+
"downloadSeconds": 30,
|
|
103
|
+
"timers": { "fetch": 15, "search": 15, "read": 20, "write": 30, "exec": 30, "long": 120, "other": 30 },
|
|
104
|
+
"overrides": { "web_fetch": 45 },
|
|
105
|
+
"autoSwitch": true,
|
|
106
|
+
"scenes": {
|
|
107
|
+
"download": { "enabled": true, "seconds": 30 },
|
|
108
|
+
"fetch": { "enabled": true, "seconds": 15 },
|
|
109
|
+
"search": { "enabled": true, "seconds": 15 }
|
|
110
|
+
},
|
|
111
|
+
"supervisor": { "show": true, "display": "avatar" }
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
- `downloadSeconds` —— 下载预算。GitHub 慢就调大,急着换源就调小。
|
|
116
|
+
- `watchDownloads: false` —— 完全关掉下载检测,下载命令就按 `exec` 类处理(只提示不中止)。
|
|
117
|
+
- `overrides` —— 给单个工具单独设秒数。
|
|
118
|
+
|
|
119
|
+
## 监督员(次要功能)
|
|
120
|
+
|
|
121
|
+
三种形态,面板里切换:
|
|
122
|
+
|
|
123
|
+
| 形态 | 平时 | 卡住时 |
|
|
124
|
+
|---|---|---|
|
|
125
|
+
| `dot` | 状态栏 6px 半透明点 | 变红脉冲 |
|
|
126
|
+
| `icon` | 静止图标 | 弹跳 + 发光 |
|
|
127
|
+
| `avatar` | 闭眼小鲸鱼 | 弹跳 + 气泡说出原因 |
|
|
128
|
+
|
|
129
|
+
### 显示开关
|
|
130
|
+
|
|
131
|
+
面板里「显示监督员」一勾即关,**关掉后守卫照常工作**(下载一样会被掐断、提示一样会写进工具结果),
|
|
132
|
+
只是不再画那个形象。右下角会留一个 14px 的半透明小点,点它随时能打开面板重新打开。
|
|
133
|
+
|
|
134
|
+
### 图标外观(仅本浏览器)
|
|
135
|
+
|
|
136
|
+
| 项目 | 范围 | 说明 |
|
|
137
|
+
|---|---|---|
|
|
138
|
+
| 大小 | 14–64px | 滑块,带数值回显 |
|
|
139
|
+
| 透明度 | 20%–100% | 下限 20% 是为了它仍然可见、可点 |
|
|
140
|
+
| 位置 | 标题栏 / 浮动 | 浮动模式下**可以拖到任何地方**,位置会记住 |
|
|
141
|
+
|
|
142
|
+
外观存在 `localStorage`(键 `dsh-stall-guard.appearance.v1`),不写进 Host 配置:
|
|
143
|
+
这是"这个浏览器上我喜欢多大"的个人偏好,不该同步给所有人,也省掉一次往返。
|
|
144
|
+
拖动位置会自动夹在视口内,窗口变小也不会跑到屏幕外。
|
|
145
|
+
|
|
146
|
+
那句提示来自**内置的中英文案表**,不调用模型,零 token。
|
|
147
|
+
|
|
148
|
+
例如:`下载 30s 没完成,已中止,换源提示已交给智能体。`
|
|
149
|
+
|
|
150
|
+
文案按工具类型、动作、结果三个维度挑选,中英双语,切换界面语言时已在屏幕上的提示也会跟着改写。
|
|
151
|
+
|
|
152
|
+
## 自定义预设(完全不碰模型)
|
|
153
|
+
|
|
154
|
+
面板里可以直接写**你要发给智能体看的原文**,插件只做占位符替换,一个模型都不叫。
|
|
155
|
+
|
|
156
|
+
三个场景各一份,中英各一份:
|
|
157
|
+
|
|
158
|
+
| 场景 | 什么时候用 |
|
|
159
|
+
|---|---|
|
|
160
|
+
| 下载 | `git clone` / `pnpm install` / `curl` 超时 |
|
|
161
|
+
| 抓取 | `web_fetch` 超时改搜索 |
|
|
162
|
+
| 搜索 | `web_search` 超时重试 |
|
|
163
|
+
|
|
164
|
+
### 占位符
|
|
165
|
+
|
|
166
|
+
写进文本框,发送时自动替换:
|
|
167
|
+
|
|
168
|
+
| 占位符 | 含义 |
|
|
169
|
+
|---|---|
|
|
170
|
+
| `{{label}}` | 在下载什么(如 `git repository github.com/a/b.git`) |
|
|
171
|
+
| `{{channel}}` | 渠道(`git`/`npm`/`pip`/`cargo`/`go`/`http`) |
|
|
172
|
+
| `{{target}}` | 目标地址或仓库 |
|
|
173
|
+
| `{{host}}` | 主机名 |
|
|
174
|
+
| `{{command}}` | 原始命令(超 240 字会截断) |
|
|
175
|
+
| `{{seconds}}` | 超时阈值 |
|
|
176
|
+
| `{{elapsed}}` | 实际耗时 |
|
|
177
|
+
| `{{hints}}` | 内置的镜像候选清单(**最省事的用法**) |
|
|
178
|
+
| `{{query}}` / `{{sources}}` | 搜索词 / 结果数(抓取、搜索场景) |
|
|
179
|
+
|
|
180
|
+
面板里每个占位符都是一个可点的按钮,点一下追加到末尾。
|
|
181
|
+
|
|
182
|
+
### 例子
|
|
183
|
+
|
|
184
|
+
最简写法(完全自己控制):
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
{{label}} 卡了 {{seconds}} 秒。换源,别重试同一个地址。
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
想保留内置的镜像清单但换掉措辞:
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
下载超时了({{seconds}}s),源:{{host}}
|
|
194
|
+
请从下面挑一个换:
|
|
195
|
+
{{hints}}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### 几个行为约定
|
|
199
|
+
|
|
200
|
+
- **空着 = 用内置文案**。不会变成"什么都不发"——清空不会让插件失声。
|
|
201
|
+
- **"用内置文案"按钮**等同于清空;"恢复默认"会把内置全文填进文本框供你改。
|
|
202
|
+
- **占位符拼错会原样保留**(比如写成 `{{labl}}`),不会静默变成空字符串——否则你永远发现不了。
|
|
203
|
+
- 上限 4000 字,超了截断并提示。
|
|
204
|
+
- **预设是唯一的文案来源**:这个插件从不调用模型,所以预设就是发给智能体的最终文本。
|
|
205
|
+
- 清理半成品的那句提醒会**始终追加**(即使是自定义预设),因为少了它重试会撞上 `already exists`。
|
|
206
|
+
- 占位符不是代码,`${...}` 之类原样输出,不执行任何东西。
|
|
207
|
+
|
|
208
|
+
## Token 成本
|
|
209
|
+
|
|
210
|
+
**这个插件在任何情况下都不调用模型。**
|
|
211
|
+
|
|
212
|
+
| 行为 | 成本 |
|
|
213
|
+
|---|---|
|
|
214
|
+
| 守卫逻辑、计时、下载检测 | **0** |
|
|
215
|
+
| 每秒轮询 `state.json` | **0**(本机 127.0.0.1 HTTP,不经模型) |
|
|
216
|
+
| 状态栏那句提示 | **0**(内置文案表,写死的) |
|
|
217
|
+
| 换源提示(发给智能体) | 占上下文 ~195–325 token,**只在真卡住时产生** |
|
|
218
|
+
|
|
219
|
+
唯一进入智能体上下文的是换源提示,平均约 240 token/次卡顿。平顺时是 0。
|
|
220
|
+
|
|
221
|
+
这笔通常还是**省钱的**——它替代了「智能体干等几分钟后放弃、再乱猜源」。
|
|
222
|
+
|
|
223
|
+
### 为什么没有「用模型生成提示」这个选项
|
|
224
|
+
|
|
225
|
+
之前有过,已删除。理由是它不该存在:
|
|
226
|
+
- 提示要传达的事实(哪个工具、跑了多久、阈值多少、做了什么)守卫**已经完全知道**;
|
|
227
|
+
- 模型只能换个说法,不能更准,却每次卡顿都要花约 300 token;
|
|
228
|
+
- 而且那句提示是**给你看的**,不是给智能体看的——花钱美化给人看的一句话,不值。
|
|
229
|
+
|
|
230
|
+
内置文案已经足够具体,例如:
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
下载卡住了:git repository github.com/nodejs/node.git 在 30 秒内没完成(已经跑了 30 秒,已中止)。
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## 隐私
|
|
237
|
+
|
|
238
|
+
- 除了监督模型那一次调用,**不联网**。
|
|
239
|
+
- 卡顿记录只在内存,最多 10 条,重启清空。
|
|
240
|
+
- 配置只写在你自己 `~/.dsh` 下。
|
|
241
|
+
|
|
242
|
+
## 兼容性
|
|
243
|
+
|
|
244
|
+
- 需要 `tools/execute` waterfall 和 `webServer`;没有 `webServer` 的组合照常工作,只是没面板。
|
|
245
|
+
- 不注册任何工具,不占用工具名。
|
|
246
|
+
- 只用一个 slot:`conversation.session.header.utilities`。
|
|
247
|
+
|
|
248
|
+
## 和类似插件的区别
|
|
249
|
+
|
|
250
|
+
| 插件 | 它做什么 |
|
|
251
|
+
|---|---|
|
|
252
|
+
| `dsh-turn-doctor` | 解释**已失败**的一轮是哪层杀的(事后) |
|
|
253
|
+
| `dsh-llm-fallbacks` | 模型请求失败换 provider(LLM 层) |
|
|
254
|
+
| `dsh-repeat-tool-breaker` | 拦重复调同一工具(防循环) |
|
|
255
|
+
| `@lolkda/dsh-retry` | 改 provider 重试参数 |
|
|
256
|
+
| **本插件** | **下载卡住 → 掐掉 → 把换源提示写给智能体(工具层,事中)** |
|
|
257
|
+
|
|
258
|
+
## 开发
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
node --test test/*.test.mjs # 144 个用例
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## 许可
|
|
265
|
+
|
|
266
|
+
MIT,见 [LICENSE](LICENSE)。素材来源见 [PROVENANCE.md](PROVENANCE.md)。
|