@shgroup/dsh-serenity-hooks 1.56.10 → 1.57.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/README.md +25 -11
- package/dsh.plugin.json +3 -3
- package/lib/agent-idle.d.ts +2 -2
- package/lib/api.d.ts +0 -1
- package/lib/{ccc-DXky9UZu.js → ccc-B0ZGL9lx.js} +30 -13
- package/lib/{ccc-roots-CDW2dO0n.js → ccc-roots-GIJ3A_tw.js} +82 -5
- package/lib/ccc-roots.d.ts +3 -2
- package/lib/ccc.d.ts +23 -10
- package/lib/cheap-worker-ops.d.ts +49 -0
- package/lib/cheap-worker-preset-inherit.d.ts +35 -0
- package/lib/client.js +47 -471
- package/lib/config-ops.d.ts +3 -34
- package/lib/cro-guide.d.ts +1 -1
- package/lib/face-host.d.ts +7 -5
- package/lib/host/access.d.ts +2 -2
- package/lib/index.d.ts +0 -31
- package/lib/index.js +280 -1599
- package/lib/invariant.d.ts +1 -1
- package/lib/invariant.js +1 -1
- package/lib/localstore-ops.d.ts +1 -1
- package/lib/{message-source-CQNfQaTx.js → message-source-B4P3Uw6D.js} +1 -1
- package/lib/output-guard-seam.d.ts +9 -2
- package/lib/ports.d.ts +6 -6
- package/lib/seams/context.d.ts +2 -2
- package/lib/seams/lifecycle.d.ts +3 -3
- package/lib/{settings-section-xHABl8nk.js → settings-section-DQIVsTqE.js} +45 -30
- package/lib/settings-section.d.ts +3 -16
- package/lib/skiff-core.d.ts +6 -5
- package/lib/skiff-debug.d.ts +5 -4
- package/lib/{skiff-role-Det66X16.js → skiff-role-B615L9MV.js} +2 -2
- package/lib/skiff-role.d.ts +2 -2
- package/lib/status.d.ts +2 -2
- package/lib/tools/cheap-worker.d.ts +21 -0
- package/lib/tools/skiff-admin.d.ts +2 -2
- package/lib/unattended-ops.d.ts +6 -4
- package/lib/weixin-bridge.d.ts +9 -2
- package/lib/weixin-output-guard.d.ts +1 -1
- package/lib/{weixin-route-CxCciqQl.js → weixin-route-B9gU1YXz.js} +5 -5
- package/package.json +2 -2
- package/lib/access-CNccNtgf.js +0 -79
- package/lib/acp-core.d.ts +0 -80
- package/lib/acp-http.d.ts +0 -37
- package/lib/handyman-ops.d.ts +0 -97
- package/lib/handyman-preset-inherit.d.ts +0 -35
- package/lib/skiff-registry-BjIX_KD1.js +0 -43
- package/lib/tools/handyman.d.ts +0 -24
package/README.md
CHANGED
|
@@ -78,7 +78,7 @@ dsh plugin --profile web add link:$(pwd)/hooks/dsh-serenity-hooks
|
|
|
78
78
|
| `praxis` | 按需向 AI 注入四套"做事方法":输出自检(eap)、设计对齐(neat)、认知连续性(cce)、本体工程(ontology) | 需要它把话说清楚 / 先对齐再动手 / 动手前先把领域结构显式化时 |
|
|
79
79
|
| `ontology` | 本体工程**引擎**(可执行者):读取 `.ttl` 本体文件,执行结构校验、生成摘要、检查"声明与实况是否一致"、输出语义审查提示词、输出合规清单,并可写入一份新本体模板 | 需要为某个领域建立或校验本体时。⚠️ 与 `praxis ontology` 是**同一领域的两个面**:前者提供**方法文本**(如何建模),后者**实际执行检查**。路径必须在工作区内 |
|
|
80
80
|
| `serenity-skill-creator` | 增强型技能标准(serenity-skill)的创建器:`guide` 编写方法 / `create` 生成骨架(基础链路径由它算)/ `check` 结构检查(三态可分辨:已建模通过 · 普通技能 · 建模了但检查未执行)/ `review` 逐条合规问题清单 / `index` 预览**模型实际会看到**的参考件清单 / `status` 全容器一览 | 新建或改造技能、为技能建本体、需要确认"模型究竟能否看到指定参考件"时 |
|
|
81
|
-
| `
|
|
81
|
+
| `cheap-worker` | 杂工:委派一个低成本模型的助手执行任务,取回其最终文本。一次调用一个串行子代理;`jobs` 可一次扇出多个并行(上限 10)。**不循环、不校验完成码、不写进度文件** | 大批量、重复性的工作(扫描数十个技能、逐用例回归) |
|
|
82
82
|
| `localstore` | 存储密钥与配置(凭据、偏好两个命名空间) | API key、密码集中放一处,不进 git |
|
|
83
83
|
| `container_admin` | 机务舱:管理子角色、管理小工具注册表、查看全部配置 | 定义"子角色"、注册新小工具、修改配置时 |
|
|
84
84
|
| `im-bridge` | 向 IM 联系人发消息(目前为微信):发文本、发文件、查已配置联系人、查通道状态。每次成功发送自动写入工作区的消息记录 | 需要 AI 主动给家人/同事发消息时(见 §6.2)。**条件出现**:仅在工作区配置了微信桥时可见 |
|
|
@@ -100,7 +100,7 @@ dsh plugin --profile web add link:$(pwd)/hooks/dsh-serenity-hooks
|
|
|
100
100
|
| **工作区围墙** | 墙内可用,墙外一律拒绝(路径无法解析) | AI 不应接触工作区之外的内容 |
|
|
101
101
|
| **黑名单 / 治理文件** | 黑名单可配置;`.serenity` 等治理文件禁止 AI 写入 | 防止 AI 破坏自身所在的"地基" |
|
|
102
102
|
| **密钥文件守卫** | `localstore.json` 对**所有**工具拒绝(包括 read/grep/glob) | 密钥值在结构上无法外流 |
|
|
103
|
-
| **对外输出守卫** | 对外向会话(子角色 /
|
|
103
|
+
| **对外输出守卫** | 对外向会话(子角色 / 重建会话)若答出敏感词,会被打回重答,并告知命中的词与修改方向 | 外部使用者不应看到内部机制 |
|
|
104
104
|
| **轨迹提醒** | 持续一段时间后会提醒 AI"把进度写回工作日志",并要求它回一个确认码 | 提醒是机制,不依赖自觉 |
|
|
105
105
|
| **工作日志体积提醒** | 工作日志(SESSION.md)超过 200KB 时提醒 AI"停下重写",并附四条重写原则(保留骨架 / 细节移至附件文件 / 可合并的合并 / 其余自行判断) | 日志持续增厚则无人读得完;重写成本低于堆积。阈值按工作区可调(`sessionKeeper.sessionMdMaxKB`,0 = 关) |
|
|
106
106
|
| **重建前交接** | 重建上下文前,要求 AI 先把"手头做到哪了 / 还差什么 / 下一步做什么"写入**本轨迹目录下的 `REBUILD-TODO.md`**(固定文件名);重建后的 AI 首先读取该文件并继续 | 上下文被清空,但在办的事不能丢。该便签是**只用一次的交界材料**:无格式义务、随时可丢;超过 10 KB 会提醒清理(`SCRATCH PRUNE`,整份删除亦可) |
|
|
@@ -113,10 +113,15 @@ dsh plugin --profile web add link:$(pwd)/hooks/dsh-serenity-hooks
|
|
|
113
113
|
| **网页登录入口** | 3081 | 外部/手机访问完整界面:登录后反向代理到 3080,可配工作区白名单 |
|
|
114
114
|
| **微信主动发送入口** | 3082(只绑 127.0.0.1) | 工作区外的脚本/集成用它给微信发消息(公网不可达,所以不需要密钥)。工作区内的 AI 不走这个端口,直接使用 `im-bridge` 工具 |
|
|
115
115
|
| **子角色调试页** | 3099(只绑 127.0.0.1) | 调试"子角色"时使用,可切换工作区、查看对话轨迹 |
|
|
116
|
-
| **ACP + 对外问答页** | 3100(只绑 127.0.0.1) | 程序化接入(JSON-RPC)+ 给别人用的问答页(key 认证,只返回答案,不返回内部轨迹) |
|
|
117
116
|
| **微信桥** | 无需端口(出站长轮询) | 家人在微信里直接和 AI 说话 |
|
|
118
117
|
|
|
119
|
-
> 3081 / 3099
|
|
118
|
+
> 3081 / 3099 **默认关**(须自行开启);3082 **默认开**(微信桥启用时才有意义)。默认只监听 127.0.0.1 的入口,如需暴露到公网,由使用者自行决定方式(隧道 / 反代 / 端口映射都行),插件不绑定任何特定做法。
|
|
119
|
+
|
|
120
|
+
> 🔴 **已退役:原「ACP + 对外问答页」(3100)**。该面是本插件早期自造的一套私有 HTTP+HTML 协议外壳
|
|
121
|
+
> (无客户端生态),已于 2026-10-15 **整体移除**(连同 `acp-core` / `acp-http` 与相关开关、问答页 key)。
|
|
122
|
+
> **要程序化或从手机/远程接入,走宿主自带的官方 ACP server**:`dsh --profile acp` 起一个纯 stdio、
|
|
123
|
+
> 零认证的 ACP 服务,再由任一现成 ACP 客户端(编辑器如 Zed;手机端如 Agmente、ACP UI)连接。
|
|
124
|
+
> 认证落在**接入层**(隧道 / 反代 / Cloudflare Access),不再由本插件发放 key。
|
|
120
125
|
|
|
121
126
|
### 3.4 自动配置:用 opencode 的模型
|
|
122
127
|
|
|
@@ -268,10 +273,18 @@ my-workspace/ ← 工作区根目录(放一个 .serenity
|
|
|
268
273
|
- 调试页(3099)可以切工作区、看轨迹;回答用 markdown 渲染,思考过程折叠
|
|
269
274
|
- `container_admin role validate` 校验配置,`apply` 才真正生效
|
|
270
275
|
|
|
271
|
-
### 6.4
|
|
276
|
+
### 6.4 对外接入(官方 ACP)
|
|
277
|
+
|
|
278
|
+
本插件**不自造** ACP 面。要程序化或远程使用,用宿主自带的官方 ACP server:
|
|
279
|
+
|
|
280
|
+
| 步 | 做什么 |
|
|
281
|
+
|---|---|
|
|
282
|
+
| 1 | `dsh --profile acp` —— 起官方 ACP 服务(**纯 stdio、零认证**;首次运行自动建 profile) |
|
|
283
|
+
| 2 | 用任一 ACP 客户端连它(编辑器内直接起子进程;手机/远程经桥 + 隧道) |
|
|
284
|
+
| 3 | **认证放在接入层**(隧道 / 反代 / Cloudflare Access)——官方 server 自身不做认证 |
|
|
272
285
|
|
|
273
|
-
|
|
274
|
-
|
|
286
|
+
> **为什么不再自造**:原 3100 面是一个**没有客户端生态**的私有外壳,而官方件已发布并随宿主同版本演进。
|
|
287
|
+
> 详细接法与手机端配置见宁静号 CCC 的接入指南。
|
|
275
288
|
|
|
276
289
|
### 6.5 轨迹与定时唤醒(trajectory)
|
|
277
290
|
|
|
@@ -332,8 +345,8 @@ my-workspace/ ← 工作区根目录(放一个 .serenity
|
|
|
332
345
|
|
|
333
346
|
| 层 | 位置 | 放什么 |
|
|
334
347
|
|---|---|---|
|
|
335
|
-
| DSH 原生设置 | DSH 的 settings.yaml(即设置面板那几项) |
|
|
336
|
-
| 插件全局文件 | `~/.dsh/serenity-hooks.json`(权限 0600) | 网关账号(scrypt + TOTP)、监听地址与端口、工作区白名单、cookie
|
|
348
|
+
| DSH 原生设置 | DSH 的 settings.yaml(即设置面板那几项) | 开关与阈值:网关总开关、重建阈值、子角色开关与调试端口、**CRO 总闸(`croEnabled`,默认为开)**、**无人值守代理回复(`unattendedEnabled`,默认为关)**、**图工具总闸(默认关)** |
|
|
349
|
+
| 插件全局文件 | `~/.dsh/serenity-hooks.json`(权限 0600) | 网关账号(scrypt + TOTP)、监听地址与端口、工作区白名单、cookie 安全开关 |
|
|
337
350
|
| 工作区配置 | `.opencode/serenity.json` | 助手模型白名单、日志阈值、安全模式黑名单、子角色、**轨迹级 skill 供给(`trajectory.skills`)**、微信(账号/路由/开关) |
|
|
338
351
|
| 工作区凭据 | `localstore.json` | 密钥与本地偏好;微信机器人 token 也在这一层 |
|
|
339
352
|
|
|
@@ -386,7 +399,7 @@ pnpm build # 打包(lib/index.js + client.js)
|
|
|
386
399
|
| 跑在 | OpenCode | DeepSeek Harness |
|
|
387
400
|
| 实现 | 独立 | **独立**(不复用源码,但遵循同一套标准) |
|
|
388
401
|
| 系统提示词 | `system.transform` | `systemPrompt.section`,平台无关的部分逐字对齐 |
|
|
389
|
-
| 工具 | msm / container_fs / logbook 等 | container_fs / container_trajectory / dashboard / container_git / msm / praxis / ontology / serenity-skill-creator /
|
|
402
|
+
| 工具 | msm / container_fs / logbook 等 | container_fs / container_trajectory / dashboard / container_git / msm / praxis / ontology / serenity-skill-creator / cheap-worker / localstore / container_admin + 三个条件出现的(`im-bridge` / `acc-diag` / `diagram`) |
|
|
390
403
|
|
|
391
404
|
**同一个工作区可以随时换运行时**:`.serenity` 标记、`.opencode/skills/`、配置、`AGENT_SESSIONS/` 的文件格式都一致;
|
|
392
405
|
差别只在平台层(工具名、注入方式),换过去以后 AI 收到的约束是一样的。
|
|
@@ -408,7 +421,8 @@ pnpm build # 打包(lib/index.js + client.js)
|
|
|
408
421
|
先让 AI 把进度写回 SESSION.md,然后按提示调用 `container_trajectory rebuild`。轨迹会自动接续,不用手动开新会话。
|
|
409
422
|
|
|
410
423
|
**Q:对外问答页会返回内部信息吗?**
|
|
411
|
-
|
|
424
|
+
该面已于 2026-10-15 移除(改用官方 ACP,见 §6.4)。走官方 ACP 时,**认证与暴露范围由接入层决定**——
|
|
425
|
+
官方 server 只跑在 stdio 上、不认识网络,把它接到哪里、谁能连,取决于你怎么架隧道。
|
|
412
426
|
|
|
413
427
|
**Q:微信桥里,AI 的回复是怎么发出去的?**
|
|
414
428
|
默认由插件自动把它的最后一段话转发给用户。如果配了 `autoReplyWithLastMessage: false`,插件就不转了,改由 AI 自己发——所以这时候它如果没发,用户就收不到消息(除非另外开了 `fallbackOnNoSend` 让插件兜底)。
|
package/dsh.plugin.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-serenity-hooks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.57.1",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
|
-
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——14 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/
|
|
5
|
+
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——14 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/cheap-worker/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 轨迹日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/trajectory 唤醒注册表。适配 DSH 0.1.7-rc.1 与 0.2.0-rc.1(双档,deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
|
7
7
|
"dsh": ">=0.1.7-rc.1"
|
|
8
8
|
},
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"container_git",
|
|
15
15
|
"msm",
|
|
16
16
|
"praxis",
|
|
17
|
-
"
|
|
17
|
+
"cheap-worker",
|
|
18
18
|
"localstore",
|
|
19
19
|
"container_admin",
|
|
20
20
|
"im-bridge",
|
package/lib/agent-idle.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* agent-idle.ts — 等待 agent 空闲(含销毁竞速,S142 review F-08)
|
|
3
3
|
*
|
|
4
|
-
* 为什么单独成模块:`askSkiff`(skiff 问答)与 `
|
|
4
|
+
* 为什么单独成模块:`askSkiff`(skiff 问答)与 `cheap-worker`(杂工循环)都要"等这一轮做完",
|
|
5
5
|
* 此前各自复制了一份只监听 `agent/status → idle` 的实现。该实现有一个静默挂死:
|
|
6
6
|
* **agent 先被销毁(会话关闭/进程回收/显式 dispose)就永远不会再发 idle 事件**,
|
|
7
7
|
* 等待方 Promise 永不结算 → 问答/杂工永久卡住(宿主的 disposal 语义:
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* ② `agent/disposed` 且是同一个 agent —— 销毁竞速(宿主 `runtime-types.ts:175`)
|
|
13
13
|
* ③ `session/disposed` 且是同一会话 —— 会话先于 agent 消失(宿主 `core/session/src/index.ts:62`)
|
|
14
14
|
*
|
|
15
|
-
* 无超时:agent 工作多久等多久(
|
|
15
|
+
* 无超时:agent 工作多久等多久(cheap-worker 可永续)。订阅后再查一次 `agent.status`——
|
|
16
16
|
* 宿主 `followup`/`steer` 会同步把 phase 置为 running(`agent.ts:181-201`),
|
|
17
17
|
* 因此此刻读到 idle 只可能是"唤醒已在订阅前收敛",立即结算以避免漏事件挂死。
|
|
18
18
|
*
|
package/lib/api.d.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* 路由:
|
|
5
5
|
* GET /serenity/status ?workspace=<路径> → 状态(root/accVersion/safeModeOn/...)
|
|
6
6
|
* POST /serenity/status { workspace, on } → 切换安全模式(WebUI 专属头)
|
|
7
|
-
* GET /serenity/handymen → handyman 运行状态(v1.24.0:loop → handyman)
|
|
8
7
|
* POST /serenity/image-upload { workspace?, mediaType, data(base64) } → 图片写 _tmp/images_from_user/(client 专属)
|
|
9
8
|
*
|
|
10
9
|
* 经 ctx.webServer(webserver 服务,公开版由 httpServer 改名)注册;客户端与服务器同源,调用无信任围栏问题。
|
|
@@ -77,24 +77,41 @@ function readCccName(root) {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
/**
|
|
80
|
-
* 解析
|
|
81
|
-
*
|
|
80
|
+
* 解析 cheap-worker 配置。
|
|
81
|
+
*
|
|
82
|
+
* 🔴 **键的优先级(2026-10-14,owner 令「配置兼容旧配置 key」)**:
|
|
83
|
+
* ① 新键 `cheap-worker`;② **读不到(键缺失或 models 非有效数组)⇒ 回落旧键 `handyman`**。
|
|
84
|
+
* 「读不到」的判据是**同一套**(models 必须是至少含一个非空字符串的数组)—— 这样"新键存在但写错了"
|
|
85
|
+
* 与"没写新键"行为一致,都不会静默走一个空白名单。
|
|
86
|
+
*
|
|
87
|
+
* ⚠️ `maxRounds`/`maxParallel` 已随 background 模式退场,**不再被本函数读取**(旧配置里留着无害)。
|
|
88
|
+
*
|
|
89
|
+
* @returns 白名单 + 缺省模型;两处都取不到 models 时返回 null(工具应报错要求配置)
|
|
82
90
|
*/
|
|
83
|
-
function
|
|
91
|
+
function readCheapWorkerConfig(root, paths = DEFAULT_SERENITY_CONFIG_PATHS) {
|
|
84
92
|
const cfg = loadSerenityConfig(root, paths);
|
|
85
|
-
const
|
|
86
|
-
if (
|
|
87
|
-
const clean = models.map((m) => m.trim()).filter(Boolean);
|
|
93
|
+
const section = pickModelSection(cfg["cheap-worker"]) ?? pickModelSection(cfg.handyman) ?? null;
|
|
94
|
+
if (section === null) return null;
|
|
95
|
+
const clean = section.models.map((m) => m.trim()).filter(Boolean);
|
|
88
96
|
if (clean.length === 0) return null;
|
|
89
|
-
const defaultModel =
|
|
97
|
+
const defaultModel = section.defaultModel?.trim();
|
|
90
98
|
return {
|
|
91
99
|
models: clean,
|
|
92
|
-
defaultModel: defaultModel !== void 0 && clean.includes(defaultModel) ? defaultModel : clean[0]
|
|
93
|
-
maxRounds: cfg.handyman?.maxRounds ?? 100,
|
|
94
|
-
maxParallel: cfg.handyman?.maxParallel ?? 10
|
|
100
|
+
defaultModel: defaultModel !== void 0 && clean.includes(defaultModel) ? defaultModel : clean[0]
|
|
95
101
|
};
|
|
96
102
|
}
|
|
97
103
|
/**
|
|
104
|
+
* 从一段配置里取出可用的模型白名单段;不满足「models = 至少一个非空字符串的数组」⇒ `null`。
|
|
105
|
+
* 抽成函数是为了让**新键与旧键走同一套判据**(不同判据会让"回落"产生两类行为差异)。
|
|
106
|
+
*/
|
|
107
|
+
function pickModelSection(section) {
|
|
108
|
+
if (section === void 0 || section === null) return null;
|
|
109
|
+
const models = section.models;
|
|
110
|
+
if (!Array.isArray(models) || models.length === 0) return null;
|
|
111
|
+
if (models.every((m) => typeof m !== "string" || m.trim() === "")) return null;
|
|
112
|
+
return section;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
98
115
|
* ACC 依赖的 CCC 配置路径(S134 修正:兼容历史——历史在 .opencode,规范位置 = .opencode;
|
|
99
116
|
* .dsh 仅作 dsh 运行时回退,不优先)。
|
|
100
117
|
*/
|
|
@@ -108,7 +125,7 @@ function readUtf8(path) {
|
|
|
108
125
|
}
|
|
109
126
|
/**
|
|
110
127
|
* 已告警过的损坏配置路径(进程级去重:同一坏文件不刷屏,但绝不静默)。
|
|
111
|
-
* S142 review F-07:此前损坏 → 静默返回 `{}`——安全模式黑名单/
|
|
128
|
+
* S142 review F-07:此前损坏 → 静默返回 `{}`——安全模式黑名单/cheap-worker 白名单/skiff 角色
|
|
112
129
|
* 全部**无声失效**(用户以为配了,实际没配)。守卫的输入失败必须响亮。
|
|
113
130
|
*/
|
|
114
131
|
const warnedBrokenConfigs = /* @__PURE__ */ new Set();
|
|
@@ -132,7 +149,7 @@ function loadSerenityConfig(root, paths = DEFAULT_SERENITY_CONFIG_PATHS) {
|
|
|
132
149
|
} catch (err) {
|
|
133
150
|
if (!warnedBrokenConfigs.has(p)) {
|
|
134
151
|
warnedBrokenConfigs.add(p);
|
|
135
|
-
console.warn(`[serenity-hooks] ✗ CCC 配置解析失败,已按空配置继续(该 CCC 的安全模式黑名单/
|
|
152
|
+
console.warn(`[serenity-hooks] ✗ CCC 配置解析失败,已按空配置继续(该 CCC 的安全模式黑名单/cheap-worker 白名单/skiff 角色等全部失效,请修 JSON): ${p} — ${String(err?.message ?? err)}`);
|
|
136
153
|
}
|
|
137
154
|
return {};
|
|
138
155
|
}
|
|
@@ -239,4 +256,4 @@ function matchBlacklist(relPath, rules) {
|
|
|
239
256
|
return null;
|
|
240
257
|
}
|
|
241
258
|
//#endregion
|
|
242
|
-
export { resolveInside as _, findSerenityRoot as a, matchBlacklist as c, readCccName as d,
|
|
259
|
+
export { resolveInside as _, findSerenityRoot as a, matchBlacklist as c, readCccName as d, readCheapWorkerConfig as f, readUtf8 as g, readTrajectorySkills as h, findGitRoot as i, pathInside as l, readSafeModeHiddenTools as m, SAFE_MODE_MARKER as n, isSafeModeOn as o, readExclusiveTools as p, classifyPath as r, loadSerenityConfig as s, DEFAULT_SERENITY_CONFIG_PATHS as t, readBlacklist as u };
|
|
@@ -1,7 +1,84 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
|
|
2
|
-
import { a as
|
|
3
|
-
import { a as findSerenityRoot } from "./ccc-DXky9UZu.js";
|
|
2
|
+
import { a as findSerenityRoot } from "./ccc-B0ZGL9lx.js";
|
|
4
3
|
import { basename } from "node:path";
|
|
4
|
+
//#region src/host/access.ts
|
|
5
|
+
/**
|
|
6
|
+
* host/access.ts — 宿主访问收口(S142 review F-06)
|
|
7
|
+
*
|
|
8
|
+
* 为什么存在:dsp 此前在 30+ 个文件里各自用 `(ctx as unknown as {…})` 断言读取宿主
|
|
9
|
+
* 服务——契约表达分散、失败模式各异(多数静默 undefined)。本模块是**唯一**读取宿主
|
|
10
|
+
* 的入口:所有 `ctx.get` / `ctx.<service>` 的形状断言集中在此,调用点只拿类型化结果。
|
|
11
|
+
*
|
|
12
|
+
* 约定:
|
|
13
|
+
* - 只读、无副作用;服务缺失一律返回 `undefined`(调用方决定降级策略),**不抛错**
|
|
14
|
+
* (宿主对插件 apply 抛错 = 整个 dsh 启动失败,访问层不能成为单点)。
|
|
15
|
+
* - 形状以 `AI_LAB/dsh-harness-public` @ 0.1.2-rc.1 为准;成员缺失由
|
|
16
|
+
* `host/contract.ts` 的探针在装载时与 `dashboard health` 中报告。
|
|
17
|
+
* - 迁移是渐进的:新代码必须走本模块;旧调用点逐轮收敛(F-06 轮次记录见 CHANGELOG)。
|
|
18
|
+
*/
|
|
19
|
+
/** 通用读取:`ctx.get(name)`(含异常吞掉——服务 getter 抛错视为不可用) */
|
|
20
|
+
function hostService(ctx, name) {
|
|
21
|
+
const c = ctx;
|
|
22
|
+
if (typeof c?.get !== "function") return void 0;
|
|
23
|
+
try {
|
|
24
|
+
return c.get(name);
|
|
25
|
+
} catch {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 直接属性读取(injected 服务:`ctx.<name>`),属性缺失**或读取抛错**时回落 `ctx.get`。
|
|
31
|
+
*
|
|
32
|
+
* v1.31.4 修复(R↓,实证 v1.31.3 真机首测):cordis 的 Context 是 Proxy,
|
|
33
|
+
* `ReflectService.handler.get`(`vendor/cordis/src/reflect.ts`)对**未经 `inject` 声明**
|
|
34
|
+
* 的服务名会沿 fiber 链查找,找不到时**抛错**而非返回 undefined:
|
|
35
|
+
*
|
|
36
|
+
* cannot get property "<name>" without inject
|
|
37
|
+
*
|
|
38
|
+
* 于是"先直接属性读、失败回落 ctx.get"的写法在**真实 cordis** 下永远走不到回落分支——
|
|
39
|
+
* 异常直接逃逸(`hostService` 的 try/catch 被绕过)。v1.31.3 的 `hostSubagents`
|
|
40
|
+
* 正是这样炸的:`subagents` 是 lazy 服务(不在插件 `inject` 列表内)。
|
|
41
|
+
* 现有 fake ctx 单测(普通对象无 getter)复现不了 → 真 cordis 用例见
|
|
42
|
+
* `tests/host/cordis-access.test.ts`。
|
|
43
|
+
*
|
|
44
|
+
* 为什么吞掉异常而不是让它冒泡:本模块的契约是"服务缺失一律返回 undefined,**不抛错**"
|
|
45
|
+
* (宿主对插件 apply 抛错 = 整个 dsh 启动失败)。读取失败 = 服务不可用,等价于缺失。
|
|
46
|
+
*/
|
|
47
|
+
function hostInjected(ctx, name) {
|
|
48
|
+
const c = ctx;
|
|
49
|
+
try {
|
|
50
|
+
const direct = c?.[name];
|
|
51
|
+
if (direct !== void 0) return direct;
|
|
52
|
+
} catch {}
|
|
53
|
+
return hostService(ctx, name);
|
|
54
|
+
}
|
|
55
|
+
/** `ctx.sessions`(injected) */
|
|
56
|
+
function hostSessions(ctx) {
|
|
57
|
+
return hostInjected(ctx, "sessions");
|
|
58
|
+
}
|
|
59
|
+
/** `ctx.agents`(injected) */
|
|
60
|
+
function hostAgents(ctx) {
|
|
61
|
+
return hostInjected(ctx, "agents");
|
|
62
|
+
}
|
|
63
|
+
/** `ctx.webServer`(injected) */
|
|
64
|
+
function hostWebServer(ctx) {
|
|
65
|
+
return hostInjected(ctx, "webServer");
|
|
66
|
+
}
|
|
67
|
+
/** `ctx.settings`(injected;提供 settings 面板装配通道) */
|
|
68
|
+
function hostSettings(ctx) {
|
|
69
|
+
return hostInjected(ctx, "settings");
|
|
70
|
+
}
|
|
71
|
+
/** `ctx.web`(injected;v1.30.12 web_fetch provider 注册通道) */
|
|
72
|
+
function hostWeb(ctx) {
|
|
73
|
+
return hostInjected(ctx, "web");
|
|
74
|
+
}
|
|
75
|
+
function hostSubagents(ctx) {
|
|
76
|
+
return hostInjected(ctx, "subagents");
|
|
77
|
+
}
|
|
78
|
+
function hostLlm(ctx) {
|
|
79
|
+
return hostInjected(ctx, "llm");
|
|
80
|
+
}
|
|
81
|
+
//#endregion
|
|
5
82
|
//#region src/ccc-roots.ts
|
|
6
83
|
/**
|
|
7
84
|
* ccc-roots.ts — CCC 根解析的**唯一判断层**(L1 单根解析 + L2 全量枚举)
|
|
@@ -47,7 +124,7 @@ var ccc_roots_exports = /* @__PURE__ */ __exportAll({
|
|
|
47
124
|
*
|
|
48
125
|
* ⚠️ 无 `exec.agent` 时回落进程 cwd —— "用服务启动目录冒充会话目录"是**既有语义**,
|
|
49
126
|
* 不是本模块的选择(改它会动到 9 个工具的根解析行为)。已知副作用与规避见
|
|
50
|
-
* `tools/
|
|
127
|
+
* `tools/cheap-worker.ts` 的「调用形态检查前移」补偿(`?? process.cwd()` 会把真因
|
|
51
128
|
* "exec.agent 不存在"盖成 `No CCC found`)。
|
|
52
129
|
*/
|
|
53
130
|
function agentCwdFor(execOrAgent) {
|
|
@@ -150,7 +227,7 @@ async function listCccs(ctx, opts = {}) {
|
|
|
150
227
|
if (typeof defaultRoot === "string" && defaultRoot !== "" && !c.roots.includes(defaultRoot)) c.roots.unshift(defaultRoot);
|
|
151
228
|
let rolesOf = null;
|
|
152
229
|
if (opts.withRoles === true) {
|
|
153
|
-
const { readSkiffRoles } = await import("./skiff-role-
|
|
230
|
+
const { readSkiffRoles } = await import("./skiff-role-B615L9MV.js").then((n) => n.u);
|
|
154
231
|
rolesOf = (root) => [...readSkiffRoles(root).keys()];
|
|
155
232
|
}
|
|
156
233
|
return c.roots.map((root) => ({
|
|
@@ -160,4 +237,4 @@ async function listCccs(ctx, opts = {}) {
|
|
|
160
237
|
}));
|
|
161
238
|
}
|
|
162
239
|
//#endregion
|
|
163
|
-
export { ccc_roots_exports as a, cccRootForExec as i, agentCwdFor as n, listCccs as o, cccRootForCwd as r, NO_CCC_FROM_AGENT_CWD as t };
|
|
240
|
+
export { ccc_roots_exports as a, hostInjected as c, hostSessions as d, hostSettings as f, hostWebServer as h, cccRootForExec as i, hostLlm as l, hostWeb as m, agentCwdFor as n, listCccs as o, hostSubagents as p, cccRootForCwd as r, hostAgents as s, NO_CCC_FROM_AGENT_CWD as t, hostService as u };
|
package/lib/ccc-roots.d.ts
CHANGED
|
@@ -53,7 +53,7 @@ export interface ExecOrAgent {
|
|
|
53
53
|
*
|
|
54
54
|
* ⚠️ 无 `exec.agent` 时回落进程 cwd —— "用服务启动目录冒充会话目录"是**既有语义**,
|
|
55
55
|
* 不是本模块的选择(改它会动到 9 个工具的根解析行为)。已知副作用与规避见
|
|
56
|
-
* `tools/
|
|
56
|
+
* `tools/cheap-worker.ts` 的「调用形态检查前移」补偿(`?? process.cwd()` 会把真因
|
|
57
57
|
* "exec.agent 不存在"盖成 `No CCC found`)。
|
|
58
58
|
*/
|
|
59
59
|
export declare function agentCwdFor(execOrAgent: ExecOrAgent): string;
|
|
@@ -75,7 +75,8 @@ export declare function cccRootForExec(execOrAgent: ExecOrAgent): string | null;
|
|
|
75
75
|
* **文案逐字不变**(外在行为不变)。
|
|
76
76
|
*/
|
|
77
77
|
export declare const NO_CCC_FROM_AGENT_CWD = "No CCC found: no .serenity file from agent cwd";
|
|
78
|
-
/** 候选 CCC 条目(调试页 CCC 切换器 / 微信桥 /
|
|
78
|
+
/** 候选 CCC 条目(调试页 CCC 切换器 / 微信桥 / `/serenity/cccs` 共用数据形状)
|
|
79
|
+
* ⚠️ 2026-10-15:原同批还有「ACP 问答页」,其面已退役 ⇒ 消费方少一个(形状不变)。 */
|
|
79
80
|
export interface CccEntry {
|
|
80
81
|
/** CCC 根(绝对路径) */
|
|
81
82
|
root: string;
|
package/lib/ccc.d.ts
CHANGED
|
@@ -32,15 +32,22 @@ export declare function resolveInside(root: string, p: string): string;
|
|
|
32
32
|
*/
|
|
33
33
|
export declare function readCccName(root: string): string | null;
|
|
34
34
|
interface SerenityConfig {
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
/** 可用模型白名单(provider/model 列表)——
|
|
35
|
+
/** cheap-worker(杂工)配置:模型白名单(v1.24.0 取代 loop;2026-10-14 取代 handyman) */
|
|
36
|
+
'cheap-worker'?: {
|
|
37
|
+
/** 可用模型白名单(provider/model 列表)——cheap-worker 只能使用其中模型(用户拍板:CCC 配置控制) */
|
|
38
38
|
models?: string[];
|
|
39
39
|
/** 缺省模型(必须 ∈ models) */
|
|
40
40
|
defaultModel?: string;
|
|
41
|
-
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* 🔴 **旧键(历史名)**:2026-10-14 起本插件读 `cheap-worker`,**读不到时回落到这里**
|
|
44
|
+
* (owner 令「配置兼容旧配置 key」)。仍可含 `maxRounds`/`maxParallel` —— 那两个键已随
|
|
45
|
+
* background 模式退场,**不再被读取**,但**留在文件里不会报错**(宽松解析,见 loadSerenityConfig)。
|
|
46
|
+
*/
|
|
47
|
+
handyman?: {
|
|
48
|
+
models?: string[];
|
|
49
|
+
defaultModel?: string;
|
|
42
50
|
maxRounds?: number;
|
|
43
|
-
/** jobs 编排并行上限(缺省 10——便宜模型便宜) */
|
|
44
51
|
maxParallel?: number;
|
|
45
52
|
};
|
|
46
53
|
sessionKeeper?: {
|
|
@@ -286,14 +293,20 @@ export interface SkiffRoleConfig {
|
|
|
286
293
|
systemPromptFile?: string;
|
|
287
294
|
}
|
|
288
295
|
/**
|
|
289
|
-
* 解析
|
|
290
|
-
*
|
|
296
|
+
* 解析 cheap-worker 配置。
|
|
297
|
+
*
|
|
298
|
+
* 🔴 **键的优先级(2026-10-14,owner 令「配置兼容旧配置 key」)**:
|
|
299
|
+
* ① 新键 `cheap-worker`;② **读不到(键缺失或 models 非有效数组)⇒ 回落旧键 `handyman`**。
|
|
300
|
+
* 「读不到」的判据是**同一套**(models 必须是至少含一个非空字符串的数组)—— 这样"新键存在但写错了"
|
|
301
|
+
* 与"没写新键"行为一致,都不会静默走一个空白名单。
|
|
302
|
+
*
|
|
303
|
+
* ⚠️ `maxRounds`/`maxParallel` 已随 background 模式退场,**不再被本函数读取**(旧配置里留着无害)。
|
|
304
|
+
*
|
|
305
|
+
* @returns 白名单 + 缺省模型;两处都取不到 models 时返回 null(工具应报错要求配置)
|
|
291
306
|
*/
|
|
292
|
-
export declare function
|
|
307
|
+
export declare function readCheapWorkerConfig(root: string, paths?: string[]): {
|
|
293
308
|
models: string[];
|
|
294
309
|
defaultModel: string;
|
|
295
|
-
maxRounds: number;
|
|
296
|
-
maxParallel: number;
|
|
297
310
|
} | null;
|
|
298
311
|
/**
|
|
299
312
|
* ACC 依赖的 CCC 配置路径(S134 修正:兼容历史——历史在 .opencode,规范位置 = .opencode;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cheap-worker-ops.ts — cheap-worker(杂工)纯逻辑层(零 DSH 依赖,可独立单测)
|
|
3
|
+
*
|
|
4
|
+
* 🆕 2026-10-14(owner 令「删除后台运行能力」):**进度文件 / stop token / 轮次循环**整族已退场 ——
|
|
5
|
+
* 它们**只**服务于 background 模式。本模块现存 = 前台委派真正需要的三件:
|
|
6
|
+
* 模型串解析 / 白名单校验 / provider 可用性判读(+ 使用指引文本)。
|
|
7
|
+
*/
|
|
8
|
+
/** 解析 model 字符串(provider/model)→ {provider, model};无 / 视为 model-only */
|
|
9
|
+
export declare function splitModel(model: string): {
|
|
10
|
+
provider: string | undefined;
|
|
11
|
+
model: string;
|
|
12
|
+
};
|
|
13
|
+
/** 校验模型在白名单内;不在 → 抛错(用户拍板:只能使用 CCC 配置的模型) */
|
|
14
|
+
export declare function requireWhitelistedModel(model: string, models: string[]): void;
|
|
15
|
+
/**
|
|
16
|
+
* providerAvailabilityError — 判定「**本机有没有该 provider 的 adapter**」,并产出**可执行**的错误文本。
|
|
17
|
+
* 返回 `null` = 全部可用(调用方照常继续)。
|
|
18
|
+
*
|
|
19
|
+
* 🔴 为什么需要它(S142 2026-09-25,owner 在 **Mac** 上实测):`cheap-worker` 的模型白名单写在
|
|
20
|
+
* **CCC**(`.opencode/serenity.json`,**随 git 走**),而 provider adapter 由**每台机器的宿主**
|
|
21
|
+
* 注册(profile 配置 / settings 命名空间)⇒ 同一份白名单在一台机器可用、在另一台必失败。
|
|
22
|
+
* 实测症状:宿主抛 `no adapter registered for provider "<p>"`(`dsh-llm`,code `NO_ADAPTER`),
|
|
23
|
+
* 而**前台路径的 `diagnostic` 是空的** ⇒ 调用方(LLM)拿到 `stopReason:"error"` 却**不知道为什么**,
|
|
24
|
+
* 也就无法修正自己的配置 —— 本条把「沉默的失败」变成「可执行的错误」。
|
|
25
|
+
*
|
|
26
|
+
* 数据来源(宿主 `LlmRuntime`):`listProviders()` = **有 adapter 的路由**;
|
|
27
|
+
* `listConfigurableProviders()` = **已声明但未必激活**的路由(含激活用的 settings 命名空间)。
|
|
28
|
+
*
|
|
29
|
+
* 判据边界:`model` 串里**没有 `/`** 时取不到 provider(沿用 agent 默认路由)⇒ **不判定**(跳过)。
|
|
30
|
+
*/
|
|
31
|
+
export declare function providerAvailabilityError(models: readonly string[], facts: {
|
|
32
|
+
registered: readonly {
|
|
33
|
+
id: string;
|
|
34
|
+
name?: string;
|
|
35
|
+
}[];
|
|
36
|
+
declared?: readonly {
|
|
37
|
+
provider: string;
|
|
38
|
+
displayName?: string;
|
|
39
|
+
settingsNs?: string;
|
|
40
|
+
}[];
|
|
41
|
+
configPath?: string;
|
|
42
|
+
}): string | null;
|
|
43
|
+
/**
|
|
44
|
+
* cheap-worker 规模化使用指引(guide 子命令输出)。
|
|
45
|
+
*
|
|
46
|
+
* 🆕 2026-10-14:**双模式段已整段退场**(owner 令「删除后台运行能力」)。本指引只描述现行机制:
|
|
47
|
+
* 前台委派(单任务)/前台并行扇出(jobs)/白名单与 provider 预检。
|
|
48
|
+
*/
|
|
49
|
+
export declare const CHEAP_WORKER_GUIDE = "# cheap-worker \u2014 Scale-Up Usage Guide (guide)\n\n## What it is\nOne delegation primitive: **foreground spawn**. The host starts child agent(s) through its delegation\nservice, awaits them, and returns their final text. There is no loop, no completion code, no progress\nfile, and no unattended/background run.\n\n| | single | parallel (jobs) |\n|---|---|---|\n| Call | cheap-worker(task, [label]) | cheap-worker(jobs=[{task, label?}, ...]) |\n| Behaviour | one child runs the task once | all children start at once, results keep your order |\n| Cap | \u2014 | **10 (fixed, hardcoded)** |\n| Model | CCC config (single source) | same |\n\n## \u26A0\uFE0F Before using: load eap and design the plan\nBefore calling cheap-worker, load eap (acc-eap skill) and design the \"scale-up cheap-worker plan\" based on the EAP framework.\n\n### 1. Task decomposition (E\u2191 Explicit)\n- Split large tasks into explicit subtasks: each subtask defines goal / input / boundaries (what to do, what not to do) / acceptance criteria\n- Make dependencies explicit: dependent tasks run serially, independent ones can run in parallel via `jobs`\n\n### 2. Prompt design (cheap-worker's task parameter)\n- task must be detailed, fixed, and EAP-compliant: clear goal, drawn boundaries, decidable acceptance criteria\n- the child does NOT share your conversation \u2014 restate everything it needs in task\n- Anti-example \"handle this file\" \u2014 ambiguous; good example \"read <path>, extract all rows of the\u300C\u5173\u952E\u51B3\u7B56\u300Dtable,\n output a JSON array (fields id/conclusion/evidence), do not modify the original file\"\n- Reading/curating or text-writing work (extracting from files, summarizing, writing docs, generating text, etc.):\n the cheap-worker-internal agent is also required to load eap and organize output per the EAP standard\n\n### 3. Model (CCC-configured, not selectable per call)\n- The model is read from .opencode/serenity.json \"cheap-worker.models\" \u2014 **the caller cannot pass one**\n (there is no \"model\" parameter). \"cheap-worker.defaultModel\" names which entry is used; it falls back to models[0].\n- The CCC is expected to point this whitelist at LOW-COST models: cheap-worker is the bulk-execution channel\n- A child's own recursive subagents inherit the child's model automatically (DSH native)\n\n### 3b. \uD83D\uDD34 Provider availability (per-machine \u2014 the whitelist is NOT enough)\n- The whitelist lives in the **CCC** (\"serenity.json\", it **travels with the repository**), but provider\n **adapters are registered per machine by the host** (profile config / settings namespace). An entry that\n works on one machine can fail on another with: \"no adapter registered for provider <p>\".\n- Before spawning, cheap-worker verifies the provider of the resolved model against the adapters registered\n **on this machine**; if it is missing it reports the requested model, where it is configured, **the\n providers that ARE available here**, any declared-but-dormant route (with its settings namespace), and the\n exact fix \u2014 delivered in the result's \"diagnostic\" field (never an opaque failure, never a created child).\n- \u21D2 If you see \"has no adapter registered on this machine\": edit \".opencode/serenity.json\" \"cheap-worker.models\"\n (and \"cheap-worker.defaultModel\") to a provider listed as available, or activate/register the provider on this\n machine. **Do not retry the same call unchanged** \u2014 it fails identically.\n\n### 4. Parallel strategy\n- Independent subtasks: cheap-worker(jobs=[{task,label?},...]) \u21D2 fan-out, **cap 10**, results come back\n **in the order you passed them** (label is only a display name).\n- For programmable pipeline/phase orchestration at scale, use the platform's workflow tool instead.\n\n## Completion criteria\n- The child's run settles; done=true only when stopReason=\"completed\" \u2014 otherwise read \"diagnostic\"\n (and \"output\" for whatever partial text was produced).\n";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cheap-worker-preset-inherit.ts — cheap-worker worker 的 preset 继承 + 工具面收窄(纯函数,可单测)
|
|
3
|
+
*
|
|
4
|
+
* v1.24.0:loop → cheap-worker 重命名。对齐 subagent 先例(applyChildComposition →
|
|
5
|
+
* agentPresets.composeFrom):cheap-worker worker 在创建窗口内 join 发起方 agent 的 standing
|
|
6
|
+
* preset 组合,从而获得 preset 层工具(read/write/edit 等)。
|
|
7
|
+
*
|
|
8
|
+
* **工具面收窄(用户拍板)**:worker 内部**不含 cheap-worker 工具本身**——递归编排归主
|
|
9
|
+
* agent,worker 内部只走 subagent(模型继承 worker,同样低能)。实现:setup 钩子
|
|
10
|
+
* composeFrom 后对子 scope `tools.restrict({ deny: ['cheap-worker'] })`(同 scope 注册的
|
|
11
|
+
* 规则,最近 scope 胜出——worker 看不到 cheap-worker,主 agent 不受影响)。
|
|
12
|
+
*
|
|
13
|
+
* agentPresets 是可选服务(ctx.get 读取):
|
|
14
|
+
* - 无该服务 / 父未 join preset → 返回空(worker 落全局工具层 + deny cheap-worker);
|
|
15
|
+
* - 有且父已 join → 返回 preset id(写入 session meta 供重建)+ setup 钩子
|
|
16
|
+
* (在 agent 未发布前执行 composeFrom + restrict,失败由创建事务回滚)。
|
|
17
|
+
*
|
|
18
|
+
* 仅依赖 cordis 的 Context 类型(type-only,运行时擦除)——保持可被 vitest
|
|
19
|
+
* 直接加载(与 ccc.ts / cheap-worker-ops.ts 同级的纯模块约定)。
|
|
20
|
+
*/
|
|
21
|
+
import type { Context } from 'cordis';
|
|
22
|
+
/** 从父 agent ctx 解析 preset 继承的创建期组合。 */
|
|
23
|
+
interface CheapWorkerPresetInheritance {
|
|
24
|
+
/** 父 agent 的 preset id(写入子 session meta.agentPreset,供持久化重建);无则不写。 */
|
|
25
|
+
readonly agentPreset?: string;
|
|
26
|
+
/** 创建 setup 钩子:子 scope join 父的 standing preset + deny cheap-worker 工具;无 preset 继承时仅 deny。 */
|
|
27
|
+
readonly setup?: (childCtx: Context) => void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 解析 cheap-worker worker 从父 agent 继承的 preset,并组装创建 setup 钩子。
|
|
31
|
+
* @param parentCtx - 发起 cheap-worker 的 agent 的 scope ctx;无(headless/非 agent 上下文)时为 undefined。
|
|
32
|
+
* @returns 继承结果:meta 用的 agentPreset 与创建 setup 钩子。
|
|
33
|
+
*/
|
|
34
|
+
export declare function cheapWorkerPresetInheritance(parentCtx: Context | undefined): CheapWorkerPresetInheritance;
|
|
35
|
+
export {};
|