mingdao-harness 0.6.12 → 0.6.14
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 +2 -2
- package/docs/CONFIG.md +112 -22
- package/docs/DEVELOPER.md +13 -7
- package/package.json +1 -1
- package/presets/local-model.json +1 -1
- package/src/agent.js +275 -35
- package/src/model-discovery.js +394 -44
- package/src/presets.js +34 -9
- package/src/web/app.js +20 -1
- package/src/web/server.js +125 -9
- package/presets/readonly-audit.json +0 -10
package/README.md
CHANGED
|
@@ -275,7 +275,7 @@ mingdao cost --by pack # 垂域费用分账
|
|
|
275
275
|
|
|
276
276
|
## 配置与扩展
|
|
277
277
|
|
|
278
|
-
配置字段、权限规则、Hooks、MCP、云同步、自定义 Provider 的完整说明见 [docs/CONFIG.md](docs/CONFIG.md);架构见 [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md);Provider 扩展见 [docs/PROVIDERS.md](docs/PROVIDERS.md)。
|
|
278
|
+
配置字段、权限规则、Hooks、MCP、云同步、自定义 Provider 的完整说明见 [docs/CONFIG.md](docs/CONFIG.md);架构见 [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md);Provider 扩展见 [docs/PROVIDERS.md](docs/PROVIDERS.md);桌面版自动更新(检查 / 下载 / 来源签名 / feed 与发版链路)见 [docs/DESKTOP-AUTO-UPDATE.md](docs/DESKTOP-AUTO-UPDATE.md)。
|
|
279
279
|
|
|
280
280
|
## 常见问题
|
|
281
281
|
|
|
@@ -299,7 +299,7 @@ src/ CLI / Agent 循环 / 工具 / 权限 / 技能库 / MCP / 云
|
|
|
299
299
|
skills/ 14 个内置常驻技能
|
|
300
300
|
skills-lib/ 22 个可安装技能库预设
|
|
301
301
|
registry/ 线上技能 registry 索引
|
|
302
|
-
presets/ 内置 Agent
|
|
302
|
+
presets/ 内置 Agent 预设(只 `local-model`:只调参数,不含人格/工具白名单/权限)
|
|
303
303
|
packs/ 内置示例 Pack(example-hello)
|
|
304
304
|
assets/ 内置分词器数据(tokenizer-data.json.gz,约 762 KB,`src/tokenizer.js` 使用)
|
|
305
305
|
desktop/ Electron 桌面版外壳(含自动更新、原生目录选择器)
|
package/docs/CONFIG.md
CHANGED
|
@@ -111,7 +111,7 @@ WebUI 中每个会话记住自己的工作目录:新会话记录创建时的
|
|
|
111
111
|
> 那里"一次误按 y 就绕过自己写的禁令"是不可接受的;
|
|
112
112
|
> 交互式日常使用保持默认即可——每次放行都是一次明确的、点名规则的确认。
|
|
113
113
|
|
|
114
|
-
### 权限优先级与预设(v0.6.14
|
|
114
|
+
### 权限优先级与预设(v0.6.14,v0.6.16 收窄)
|
|
115
115
|
|
|
116
116
|
口径:**显式选择 > 预设建议(`recommendedPermission`)> config.json**。
|
|
117
117
|
(这句说的是"档位意图从哪来"的优先序;落到判定上,`recommendedPermission` **只是建议**——不参与判定、
|
|
@@ -120,26 +120,31 @@ WebUI 中每个会话记住自己的工作目录:新会话记录创建时的
|
|
|
120
120
|
| 层级 | 从哪来 | 性质 |
|
|
121
121
|
| --- | --- | --- |
|
|
122
122
|
| 显式选择 | CLI `mingdao run "…" --permission auto\|ask\|readonly`、REPL `/mode`、WebUI「权限模式」下拉(随本次请求发出) | **覆盖**:本回合的终值,任何预设都压不过它 |
|
|
123
|
-
| 预设建议 | 预设 JSON 的 `recommendedPermission
|
|
123
|
+
| 预设建议 | 预设 JSON 的 `recommendedPermission`(**内置预设不使用它**;字段支持保留给第三方/自写预设);`GET /api/presets` 会透出该字段 | **只是建议**:不参与权限判定、不静默改档;想让建议生效,就在上面那一层显式选它 |
|
|
124
124
|
| config.json | `permission` 字段(支持 `{mode, allow, deny}` 对象形态) | **兜底**:没有显式选择、预设也没声明 `permission` 时才用它 |
|
|
125
125
|
|
|
126
126
|
三条要点(别再踩):
|
|
127
127
|
|
|
128
|
-
-
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
- **要"只读",请自己组合权限档与工具白名单。** 预设的 `tools` 白名单是只读的**硬约束**
|
|
129
|
+
(白名单里没有 `write`/`edit`,写工具根本不会出现在模型可见的工具表里——这比任何权限档都硬,
|
|
130
|
+
权限档只决定"要不要逐次询问");把会话钉在 `readonly` 档则是另一层。内置预设**不替你决定**这两件事,
|
|
131
|
+
正确的做法是在权限档里显式选 `readonly`,并在自己的预设里收 `tools` 白名单。
|
|
131
132
|
- **`permission` 字段是覆盖。** 预设声明它会改本回合的档位(更宽松的方向被反提权拦掉:
|
|
132
|
-
`readonly→auto` 一律拒绝并只发一条 ⚠ banner
|
|
133
|
-
|
|
133
|
+
`readonly→auto` 一律拒绝并只发一条 ⚠ banner)。**内置预设不携带任何权限字段**——`permission`
|
|
134
|
+
的实际效果只是"沉默覆盖用户的选择":负责人实测的坑就是界面上选了「自动」,勾上当时的审计预设后仍按
|
|
134
135
|
`readonly` 跑,于是每调用一次非只读工具都弹「只读模式将拦截 task,是否本次放行?」。
|
|
135
136
|
第三方/老预设仍可声明(兼容),但同样受反提权约束,且要自己承担"覆盖用户选择"的后果。
|
|
136
|
-
- **`recommendedPermission`
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
>
|
|
142
|
-
>
|
|
137
|
+
- **`recommendedPermission` 只是建议,且内置预设不使用它。** 它是预设对"我适合跑在哪个档"的表达,
|
|
138
|
+
只做展示/透出,不写进任何权限判定;权限档以你的显式选择为准,其次才是 config.json 里的默认值。
|
|
139
|
+
v0.6.16 起**内置预设连这个字段也不用**(避免任何形式的权限覆盖/权限偏好暗示)——字段本身保留,
|
|
140
|
+
第三方/自写预设可以继续用它。
|
|
141
|
+
|
|
142
|
+
> **内置预设只提供参数类默认值。** 发行版面向普通大众,不为某种任务做定制,因此内置只保留
|
|
143
|
+
> `local-model`(只调 `contextBudget`/`maxOutputTokens`/`maxRounds`,**不加人格、不限制工具、
|
|
144
|
+
> 不涉及权限**)。v0.6.16 已**删除**原来的内置「只读代码审计」预设 `readonly-audit`(它只是负责人
|
|
145
|
+
> 拿 MDH 做的一次较长任务的测试);老名字 `local-audit` 仍可用,但会提示已更名为 `local-model`。
|
|
146
|
+
> 另:审计日志/账本与预设无关——那是 `config.audit` 与 `mingdao audit` / `mingdao ledger` 的事,
|
|
147
|
+
> 别把任何预设当合规审计开关。
|
|
143
148
|
|
|
144
149
|
## 项目记忆(自动写入项目目录,默认已自忽略)
|
|
145
150
|
|
|
@@ -419,26 +424,108 @@ completion 计费,防止推理吃满上限时空轮白烧)、`compactTrigger
|
|
|
419
424
|
```
|
|
420
425
|
|
|
421
426
|
- **判据**:连续 N 分钟**既没有"成功且不重复的工具结果"、也没有新的正文/推理增量** → 主动中止整个
|
|
422
|
-
回合,并如实报告「连续 N 分钟没有任何工具调用、也没有新内容,已中止」+
|
|
427
|
+
回合,并如实报告「连续 N 分钟没有任何工具调用、也没有新内容,已中止」+ 已发生的模型轮次/工具调用数,
|
|
428
|
+
外加**中止时正在等待哪个工具、等了多久**,以及与 `capped`/`aborted` 的区别
|
|
429
|
+
(capped = 跑满步数上限、可续跑;aborted = 你点的停止;stalled = 再等下去也不会产出新东西)。
|
|
423
430
|
重复调用(name+args 完全相同)与失败调用**不算进展**——真机现场正是它们把时间烧光的。
|
|
424
431
|
- **默认 60 分钟**的依据:现有单请求总量上限是本地 1800s;回合级阈值取它的 **2 倍**,
|
|
425
432
|
保证"一次慢 prefill"永远由更具体的请求级超时(首帧/空闲/总量各有文案)先说话,看门狗不抢答;
|
|
426
433
|
而真干活的回合每隔几秒就有工具结果或正文增量,60 分钟零增量在任何正常回合都不可能。
|
|
427
|
-
- 该值**不能**用 0/负数/Infinity 关掉(一律回落默认,fail-safe
|
|
428
|
-
(24
|
|
429
|
-
|
|
430
|
-
|
|
434
|
+
- 该值**不能**用 0/负数/Infinity 关掉(一律回落默认,fail-safe);子代理会**继承父回合的阈值**
|
|
435
|
+
(24 个并行子代理不会各跑各的几小时),且继承的**截止时刻是活的**——它随父回合的进展前移。
|
|
436
|
+
- **子代理的进展算父回合的进展**(v0.6.13 真机修复):父回合在 `await task` 期间拿不到任何中间信号,
|
|
437
|
+
所以子代理每有一次真实进展(成功且不重复的工具结果 / 新正文增量)就回调父回合,父回合据此续期,
|
|
438
|
+
并把快照挂在 `io.turnProgress.subagent` 上——`web-server.log` 的进度行与界面状态条因此能写出
|
|
439
|
+
「正在等待工具 task(已 620s)· 子代理「审计 agent.js」已跑 12 轮 / 17 次工具调用,最后进展 3s 前」,
|
|
440
|
+
"在等子代理"与"卡死"才分得开(真机现场日志里只有前者,看不出子代理是在干活还是死了)。
|
|
441
|
+
- **子代理卡住由它自己的看门狗先响**:父回合在等待子代理时只多等 15s
|
|
442
|
+
(`SUBAGENT_WAIT_GRACE_MS`,相对默认 60 分钟是 0.4%——**不是**放宽阈值),
|
|
443
|
+
这样子代理的收口结论("自己无进展"还是"父回合整轮无进展")能原样回传父回合,
|
|
444
|
+
而不是被父回合抢先掐断、只剩一句"父回合中止"。
|
|
445
|
+
- **stalled 在界面上必须有说明**:内核发一条告警 banner(内容与 `done.note` 同源),
|
|
446
|
+
前端在消息下方再留一条,并把结局(含两种 stalled 原因)写进控制台
|
|
447
|
+
——桌面壳日志取的就是渲染进程 console,此前那里只有「回合收尾:generating=false」,
|
|
448
|
+
与内核的 `status=stalled` 对不上。
|
|
449
|
+
|
|
450
|
+
#### 端点预检(v0.6.13,本地端点自动执行;v0.6.13 修复误报)
|
|
431
451
|
|
|
432
452
|
对**本地端点**(baseUrl 是回环/内网,或 `customModels.<名>.local: true`)在开工前做一次轻量预检
|
|
433
453
|
(结果缓存 10 分钟,只读不写你的配置):
|
|
434
454
|
|
|
435
|
-
1.
|
|
455
|
+
1. 读**引擎自述上下文**(`GET /props`,见下一条)——配置的 `contextWindow` 超没超引擎能力,只有这里能知道;
|
|
436
456
|
2. 发 **3 次**极小请求(1 条 user + 1 个工具声明 + `max_tokens: 256`),看 `tool_calls` 与 `finish_reason`,
|
|
437
457
|
给出三态之一:**稳定支持**(3/3)/ **不稳定**(N/3,会提示"agent 任务可能步数为 0")/ **不支持**(0/3);
|
|
438
458
|
被 `max_tokens` 截断的样本(`finish_reason: length`,思考型模型常见)判为**不可判定**,不当作"不支持";
|
|
459
|
+
(引擎实际加载的模型名从 chat 响应的 `model` 字段读——**不**额外打 `GET /models`:有的端点没实现它,
|
|
460
|
+
而 llama.cpp 在流式响应里直接回完整文件路径,语义等价且少一个请求。)
|
|
439
461
|
3. 再发一次 **参考 prefill**(约 2000 tokens 的提示)测耗时;
|
|
440
462
|
4. 与本机历史值比对:**同一端点明显变慢**(≥3 倍)会提示"该端点可能仍在处理上一个请求,建议重启引擎"。
|
|
441
463
|
|
|
464
|
+
**预检的耗时与"失败不阻断"(v0.6.13 修复)**
|
|
465
|
+
|
|
466
|
+
- **探针只打 `POST {base}/chat/completions`**(与主请求同一个 URL),**不发** `GET /models`;
|
|
467
|
+
`GET /props` 只在引擎自报模型名后才打。所以"只实现了 chat 的端点"**一个 GET 都不会收到**,
|
|
468
|
+
不会被预检打扰(`test/smoke.js` §141 用桩服务钉住"GET 次数 = 0")。
|
|
469
|
+
- **单次尝试 1.5s、共 3 次、尝试之间退避 300/700ms**,整个探针的时间预算 15s(`timeoutMs` 是**总预算**,
|
|
470
|
+
不是单次超时);参考 prefill 单独放宽到 20s(本机 35B 实测 6.6~7.8s/2000 tokens)。
|
|
471
|
+
单次超时**覆盖到首帧**:引擎"回了响应头、卡在 prefill 或正在启动"也算超时,不会把回合发起一直挂着。
|
|
472
|
+
- **预检是尽力而为:失败只降级、不阻断**。探针自身任何异常都被吞掉(只在 `web-server.log` 留一行
|
|
473
|
+
"预检 … 失败(忽略,按默认超时继续)"),本回合照常发起——预检结论只影响 banner、日志与自适应超时。
|
|
474
|
+
- **失败原因分开判、分开说**(`web-server.log` 的 `chat 预检 … reason=…` 和 banner 文案都跟着变):
|
|
475
|
+
|
|
476
|
+
| `reason` | 判据 | 文案(节选) | 你该做什么 |
|
|
477
|
+
| --- | --- | --- | --- |
|
|
478
|
+
| `refused` | `ECONNREFUSED` | `❌ 不可达:连接被拒(端口没人监听)` | 这才是"引擎没起来/端口不对":确认端口与进程 |
|
|
479
|
+
| `timeout` | 1.5s 内没有首帧 | `⏱ 探针超时:1.5s 内没有首帧` | 端口是通的:引擎在 prefill 或**正在启动**;不代表主请求会失败 |
|
|
480
|
+
| `reset` | 连接被对端断开 | `❌ 连接被断开` | 引擎可能刚崩/正在重启 |
|
|
481
|
+
| `http-unimplemented` | HTTP 404/405/501 | `❌ 探针被拒绝:HTTP 404(端点未实现该探针请求)` | 该端点没有实现 `POST {base}/chat/completions`(探针与主请求同一个 URL) |
|
|
482
|
+
| `http-auth` / `http` | 401/403、其它 4xx/5xx | `HTTP 401(鉴权被拒)` 等 | 端口是通的:按状态码排查密钥/路由 |
|
|
483
|
+
| `other` | 其它网络错误 | `❌ 探针失败:其它错误(…)` | 按错误码排查,不要当成"引擎没起来" |
|
|
484
|
+
|
|
485
|
+
- **失败结论只保鲜 60 秒**(成功结论仍缓存 10 分钟)。这条是**真机误报的根因**:v0.6.13 早期版本的
|
|
486
|
+
进程内备忘没有 TTL,进程启动时(引擎还没起来)留下的"不可达"被之后**每一个新回合**原样重放
|
|
487
|
+
(真机 `web-server.log:413` 07:03:02 的真实探测 → `:416` 07:08:13、`:799` 10:13:58 两次重放,
|
|
488
|
+
相隔 7 小时 10 分钟),而同一回合其实完全可用(`:803` 首帧 8.7s)。现在超过 60 秒会**重测**。
|
|
489
|
+
- **复核行**:如果预检判过"不可达",而这一回合**真的出过首帧**,回合结束后日志会留一行
|
|
490
|
+
`chat 预检复核 <taskId> 预检曾判不可达(reason=…),但本回合实际可用(首帧 Xs)——预检判据需复核`
|
|
491
|
+
——看到它说明"预检判据"该被质疑,而不是"引擎没起来"。
|
|
492
|
+
|
|
493
|
+
#### 预检读「引擎自述上下文」(v0.6.13)
|
|
494
|
+
|
|
495
|
+
本地端点预检时**额外读一次引擎自述**(`GET /props`,只读、不改配置):
|
|
496
|
+
|
|
497
|
+
- llama.cpp 的 `/props` 通常返回 `default_generation_settings.n_ctx`(有的版本另有顶层 `n_ctx`/`n_ctx_train`);
|
|
498
|
+
其他引擎能读多少读多少(`max_model_len`、`context_length`、`model_info.*.context_length`),
|
|
499
|
+
**读不到就跳过并说明**(不猜、不编造、也不据此判定端点不行)。
|
|
500
|
+
`/props` 挂在根上,而 `baseUrl` 通常带 `/v1`,预检会先剥掉 `/v\d+` 再试,失败再退回原样。
|
|
501
|
+
- **什么时候会去打这个请求**:只有端点**自报了模型名**才打。llama.cpp 家族(含 llama-cpp-python/
|
|
502
|
+
koboldcpp/LM Studio)总会在响应里回模型名或模型文件路径;回不了名的多半是"只实现了
|
|
503
|
+
`/v1/chat/completions`"的网关或测试桩——它们不认识 `/props`,多打一个 GET 可能把对方打断
|
|
504
|
+
(本仓 `test/e2e-web.js` 的 mock 就是这样被打挂的:它只按 `POST + JSON body` 解析)。
|
|
505
|
+
跳过时结论里会写「引擎自述上下文:跳过(该端点未自报模型名,不确认它实现 /props)」,
|
|
506
|
+
不会假装核对过。
|
|
507
|
+
- 结论会与配置**并排**写出来,同时出现在界面 banner、`web-server.log`
|
|
508
|
+
(`预检 <模型> … 引擎自述上下文=… 配置=…`)与发送前的规模预告里:
|
|
509
|
+
|
|
510
|
+
```
|
|
511
|
+
⚠ 引擎自述上下文 32768 vs 配置 131072 —— 配置超出引擎能力,长上下文将直接被引擎拒绝
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
- 为什么这条必须有:真机实测配置 `contextWindow: 131072`、引擎只装了 32768,
|
|
515
|
+
15,983 tokens 的 prompt 在 prefill 阶段就被引擎拒绝(`insufficient memory: the request exceeded
|
|
516
|
+
available GPU memory … during prefill`)。此时**换预设、调小 `contextBudget`、调大 `timeout.*`
|
|
517
|
+
都无效**——它们改不了引擎的 `n_ctx`;要么在引擎侧把上下文窗口调大
|
|
518
|
+
(llama.cpp 的 `--ctx-size` / `--context-window`),要么把 `customModels.<名>.contextWindow` 改成 ≤ 引擎值。
|
|
519
|
+
|
|
520
|
+
#### 发送前的规模预告由预检实测推导(v0.6.13)
|
|
521
|
+
|
|
522
|
+
回合开始前的 `📏 本轮上下文 ≈ …` 预告,在**有预检实测**时按
|
|
523
|
+
`参考 prefill 耗时 × 本轮 tokens ÷ 参考 tokens` 线性外推,并在文案里注明这是外推、以及
|
|
524
|
+
"长上下文下引擎可能显著变慢"的实测差值(本机 16k tokens 首帧 53.7s,而按同一份预检外推只有 0.6s)——
|
|
525
|
+
只报乐观值会训练用户忽略这条告警。**只有拿不到预检数据**(端点不可达 / 不可判定)时才退回
|
|
526
|
+
"prefill 可能需数分钟至数十分钟"的保守文案;外推超过 60s(`PREFILL_SLOW_WARN_MS`)才告警,
|
|
527
|
+
且必须写出依据(预检实测值 + 本轮 tokens + 阈值)。
|
|
528
|
+
|
|
442
529
|
预检结论会出现在:回合开始时的界面 banner、`web-server.log`(`预检 <模型> …` 行)、
|
|
443
530
|
以及发送前的规模预告里。并且**按实测 TTFT 自适应**超时:首帧上限 = clamp(max(实测首帧×20, 参考prefill×5),
|
|
444
531
|
既有默认, 1800s)、无进展看门狗 = clamp(max(实测首帧×100, 参考prefill×20), 10min, 60min);
|
|
@@ -494,10 +581,13 @@ curl -s http://127.0.0.1:8081/v1/models | head -c 400 # 端口按你的部
|
|
|
494
581
|
|
|
495
582
|
| 现象 | 内核会给什么信号 |
|
|
496
583
|
| --- | --- |
|
|
497
|
-
| 引擎没起来 / 端口不对 | 预检 `❌
|
|
584
|
+
| 引擎没起来 / 端口不对 | 预检 `❌ 不可达:连接被拒(端口没人监听)`(`reason=refused`);请求以 `网络请求失败:fetch failed` 报错(几秒内)。**注意区分**:`⏱ 探针超时`(端口是通的)/ `❌ 探针被拒绝:HTTP 404`(端点没实现该请求)都不是"引擎没起来"——见上面「端点预检」的失败原因表 |
|
|
585
|
+
| 引擎正在启动(端口刚 bind、模型在加载) | 预检会退避重试(300/700ms);仍没等到首帧则记 `reason=timeout`——**它不代表本回合会失败**,主请求照常发起;若本回合真的出过首帧,回合结束后日志会写「预检曾判不可达 … 但本回合实际可用(首帧 Xs)——预检判据需复核」 |
|
|
498
586
|
| 连上但不发首帧 | 到 `timeout.firstTokenMs` 报「首 token 等待超限(Ns,本地模型长上下文 prefill 可能很慢)——可调大 config.timeout.firstTokenMs…」 |
|
|
499
587
|
| 有帧但长时间没新数据 | 到 `timeout.streamIdleMs`(默认 120s)报「流式响应空闲超限(Ns 无新数据)」 |
|
|
500
|
-
| 每轮都能返回、但什么都没做成 | 到 `noProgressTimeoutMs`(默认 60min,快端点自适应到 10min)报「连续 N
|
|
588
|
+
| 每轮都能返回、但什么都没做成 | 到 `noProgressTimeoutMs`(默认 60min,快端点自适应到 10min)报「连续 N 分钟没有任何工具调用、也没有新内容,已中止」,并附**中止时正在等待哪个工具/等了多久**;界面另有告警 banner(与 `capped` 跑满步数、`aborted` 你点的停止**区分开**) |
|
|
589
|
+
| 一直在等 `task` 子代理 | 进度行/状态条会写出**子代理自己的进度**(第几轮、几次工具调用、最后进展距今多久);子代理有进展时父回合不会被判无进展,子代理真卡住则由**它自己的**看门狗先中止并把原因回传父回合 |
|
|
590
|
+
| 引擎装不下配置的窗口 | 预检读 `GET /props` 得到引擎自述上下文,与配置并排;配置超出即告警「配置超出引擎能力,长上下文将直接被引擎拒绝」(换预设/调 `contextBudget` 都无效) |
|
|
501
591
|
| 上游 4xx/5xx(模板/内存/鉴权…) | 错误里带**上游原文**并附一条可操作判断(例如"该端点的模板不接受当前 messages 形态") |
|
|
502
592
|
|
|
503
593
|
**第 5 步:模型不支持工具调用时会怎样**
|
package/docs/DEVELOPER.md
CHANGED
|
@@ -25,13 +25,16 @@
|
|
|
25
25
|
|
|
26
26
|
1. `<项目>/.mingdao/presets/<名>.json` — 项目级(随项目走)
|
|
27
27
|
2. `~/.mingdao/presets/<名>.json` — 用户级(本机全局)
|
|
28
|
-
3. `presets/`(随 npm 包分发)—
|
|
28
|
+
3. `presets/`(随 npm 包分发)— 内置参考。**内置预设的定位:只提供参数类默认值——不携带人格、
|
|
29
|
+
不限制工具、不涉及权限**(发行版面向普通大众,不为某种任务做定制)。因此内置**只有一个**:
|
|
29
30
|
- `local-model` —— **只放"让本地模型跑得动"的参数**(`contextBudget`/`maxOutputTokens`/`maxRounds`)。
|
|
30
|
-
本地模型只是替换云模型 API
|
|
31
|
-
- `readonly-audit` —— 审计人格 + 只读工具白名单(`tools`)+ `recommendedPermission: "readonly"`(只是**建议**)。
|
|
31
|
+
本地模型只是替换云模型 API,**功能一致**:所以它不带人格、不限制工具、不涉及权限。
|
|
32
32
|
- 老名字 `local-audit` 保留为**别名**(指向 `local-model`):按老名字调用仍可用,且会打印一次
|
|
33
33
|
「已更名」提示(CLI/内核日志)并在 WebUI 用 banner 说明——改名兼容,但不静默。
|
|
34
34
|
若你自己在项目级/用户级写了 `local-audit.json`,**以你的文件为准**(别名只在没找到同名预设时兜底)。
|
|
35
|
+
- v0.6.16 起内置**不再有**「只读代码审计」预设(`readonly-audit` 已删除:代码审计只是负责人拿
|
|
36
|
+
MDH 做的一次较长任务的测试,发行版不做任务定制)。要只读效果请**自己组合**权限档(`readonly`)
|
|
37
|
+
与工具白名单(`tools`)——见 §1.2。
|
|
35
38
|
|
|
36
39
|
### 1.2 格式
|
|
37
40
|
|
|
@@ -60,10 +63,11 @@
|
|
|
60
63
|
|
|
61
64
|
| 字段 | 语义 | 谁该用 |
|
|
62
65
|
| --- | --- | --- |
|
|
63
|
-
| `permission` | **覆盖**本回合的权限档(仍受反提权规则约束:只能更保守,不能更宽松) |
|
|
64
|
-
| `recommendedPermission` | **建议**:只透出给界面/诊断,**不参与判定、不覆盖用户选择** |
|
|
66
|
+
| `permission` | **覆盖**本回合的权限档(仍受反提权规则约束:只能更保守,不能更宽松) | 第三方/老预设;**内置预设不涉及权限,不使用它** |
|
|
67
|
+
| `recommendedPermission` | **建议**:只透出给界面/诊断,**不参与判定、不覆盖用户选择** | 第三方/自写预设想表达"建议档"时可用;**内置预设不使用它**(避免任何权限偏好暗示) |
|
|
65
68
|
|
|
66
69
|
只读的**硬约束**是 `tools` 白名单(不含 `write`/`edit`,模型连写工具都看不到),不是权限档。
|
|
70
|
+
内置预设不替你决定权限档,也不限制工具:要只读就**自己组合** `permission.mode: "readonly"` 与 `tools` 白名单。
|
|
67
71
|
|
|
68
72
|
#### 参数怎么给"本地模型"用(v0.6.15)
|
|
69
73
|
|
|
@@ -79,8 +83,10 @@
|
|
|
79
83
|
且大上下文会顶满引擎内存预算)。给 32k–65k 通常就够单个模块级任务。
|
|
80
84
|
- 模型窗口/最大输出等**能力声明**请写在 `config.customModels.<模型名>`
|
|
81
85
|
(`contextWindow`/`maxOutputTokens`/`local`),不要再写一份进预设——两处会漂移。
|
|
82
|
-
-
|
|
83
|
-
|
|
86
|
+
- 想同时要"本地模型的保守参数 + 只读":预设**不能叠加**(一次只能选一个内置预设),而且 v0.6.16 起
|
|
87
|
+
内置不再提供只读审计预设。自己的做法是**复制一份 `local-model` 再按需合并**:在 `tools` 白名单里
|
|
88
|
+
只留只读工具,权限档在你那一层显式选 `readonly`(预设里**不要**写 `permission`/`recommendedPermission`
|
|
89
|
+
——那会分别造成"沉默覆盖"与"权限偏好暗示")。
|
|
84
90
|
|
|
85
91
|
### 1.3 使用
|
|
86
92
|
|
package/package.json
CHANGED
package/presets/local-model.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "local-model",
|
|
3
3
|
"label": "本地模型(保守参数)",
|
|
4
|
-
"description": "给**本地部署模型**用的保守参数预设。先说清两件事:① 本地模型与云模型**功能一致**——本预设不加人格、不限制工具、不建议权限档,只把「上下文预算 / 单次最大输出 / 轮次」调到本地推理跑得动的量级;②
|
|
4
|
+
"description": "给**本地部署模型**用的保守参数预设。先说清两件事:① 本地模型与云模型**功能一致**——本预设不加人格、不限制工具、不建议权限档,只把「上下文预算 / 单次最大输出 / 轮次」调到本地推理跑得动的量级;② 它**不是**某个任务的专用预设(发行版面向普通大众,内置预设只提供参数类默认值,不携带人格、不限制工具、不涉及权限)。为什么只调这几个数:本地引擎的瓶颈在 prefill 与显存/内存预算(本机实测 35B Q4_K_M:约 4.9ms/token,2 万 tokens 上下文的 prefill ≈ 1.6 分钟,13 万窗口 ≈ 10 分钟以上,还会把引擎的内存预算顶满)——预算给小一点,任务跑得完、也更容易看清是哪一步慢。模型窗口/最大输出等**能力声明**请写在 config.customModels.<模型名>(contextWindow/maxOutputTokens),本预设只覆盖本回合参数。需要只读效果时,请自行组合**权限档**(readonly)与**工具白名单**。",
|
|
5
5
|
"contextBudget": 65536,
|
|
6
6
|
"maxOutputTokens": 4096,
|
|
7
7
|
"maxRounds": 4
|