@shgroup/dsh-serenity-hooks 1.72.0 → 1.74.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/README.md +12 -11
- package/dsh.plugin.json +2 -2
- package/lib/accounts-BHQbakUh.js +33 -0
- package/lib/{ccc-Dkoa2oW3.js → ccc-CyYJL4F2.js} +9 -9
- package/lib/{ccc-roots-jZYR2GVE.js → ccc-roots-B2t_aM8L.js} +5 -5
- package/lib/client.js +165 -58
- package/lib/{wake/cro.d.ts → cro/core.d.ts} +3 -3
- package/lib/{wake/cro-guide.d.ts → cro/guide.d.ts} +3 -3
- package/lib/{wake/cro-log.d.ts → cro/log.d.ts} +2 -2
- package/lib/{wake/cro-turns.d.ts → cro/turns.d.ts} +2 -2
- package/lib/guard/seam.d.ts +4 -4
- package/lib/host/effect.d.ts +1 -1
- package/lib/{ilink-DEpmE3yi.js → ilink-BMk2w2KY.js} +1 -1
- package/lib/im/bridge.d.ts +36 -65
- package/lib/im/endpoint.d.ts +3 -3
- package/lib/im/feishu-account.d.ts +92 -0
- package/lib/im/guard.d.ts +1 -1
- package/lib/im/hook.d.ts +1 -1
- package/lib/im/inbound-event.d.ts +162 -0
- package/lib/im/route.d.ts +38 -3
- package/lib/index.d.ts +5 -27
- package/lib/index.js +1089 -1208
- package/lib/kernel/ccc-roots.d.ts +4 -4
- package/lib/kernel/ccc.d.ts +19 -19
- package/lib/kernel/ports.d.ts +3 -5
- package/lib/lib-TxscFKeo.js +119355 -0
- package/lib/{message-source-kVoNK0C5.js → message-source-DCpoRHP3.js} +2 -2
- package/lib/patches/opencode-provider.d.ts +1 -1
- package/lib/{profile-DyMJ_bfr.js → profile-BVt84mbi.js} +68 -65
- package/lib/rolldown-runtime-B4iAMlE-.js +35 -0
- package/lib/{route-f7JlinIt.js → route-COOFLTpU.js} +61 -8
- package/lib/seams/guards.d.ts +14 -14
- package/lib/seams/keeper.d.ts +1 -1
- package/lib/seams/lifecycle.d.ts +2 -2
- package/lib/{settings-lt1i3OZv.js → settings-D8hlqxua.js} +49 -84
- package/lib/skills/resource-index.d.ts +1 -1
- package/lib/surface/faces.d.ts +1 -1
- package/lib/surface/http.d.ts +1 -1
- package/lib/surface/settings.d.ts +7 -13
- package/lib/surface/text.d.ts +72 -0
- package/lib/surface/usage.d.ts +2 -2
- package/lib/tools/config-docs.d.ts +53 -0
- package/lib/tools/container-admin.d.ts +19 -12
- package/lib/tools/msm/service.d.ts +7 -0
- package/lib/tools/trajectory-constraint-admin.d.ts +30 -0
- package/lib/{role/worker/idle.d.ts → trajectory/carrier.d.ts} +12 -2
- package/lib/trajectory/core.d.ts +1 -1
- package/lib/{role/worker → trajectory/delegate}/core.d.ts +7 -1
- package/lib/{role/worker → trajectory/delegate}/preset.d.ts +9 -2
- package/lib/trajectory/policy/profile.d.ts +122 -0
- package/lib/trajectory/policy/rules.d.ts +98 -0
- package/lib/{role/skiff/registry.d.ts → trajectory/policy/window.d.ts} +19 -13
- package/lib/trajectory/prompt.d.ts +12 -12
- package/lib/trajectory/rebuild.d.ts +2 -2
- package/lib/{role/skiff/core.d.ts → trajectory/session.d.ts} +58 -49
- package/package.json +3 -2
- package/lib/role/skiff/config.d.ts +0 -79
- package/lib/role/skiff/debug.d.ts +0 -88
- package/lib/role/skiff/profile.d.ts +0 -115
- package/lib/rolldown-runtime-8H4AJuhK.js +0 -14
- package/lib/tools/skiff-admin.d.ts +0 -30
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { f as hostSettings } from "./ccc-roots-
|
|
2
|
-
import { _ as resolveInside, g as readUtf8 } from "./ccc-
|
|
1
|
+
import { f as hostSettings } from "./ccc-roots-B2t_aM8L.js";
|
|
2
|
+
import { _ as resolveInside, g as readUtf8 } from "./ccc-CyYJL4F2.js";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
@@ -48,28 +48,34 @@ const ACC_VERSION = (() => {
|
|
|
48
48
|
}
|
|
49
49
|
})();
|
|
50
50
|
//#endregion
|
|
51
|
-
//#region src/
|
|
51
|
+
//#region src/trajectory/policy/rules.ts
|
|
52
52
|
/**
|
|
53
|
-
*
|
|
53
|
+
* trajectory/policy/rules.ts — 轨迹约束面的**纯逻辑助手**(零 DSH 依赖,可独立单测)
|
|
54
54
|
*
|
|
55
55
|
* ## 2026-10-19 重做后的职责边界(R↓,别再混起来)
|
|
56
56
|
*
|
|
57
57
|
* | 模块 | 管什么 |
|
|
58
58
|
* |---|---|
|
|
59
|
-
* | `./profile.ts` | **判据 + 读盘**("这是不是
|
|
60
|
-
* | `./
|
|
61
|
-
* |
|
|
59
|
+
* | `./profile.ts` | **判据 + 读盘**("这是不是 轨迹约束"、"约束面是什么") |
|
|
60
|
+
* | `./rules.ts`(本文件) | **从约束面派生出的纯函数**(白名单集合、提示词读取器、基础提示词文本) |
|
|
61
|
+
* | `../session-create.ts` | 会话创建/复用、提问、守门查询 |
|
|
62
62
|
*
|
|
63
|
-
* ⇒ 本文件**不再读 `serenity.json
|
|
64
|
-
* 它只接收一个已解析好的 `
|
|
63
|
+
* ⇒ 本文件**不再读 `serenity.json`**:`轨迹约束.roles` 整段已退役(owner 2026-10-19 重做)。
|
|
64
|
+
* 它只接收一个已解析好的 `TrajectoryConstraint`,因此**不涉及任何 IO**(除提示词文件,那是刻意懒读的)。
|
|
65
|
+
*
|
|
66
|
+
* ## S12(2026-10-19,轨迹中心重构)
|
|
67
|
+
*
|
|
68
|
+
* 原名 `role/轨迹约束/config.ts`。改名理由(框架 §6.3「角色不是一个概念,是一段历史」):
|
|
69
|
+
* 它派生的是**某条轨迹的约束面**,与"配置读取"无关(本文件零配置读取,见上一段)
|
|
70
|
+
* ⇒ `config` 这个名字描述的是**它曾经的样子**,`rules` 描述它**现在做的事**。
|
|
65
71
|
*/
|
|
66
72
|
/** 白名单推导 ────────────────────────────────────────────────────────────── */
|
|
67
73
|
/** 提示词来源提示串(`apply` 回执与面板共用;避免两处措辞漂) */
|
|
68
|
-
const
|
|
74
|
+
const TRAJECTORY_CONSTRAINT_HINT = "systemPromptFile hot-reloads by mtime; the rest of trajectory-constraint.json is re-read every turn";
|
|
69
75
|
/**
|
|
70
|
-
* 该
|
|
76
|
+
* 该 轨迹约束会话**可见**的工具面(tools ∪ `msm`)。
|
|
71
77
|
*
|
|
72
|
-
* 🔴 `msm` 为什么自动加入:`msms` 非空意味着这个
|
|
78
|
+
* 🔴 `msm` 为什么自动加入:`msms` 非空意味着这个 轨迹约束 **有 MSM 通道**,
|
|
73
79
|
* 而 MSM 的唯一合法调用入口是 `msm` 工具(单入口纪律)——不给它 `msm` 就等于
|
|
74
80
|
* 声明了一堆调不动的能力。⚠️ 这是**并集**,不是覆盖:`tools` 里显式写的照旧生效。
|
|
75
81
|
*/
|
|
@@ -79,12 +85,12 @@ function profileToolWhitelist(profile) {
|
|
|
79
85
|
if ((profile?.msms?.length ?? 0) > 0) out.add("msm");
|
|
80
86
|
return out;
|
|
81
87
|
}
|
|
82
|
-
/** 该
|
|
88
|
+
/** 该 轨迹约束会话可 exec 的 MSM 白名单(`msm` 工具内部再过滤;独立于工具白名单) */
|
|
83
89
|
function profileMsmWhitelist(profile) {
|
|
84
90
|
return new Set(profile?.msms ?? []);
|
|
85
91
|
}
|
|
86
|
-
/** 轨迹纪律参与项(`profile` 缺省已在 `
|
|
87
|
-
function
|
|
92
|
+
/** 轨迹纪律参与项(`profile` 缺省已在 `readTrajectoryConstraintAt` 归一为全 true) */
|
|
93
|
+
function constraintCognitiveTrajectory(profile) {
|
|
88
94
|
return {
|
|
89
95
|
session: profile?.cognitiveTrajectory.session === true,
|
|
90
96
|
keeper: profile?.cognitiveTrajectory.keeper === true,
|
|
@@ -99,18 +105,32 @@ function profileCognitiveTrajectory(profile) {
|
|
|
99
105
|
*
|
|
100
106
|
* ⚠️ 热路径**不用**它(那会用每次工具调用去读盘)——热路径用 `createProfilePromptReader`。
|
|
101
107
|
*/
|
|
102
|
-
function
|
|
108
|
+
function resolveConstraintSystemPrompt(root, profile) {
|
|
103
109
|
if (!profile) return "";
|
|
104
110
|
const file = profile.systemPromptFile?.trim();
|
|
105
111
|
if (file) {
|
|
106
112
|
const abs = resolveInside(root, file);
|
|
107
|
-
if (!existsSync(abs)) throw new Error(
|
|
113
|
+
if (!existsSync(abs)) throw new Error(`轨迹约束 "${profile.code}": systemPromptFile "${file}" not found (resolved: ${abs})`);
|
|
108
114
|
return readUtf8(abs).trim();
|
|
109
115
|
}
|
|
110
116
|
return profile.systemPrompt ?? "";
|
|
111
117
|
}
|
|
112
|
-
/**
|
|
113
|
-
|
|
118
|
+
/**
|
|
119
|
+
* 提示词来源(`list`/`validate` 展示用)。
|
|
120
|
+
*
|
|
121
|
+
* 🔴 **2026-10-19 修(T4 的漏网面)**:v1.72.0 起提示词有两代来源——**新形态**
|
|
122
|
+
* 是轨迹目录里的 `PROMPT.md`(`trajectory/prompt.ts`,**优先**),旧形态才是
|
|
123
|
+
* `systemPromptFile` / `systemPrompt`。本函数原先只认旧形态 ⇒ 两条只写了 `PROMPT.md`
|
|
124
|
+
* 的轨迹在 `container_admin config list` 里恒显示 `promptSource: 'none'`。
|
|
125
|
+
*
|
|
126
|
+
* 那是**读数器过时**,不是配置缺失:`validate` 侧早已按两条来源判(见
|
|
127
|
+
* `trajectory-constraint-admin.ts` 的 `hasTrajectoryPromptOrLegacy`),而 `list` 侧漏了。
|
|
128
|
+
* ⇒ 返 **四种**值,把"有章程但来源是新形态"这一格单独说出来。
|
|
129
|
+
*
|
|
130
|
+
* @param hasPromptFile 该轨迹目录下**是否真有** `PROMPT.md`(调用方查,本函数不做 IO)
|
|
131
|
+
*/
|
|
132
|
+
function constraintSystemPromptSource(profile, hasPromptFile = false) {
|
|
133
|
+
if (hasPromptFile) return "trajectory-file";
|
|
114
134
|
if (profile?.systemPromptFile?.trim()) return "file";
|
|
115
135
|
if (profile?.systemPrompt?.trim()) return "inline";
|
|
116
136
|
return "none";
|
|
@@ -138,7 +158,7 @@ function createProfilePromptReader(root, profile) {
|
|
|
138
158
|
try {
|
|
139
159
|
abs = resolveInside(root, file);
|
|
140
160
|
} catch (err) {
|
|
141
|
-
console.warn(`[serenity-hooks] ✗
|
|
161
|
+
console.warn(`[serenity-hooks] ✗ 轨迹约束提示词路径非法(${file}): ${String(err?.message ?? err)}`);
|
|
142
162
|
}
|
|
143
163
|
if (abs === null) return () => "";
|
|
144
164
|
const absPath = abs;
|
|
@@ -156,19 +176,19 @@ function createProfilePromptReader(root, profile) {
|
|
|
156
176
|
cachedSize = st.size;
|
|
157
177
|
cachedText = text;
|
|
158
178
|
warned = false;
|
|
159
|
-
if (isReload) console.info(`[serenity-hooks] ↻
|
|
179
|
+
if (isReload) console.info(`[serenity-hooks] ↻ 轨迹约束提示词已热重载(${file},${text.length} 字符)`);
|
|
160
180
|
return text;
|
|
161
181
|
} catch (err) {
|
|
162
182
|
if (!warned) {
|
|
163
183
|
warned = true;
|
|
164
|
-
console.warn(`[serenity-hooks] ✗
|
|
184
|
+
console.warn(`[serenity-hooks] ✗ 轨迹约束提示词读取失败(${file})——沿用上次成功内容: ${String(err?.message ?? err)}`);
|
|
165
185
|
}
|
|
166
186
|
return cachedText;
|
|
167
187
|
}
|
|
168
188
|
};
|
|
169
189
|
}
|
|
170
190
|
/**
|
|
171
|
-
*
|
|
191
|
+
* 轨迹约束 基础提示词(dsp 只给这部分;CCC 的 `systemPrompt` 段由调用方拼接)。
|
|
172
192
|
*
|
|
173
193
|
* ## 🔴 为什么**不再枚举**清单(owner 2026-10-19 令)
|
|
174
194
|
*
|
|
@@ -184,11 +204,11 @@ function createProfilePromptReader(root, profile) {
|
|
|
184
204
|
*
|
|
185
205
|
* ⇒ 现在只声明**边界与发现路径**,不抄内容:清单在哪,怎么取,越界会怎样。
|
|
186
206
|
*
|
|
187
|
-
* @param code
|
|
207
|
+
* @param code 轨迹编码(轨迹约束的身份 —— 不是"角色名",那个概念已退役)
|
|
188
208
|
*/
|
|
189
|
-
function
|
|
209
|
+
function buildTrajectoryBasePrompt(code) {
|
|
190
210
|
return [
|
|
191
|
-
"=== Serenity
|
|
211
|
+
"=== Serenity 轨迹约束 ===",
|
|
192
212
|
`Cognitive trajectory: ${code} (this is the trajectory you ARE, not a role you play)`,
|
|
193
213
|
"Your capability boundary is enforced mechanically by this CCC — anything outside it is rejected at the call site, not by your judgment.",
|
|
194
214
|
"Discover your surface, do not memorize it (both are generated from the live config on every turn):",
|
|
@@ -202,57 +222,6 @@ function buildSkiffBasePrompt(code) {
|
|
|
202
222
|
].join("\n");
|
|
203
223
|
}
|
|
204
224
|
//#endregion
|
|
205
|
-
//#region src/kernel/ports.ts
|
|
206
|
-
/**
|
|
207
|
-
* 集中端口表。
|
|
208
|
-
* A=宿主主面(插件不监听)/ B=网关(可配,默认关)/ C=微信发送(默认开,仅 loopback)
|
|
209
|
-
* / D=Skiff 调试(默认关)。
|
|
210
|
-
*/
|
|
211
|
-
const FACE_PORTS = {
|
|
212
|
-
main: {
|
|
213
|
-
port: 3080,
|
|
214
|
-
host: null,
|
|
215
|
-
defaultEnabled: true,
|
|
216
|
-
meaning: "宿主 DSH 主 WebUI + 插件 /serenity/* 路由面(**插件不起此 listener**,端口自宿主读)"
|
|
217
|
-
},
|
|
218
|
-
gateway: {
|
|
219
|
-
port: 3081,
|
|
220
|
-
host: "0.0.0.0",
|
|
221
|
-
defaultEnabled: false,
|
|
222
|
-
meaning: "双端口网关(外部登录 + 全量反代宿主主面;host/port 走 plugin 全局配置)"
|
|
223
|
-
},
|
|
224
|
-
weixinSend: {
|
|
225
|
-
port: 3082,
|
|
226
|
-
host: "127.0.0.1",
|
|
227
|
-
defaultEnabled: true,
|
|
228
|
-
meaning: "微信主动发送面(容器外进程 → POST /send;与 3080 显式解耦,不经网关)"
|
|
229
|
-
},
|
|
230
|
-
skiffDebug: {
|
|
231
|
-
port: 3099,
|
|
232
|
-
host: "127.0.0.1",
|
|
233
|
-
defaultEnabled: false,
|
|
234
|
-
meaning: "Skiff 调试问答面(人工调试子角色;无认证,仅靠 loopback)"
|
|
235
|
-
}
|
|
236
|
-
};
|
|
237
|
-
/** 宿主主 WebUI 端口(面 A:插件**不监听**,只读取;`readWebPort` 的回退值) */
|
|
238
|
-
const MAIN_WEB_PORT = FACE_PORTS.main.port;
|
|
239
|
-
/** 网关端口默认值(面 B) */
|
|
240
|
-
const GATEWAY_PORT = FACE_PORTS.gateway.port;
|
|
241
|
-
/** 微信主动发送端口默认值(面 C) */
|
|
242
|
-
const WEIXIN_SEND_PORT = FACE_PORTS.weixinSend.port;
|
|
243
|
-
/** Skiff 调试页端口默认值(面 D) */
|
|
244
|
-
const SKIFF_DEBUG_PORT = FACE_PORTS.skiffDebug.port;
|
|
245
|
-
/**
|
|
246
|
-
* **机制端口**词表(output-guard 用:agent 在**用户可见输出**里提及内部端口即打回)。
|
|
247
|
-
*
|
|
248
|
-
* 由 {@link FACE_PORTS} 机械派生 ⇒ 与面清单**永不漂移**。
|
|
249
|
-
* ⚠️ 修复记录(C4 块 B,2026-09-15):旧常量硬写 `['3080','3081','3099','3100']`
|
|
250
|
-
* ——**漏 3082**(微信发送面,默认开)⇒ 守卫拦不住"3082"这类提及。现由表派生,四面齐全。
|
|
251
|
-
* ⚠️ 面变更记录(2026-10-15):**面 E(3100 ACP/问答)已整体退役**(owner 裁「砍掉外部问答」)
|
|
252
|
-
* ⇒ 本词表随之少一项,**无需另改**(这正是"派生而非手抄"的收益)。
|
|
253
|
-
*/
|
|
254
|
-
const MECHANISM_PORTS = Object.keys(FACE_PORTS).map((id) => String(FACE_PORTS[id].port));
|
|
255
|
-
//#endregion
|
|
256
225
|
//#region src/surface/settings.ts
|
|
257
226
|
/**
|
|
258
227
|
* 设置面板命名空间 = **profile 条目 id**(v0.1.7 起;与旧 `settings.yaml` 段名逐字相同)。
|
|
@@ -263,8 +232,6 @@ function defaultSimpleSettings() {
|
|
|
263
232
|
return {
|
|
264
233
|
gatewayEnabled: false,
|
|
265
234
|
rebuildThresholdK: 400,
|
|
266
|
-
skiffEnabled: false,
|
|
267
|
-
skiffDebugPort: SKIFF_DEBUG_PORT,
|
|
268
235
|
croEnabled: true,
|
|
269
236
|
diagramEnabled: false,
|
|
270
237
|
humanChannel: defaultHumanChannelSettings()
|
|
@@ -280,7 +247,7 @@ function defaultSimpleSettings() {
|
|
|
280
247
|
* `meta.volatile` **无条件**包 `createVolatile(value)`,且该分支排在"缺省值回退"那一段
|
|
281
248
|
* **之前** ⇒ **"用户没设过"的字段也是恒真对象**(`.get()` 返回 `undefined`),**不是 `undefined`**。
|
|
282
249
|
*
|
|
283
|
-
* ⇒ 若这里不解包,下面十行的 `??` 链会**短路在这层包装上** ⇒ 网关 /
|
|
250
|
+
* ⇒ 若这里不解包,下面十行的 `??` 链会**短路在这层包装上** ⇒ 网关 / 轨迹约束 会被
|
|
284
251
|
* **无意打开**(比"面板不显示"更坏:静默改变对外暴露面)。
|
|
285
252
|
*
|
|
286
253
|
* ## 为什么用结构判定
|
|
@@ -358,8 +325,6 @@ function simpleSettingsFromConfig(config) {
|
|
|
358
325
|
return {
|
|
359
326
|
gatewayEnabled: unwrapVolatile(config.gatewayEnabled) ?? config.gateway?.enabled ?? d.gatewayEnabled,
|
|
360
327
|
rebuildThresholdK: unwrapVolatile(config.rebuildThresholdK) ?? config.rebuild?.thresholdK ?? d.rebuildThresholdK,
|
|
361
|
-
skiffEnabled: unwrapVolatile(config.skiffEnabled) ?? config.skiff?.enabled ?? d.skiffEnabled,
|
|
362
|
-
skiffDebugPort: unwrapVolatile(config.skiffDebugPort) ?? config.skiff?.debugPort ?? d.skiffDebugPort,
|
|
363
328
|
croEnabled: unwrapVolatile(config.croEnabled) ?? d.croEnabled,
|
|
364
329
|
diagramEnabled: unwrapVolatile(config.diagramEnabled) ?? config.diagram?.enabled ?? d.diagramEnabled,
|
|
365
330
|
humanChannel: humanChannelSettingsFromConfig(config.humanChannel)
|
|
@@ -368,7 +333,7 @@ function simpleSettingsFromConfig(config) {
|
|
|
368
333
|
/** 运行时源(`registerSettingsSection` 装配:读本插件 fiber 的**当前** Config) */
|
|
369
334
|
let simpleSource = null;
|
|
370
335
|
/**
|
|
371
|
-
* 读取当前简单配置(各功能 gateway/rebuild
|
|
336
|
+
* 读取当前简单配置(各功能 gateway/rebuild/轨迹约束/… 的启动与运行时判断都经此)。
|
|
372
337
|
*
|
|
373
338
|
* 源 = 本插件 fiber 的 `config`(宿主在配置变更时走 `fiber.update()` ⇒ `config` 始终最新,
|
|
374
339
|
* **不必**依赖 apply 重跑,也不必缓存)。
|
|
@@ -400,4 +365,4 @@ function registerSettingsSection(ctx, config) {
|
|
|
400
365
|
} catch {}
|
|
401
366
|
}
|
|
402
367
|
//#endregion
|
|
403
|
-
export {
|
|
368
|
+
export { buildTrajectoryBasePrompt as a, createProfilePromptReader as c, resolveConstraintSystemPrompt as d, ACC_VERSION as f, TRAJECTORY_CONSTRAINT_HINT as i, profileMsmWhitelist as l, readSimpleSettings as n, constraintCognitiveTrajectory as o, findPackageRoot as p, registerSettingsSection as r, constraintSystemPromptSource as s, SERENITY_SETTINGS_NS as t, profileToolWhitelist as u };
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* 六条硬性规则(逐条对应设计 §4.2,改这里先改那里):
|
|
15
15
|
* ① **只枚举,不注入正文** —— 索引里**绝不**出现任何参考文件的正文;
|
|
16
16
|
* ② **确定性排序** = 相对路径的 **UTF-8 字节序**(🔴 **不用 mtime**:mtime 随检出漂移,
|
|
17
|
-
* 会让每请求的注入文本抖动;对照 `src/
|
|
17
|
+
* 会让每请求的注入文本抖动;对照 `src/cro/core.ts:101` 那份**落盘快照**用 {name,bytes,mtime} ——
|
|
18
18
|
* **同一件事两处的取舍相反,那个差异是判据不是巧合**);
|
|
19
19
|
* ③ **有界 + 响亮** —— 条数/字符各有上限,超出**必须显式写出还剩多少项**,**绝不静默截断**;
|
|
20
20
|
* ④ **摘要可复现** —— 取该文件首个 `#` 标题(剥 markdown 记号);取不到 ⇒ 留空,**不编**;
|
package/lib/surface/faces.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* ## 现状 → 本模块要收掉什么(取证:`…/acc-c4c5-current-state.md` §①/§③ 3.1)
|
|
5
5
|
*
|
|
6
|
-
* 插件自己 spawn 了**三个** node:http 监听器(B 3081 网关 / C 3082 微信发送 / D 3099
|
|
6
|
+
* 插件自己 spawn 了**三个** node:http 监听器(B 3081 网关 / C 3082 微信发送 / D 3099 轨迹约束调试)。
|
|
7
7
|
* ⚠️ **2026-10-15 变更**:原为四个(含 **E 3100 ACP+问答**),E 已随 owner「砍掉外部问答」令**整面退役**
|
|
8
8
|
* ⇒ 仍保有面 B/C/D 三个;本段保留"当年是四个"的记述,因为下方"两套拆卸"的病史由它解释。
|
|
9
9
|
* 此前四处各写一份同款样板:`createServer` + `server.once('error')` +
|
package/lib/surface/http.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ interface StatusApiRegistration {
|
|
|
39
39
|
*
|
|
40
40
|
* 🔴🔴 **2026-10-18 修缺陷(owner 报「在别的 CCC 点开显示的还是 home-serenity 的信息」)**:
|
|
41
41
|
* 旧实现第 ③ 步是「**遍历 live sessions 找第一个 CCC 会话的 cwd**」—— 那是**跨工作区猜测**:
|
|
42
|
-
* 只要 sessionId 缺失或那条会话查不到(ACP
|
|
42
|
+
* 只要 sessionId 缺失或那条会话查不到(ACP/轨迹约束会话、尚未 materialize 的会话、远程访问),
|
|
43
43
|
* 它就会**静默返回另一个 CCC 的路径**,于是面板把**别人的轨迹/技能/安全模式**当成你的显示出来。
|
|
44
44
|
* 这比"显示未激活"危险得多 —— 用户会据此做判断(以为自己的 safe-mode 开着、以为那是自己的轨迹)。
|
|
45
45
|
*
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* ## 为什么旧扁平键**原样保留**(这是本文件最容易被后人改错的地方)
|
|
16
16
|
*
|
|
17
17
|
* 旧模型把简单配置存成 `~/.dsh/settings.yaml` 的 `serenity-hooks:` 段,字段名是**扁平**的
|
|
18
|
-
* (`gatewayEnabled` / `
|
|
18
|
+
* (`gatewayEnabled` / `轨迹约束Enabled` / …)。新模型的命名空间**逐字相同**
|
|
19
19
|
* (`serenity-hooks`),而宿主的 `SettingsForms.importLegacyDocument()` 会把该段
|
|
20
20
|
* **按同名条目导入**;schemastery 的 object 解析在非 strict 模式下 `merge(result, data)`
|
|
21
21
|
* ⇒ **未声明的键会被保留而非报错**。⇒ 只要这些扁平键**仍在本插件 Config 里声明**,
|
|
@@ -59,12 +59,12 @@ interface SimpleConfigFragment {
|
|
|
59
59
|
rebuild?: {
|
|
60
60
|
thresholdK?: number;
|
|
61
61
|
};
|
|
62
|
-
/** F4
|
|
63
|
-
|
|
62
|
+
/** F4 轨迹约束(实验性):调试服务启停(人工) */
|
|
63
|
+
轨迹约束?: {
|
|
64
64
|
enabled?: boolean;
|
|
65
65
|
debugPort?: number;
|
|
66
66
|
};
|
|
67
|
-
/** F4
|
|
67
|
+
/** F4 轨迹约束(实验性):调试服务启停(人工) */
|
|
68
68
|
/** diagram(实验性 demo;2026-09-29 owner 具名令 D104):标签源码 → 进程内出图(不借浏览器) */
|
|
69
69
|
diagram?: {
|
|
70
70
|
enabled?: boolean;
|
|
@@ -73,8 +73,6 @@ interface SimpleConfigFragment {
|
|
|
73
73
|
humanChannel?: HumanChannelConfigFragment;
|
|
74
74
|
gatewayEnabled?: PanelBoolean;
|
|
75
75
|
rebuildThresholdK?: PanelNumber;
|
|
76
|
-
skiffEnabled?: PanelBoolean;
|
|
77
|
-
skiffDebugPort?: PanelNumber;
|
|
78
76
|
croEnabled?: PanelBoolean;
|
|
79
77
|
diagramEnabled?: PanelBoolean;
|
|
80
78
|
}
|
|
@@ -90,10 +88,6 @@ interface SerenitySimpleSettings {
|
|
|
90
88
|
gatewayEnabled: boolean;
|
|
91
89
|
/** F2 触发阈值(需求① S142 用户拍板:百分比比例 → K 数值;projectedTokens ≥ thresholdK*1000 触发) */
|
|
92
90
|
rebuildThresholdK: number;
|
|
93
|
-
/** F4 Skiff 调试服务总开关(实验性;默认关——不随插件加载自动启动,人工开启) */
|
|
94
|
-
skiffEnabled: boolean;
|
|
95
|
-
/** F4 Skiff 调试端口(默认 3099,仅 127.0.0.1) */
|
|
96
|
-
skiffDebugPort: number;
|
|
97
91
|
/** **CRO(轨迹自编程唤起)总开关**(2026-09-21 所有者令新增;**缺省开**)。
|
|
98
92
|
*
|
|
99
93
|
* CRO = 轨迹目录下放一个 `continuous-re-occurrence.ts`,由 ACC 的 5min tick spawn,
|
|
@@ -109,7 +103,7 @@ interface SerenitySimpleSettings {
|
|
|
109
103
|
* `parseDsl → renderDsl(SVG + 四项体检)→ resvg-wasm 光栅化(内置字体)→ PNG`,
|
|
110
104
|
* 产物落 CCC `_tmp/diagram/` 且**图片块进对话**(**不借浏览器、不截图**)。
|
|
111
105
|
* **缺省关**:owner 口中的"demo 功能" ⇒ 关时**不注册**(工具不进模型工具清单:
|
|
112
|
-
* 零 token、不会被误调),同
|
|
106
|
+
* 零 token、不会被误调),同 `轨迹约束` 的"未开启零资源占用"口径。
|
|
113
107
|
* 依赖面:随包分发 3.8 MB 内置字体(`assets/diagram/`,wasm 对系统字体不可见)。 */
|
|
114
108
|
diagramEnabled: boolean;
|
|
115
109
|
/** **human-channel(人机信道)机器级配置**(2026-09-26 owner 定案;P0-1 立 schema + 投影)。
|
|
@@ -134,7 +128,7 @@ interface VolatileRef<T> {
|
|
|
134
128
|
* `meta.volatile` **无条件**包 `createVolatile(value)`,且该分支排在"缺省值回退"那一段
|
|
135
129
|
* **之前** ⇒ **"用户没设过"的字段也是恒真对象**(`.get()` 返回 `undefined`),**不是 `undefined`**。
|
|
136
130
|
*
|
|
137
|
-
* ⇒ 若这里不解包,下面十行的 `??` 链会**短路在这层包装上** ⇒ 网关 /
|
|
131
|
+
* ⇒ 若这里不解包,下面十行的 `??` 链会**短路在这层包装上** ⇒ 网关 / 轨迹约束 会被
|
|
138
132
|
* **无意打开**(比"面板不显示"更坏:静默改变对外暴露面)。
|
|
139
133
|
*
|
|
140
134
|
* ## 为什么用结构判定
|
|
@@ -226,7 +220,7 @@ export declare function humanChannelSettingsFromConfig(fragment: HumanChannelCon
|
|
|
226
220
|
*/
|
|
227
221
|
export declare function simpleSettingsFromConfig(config: SimpleConfigFragment): SerenitySimpleSettings;
|
|
228
222
|
/**
|
|
229
|
-
* 读取当前简单配置(各功能 gateway/rebuild
|
|
223
|
+
* 读取当前简单配置(各功能 gateway/rebuild/轨迹约束/… 的启动与运行时判断都经此)。
|
|
230
224
|
*
|
|
231
225
|
* 源 = 本插件 fiber 的 `config`(宿主在配置变更时走 `fiber.update()` ⇒ `config` 始终最新,
|
|
232
226
|
* **不必**依赖 apply 重跑,也不必缓存)。
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* surface/text.ts — 输出文本的清洗原语(**纯函数,零 listener、零宿主依赖**,可独立单测)
|
|
3
|
+
*
|
|
4
|
+
* ## 为什么它从调试面里拆出来(S11,2026-10-19,轨迹中心重构)
|
|
5
|
+
*
|
|
6
|
+
* 拆之前它是 `role/轨迹约束/debug.ts` 的**后半段**,而那份文件是**混装件**:
|
|
7
|
+
* · 前半段 = **面 D** 的 HTTP 调试页(自起 listener,端口见 `kernel/ports.ts`)
|
|
8
|
+
* · 后半段 = **通用文本清洗**(本文件,已随重构搬到 `surface/text.ts`)
|
|
9
|
+
*
|
|
10
|
+
* 判据(实测,不是猜):本文件的导出被**两个与 轨迹约束 无关的模块**直接使用 ——
|
|
11
|
+
* `im/bridge.ts`(微信桥:回复前剥 think)与 `guard/seam.ts`(输出守卫:检测前剥 think)。
|
|
12
|
+
* ⇒ 它不属于"某一条轨迹的调试面",它是**任何输出面都会用的清洗**。
|
|
13
|
+
*
|
|
14
|
+
* ## 与面的关系(单向)
|
|
15
|
+
*
|
|
16
|
+
* `surface/debug.ts`(面 D)──► 本文件
|
|
17
|
+
* 本文件 ──► 无(不 import 任何面)
|
|
18
|
+
*
|
|
19
|
+
* ⛔ **反向依赖会立刻建立环**:本文件若为了"方便"去 import 面 D 的 sendJson 之类,
|
|
20
|
+
* 就把纯函数拖进了 HTTP 生命周期。
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Markdown 渲染(v1.25.9,正经库 marked 服务端渲染——替代手写正则渲染器,S142 用户要求):
|
|
24
|
+
* ① 提取 `<think>…</think>` 块(v1.26.8 状态机扫描,占位符 \u0001T<idx>\u0001)
|
|
25
|
+
* ② 正文与 think 内容**先 escapeHtml 再 marked.parse**(GFM + breaks)——markdown 语法不受
|
|
26
|
+
* 转义影响,原始 HTML 注入被消除(安全);代码块内 `<` 显示为实体(可接受)
|
|
27
|
+
* ③ think 占位符:默认还原为 `<details class="think">` 折叠卡(🧠 思考过程,默认收起);
|
|
28
|
+
* **hideThink=true(v1.26.4,public 口)→ 直接移除**(思考过程对普通用户不展示)
|
|
29
|
+
* @param hideThink 为 true 时 `<think>` 内容完全不渲染(public 问答页体验)
|
|
30
|
+
*/
|
|
31
|
+
export declare function renderTrajectoryMarkdown(raw: string, hideThink?: boolean): string;
|
|
32
|
+
/**
|
|
33
|
+
* 剥离 `<think>…</think>` 块(v1.27.1,微信桥用户反馈:"过微信桥回复给用户的消息,
|
|
34
|
+
* 要去掉 think 标签,用户不应看到")。复用 extractThinkBlocks 状态机(v1.26.8,
|
|
35
|
+
* 弃正则)——提取后**只保留正文**(占位符替换为空,think 内容丢弃),
|
|
36
|
+
* 未闭合 think 优雅截断。适用于纯文本输出面(微信等不支持 think 折叠的通道)。
|
|
37
|
+
*/
|
|
38
|
+
export declare function stripThink(raw: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* JSC (Safari/iOS) JSON.parse 快速路径正则兼容化(v1.26.9,S142 调研定稿)。
|
|
41
|
+
*
|
|
42
|
+
* 背景:WebKit bug 200190「JavaScriptCore's Regex can't match the content」——JSC 的
|
|
43
|
+
* JSON.parse 用**内部正则**预校验字符串;内容含**原始** `\u2028`(行分隔符)/`\u2029`
|
|
44
|
+
* (段分隔符)时正则无法匹配 → 对**合法 JSON** 也抛
|
|
45
|
+
* `SyntaxError: The string did not match the expected pattern`(sentry-javascript #2487 同源)。
|
|
46
|
+
* JSON.stringify **不转义** `\u2028`/`\u2029`/`\uFEFF`(它们都是合法 JSON 字符串字符)→
|
|
47
|
+
* 在 JSON **文本层**把它们替换为 `\uXXXX` 转义序列:JSON.parse 后语义完全一致(还原原字符),
|
|
48
|
+
* 且 JSC 正则看到的是常规 ASCII 转义(与 JSON.stringify 对控制字符的输出同形态,安全)。
|
|
49
|
+
*
|
|
50
|
+
* 3099 调试页客户端 `await res.json()` 与页面内嵌 JSON 均需此兼容层
|
|
51
|
+
* ——iOS Safari 用户实测"复杂回答"触发。(原同批还列了 3100 问答页,该面已退役,2026-10-15)
|
|
52
|
+
*
|
|
53
|
+
* @param jsonText JSON.stringify 的输出文本;原地等价替换,返回 JSC 安全文本
|
|
54
|
+
*/
|
|
55
|
+
export declare function jscSafeJsonText(jsonText: string): string;
|
|
56
|
+
/** HTML 文本/属性转义(本文件的唯一转义口径;面 D 渲染时也用这一个,不另写) */
|
|
57
|
+
export declare function escapeHtml(s: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* 提取 `<think>…</think>` 块(v1.26.8:**状态机扫描,弃正则**——用户批评"老用正则不是个办法")。
|
|
60
|
+
*
|
|
61
|
+
* 逐字符扫描识别开/闭标签(大小写不敏感;`<think ...>` 允许属性变体;`</think >` 允许尾随空格),
|
|
62
|
+
* 不依赖正则回溯,天然处理:
|
|
63
|
+
* - **嵌套 `<think>`**(内层按内容处理,不递归——DeepSeek think 不会嵌套)
|
|
64
|
+
* - **未闭合 `<think>`**(优雅截断:剩余全部作为 think 内容,不泄漏标记)
|
|
65
|
+
* - **占位符冲突**(用 \u0001T<idx>\u0001——ASCII 控制字符,正文几乎不可能出现)
|
|
66
|
+
*
|
|
67
|
+
* @returns body(占位符替换后的正文)+ thinks(提取的 think 内容数组,保序)
|
|
68
|
+
*/
|
|
69
|
+
export declare function extractThinkBlocks(raw: string): {
|
|
70
|
+
body: string;
|
|
71
|
+
thinks: string[];
|
|
72
|
+
};
|
package/lib/surface/usage.d.ts
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* ⇒ 本模块让每个 CCC 留下一份**纯计数**账本:**用了哪个、多少次、第一次和最近一次是什么时候**。
|
|
16
16
|
* 用途 = 清理/精简的**依据**(没有人用的东西与天天在用的东西,不再靠猜)。
|
|
17
17
|
*
|
|
18
|
-
* ## 🔴 铁律(与 `
|
|
18
|
+
* ## 🔴 铁律(与 `cro/log.ts` 同族)
|
|
19
19
|
*
|
|
20
20
|
* **本模块每个导出函数都不抛错**:读盘 / 解析 / 写盘失败一律返回结构化失败,
|
|
21
21
|
* 由调用方只记一行日志(或什么都不做)⇒ **统计的问题绝不影响工具执行与既有链路**。
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
*
|
|
32
32
|
* 宿主会被重启(本容器实测 24h 内 3 次)⇒ 计数**不能只活在内存里**:
|
|
33
33
|
* 每次写盘 = **读旧文件 → 在旧值上自增 → 原子写**(`tmp + rename`,与 `wake/registry.ts` /
|
|
34
|
-
* `
|
|
34
|
+
* `cro/log.ts` 同款形态)⇒ **进程重启后计数自然延续**,无需额外的 flush/落盘时机。
|
|
35
35
|
*
|
|
36
36
|
* ## 口径(两个字段,勿合并)
|
|
37
37
|
*
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tools/config-docs.ts — `container_admin config docs` 的**两层菜单**(P3,2026-10-19)
|
|
3
|
+
*
|
|
4
|
+
* ## owner 原话(本文件存在的全部理由,逐字)
|
|
5
|
+
*
|
|
6
|
+
* > 「im 的整体配置方法要在 ACC 级有方法能交代我们的**说明类内容**越来越多了,
|
|
7
|
+
* > 做个**两层菜单**来承载吧,admin 里面搞两个方法,一个是**使用说明目录**,
|
|
8
|
+
* > 一个是**使用说明详情(按章节获得)**」
|
|
9
|
+
*
|
|
10
|
+
* ⇒ 第一层 `docs`(无参)= **目录**:只列"有哪几章、每章一句话、去哪个子命令看详情"。
|
|
11
|
+
* 第二层 `docs <chapter>` = **详情**:该章全文。
|
|
12
|
+
*
|
|
13
|
+
* ## 为什么是"目录 + 按章详情"而不是一坨长文(R↓,这不是排版偏好)
|
|
14
|
+
*
|
|
15
|
+
* 说明类内容已经长到 `ccc-config` 单份约 20 KB。整份塞进一次工具返回有两个真实代价:
|
|
16
|
+
* ① **截断** —— 宿主对工具结果有预算(超了走 head/tail + 落盘)⇒ 用户拿到的**不是全文**,
|
|
17
|
+
* 而是它以为的全文(本轨 A59 记过这一格)。
|
|
18
|
+
* ② **不可发现** —— 一坨长文里"我该看哪一段"要靠通读才知道;目录让模型**先选后读**。
|
|
19
|
+
* ⇒ 判据:**目录只索引,不复制**。每章正文的唯一真相源仍在它自己的产出函数里
|
|
20
|
+
* (本章 = `ccc-config` 的对应段 / `role guide` 全文),本文件只做**切分与路由**。
|
|
21
|
+
*
|
|
22
|
+
* ## 归属(D23)
|
|
23
|
+
* 机制在 ACC(有哪几章、怎么切、怎么路由);**章目内容**部分来自 ACC 自己的 guide
|
|
24
|
+
* (那些是机制说明),部分来自 CCC 的配置现状(运行时读取)。
|
|
25
|
+
*
|
|
26
|
+
* ## 与 `msm catalog` 的分工(两个目录不是冗余)
|
|
27
|
+
* - `msm catalog` = **工具/能力**目录("去哪找功能说明")
|
|
28
|
+
* - `config docs` = **配置**目录("这个键怎么填、填错会怎样")
|
|
29
|
+
* 二者在 ④ 章互指,但**不复制**对方的内容。
|
|
30
|
+
*/
|
|
31
|
+
/** 一个章节 = 菜单项(第一层)+ 正文(第二层) */
|
|
32
|
+
export interface DocsChapter {
|
|
33
|
+
/** 章节 id(稳定标识:`config docs <id>`;**英文短名**,便于逐字敲出来) */
|
|
34
|
+
id: string;
|
|
35
|
+
/** 菜单里的一句话(用户据此决定要不要读下去) */
|
|
36
|
+
summary: string;
|
|
37
|
+
/** 该章正文(第二层才返回;**惰性**——目录不触发它) */
|
|
38
|
+
render: () => string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 渲染**目录**(第一层)。
|
|
42
|
+
*
|
|
43
|
+
* 🔴 只调 `summary`,**绝不调 `render`** —— 目录若触发正文,就退化成"整份长文"。
|
|
44
|
+
* 这条不是性能优化,是**判据**:它保证 `docs` 的输出大小与章数成正比,与正文长度无关。
|
|
45
|
+
*/
|
|
46
|
+
export declare function renderDocsIndex(chapters: readonly DocsChapter[]): string;
|
|
47
|
+
/**
|
|
48
|
+
* 解析一个章节参数(第二层)。
|
|
49
|
+
*
|
|
50
|
+
* 不存在 ⇒ 返回 `null`,由调用方给出**带候选清单**的拒绝 ——
|
|
51
|
+
* "不知道这个章节" 与 "这一章是空的" 必须可区分(否则用户以为功能没有)。
|
|
52
|
+
*/
|
|
53
|
+
export declare function findDocsChapter(chapters: readonly DocsChapter[], id: string): DocsChapter | null;
|
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* container-admin.ts — container_admin(v1.30:机务舱——容器管理面统一入口)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* · skiff_admin(F4 Skiff 认知子集角色:guide/validate/apply/list)
|
|
6
|
-
* · acc_msm 管理面(register/deregister/check/guide/catalog/ccc-config)
|
|
7
|
-
* —— msm 工具只管执行+发现;一切「管理容器」的操作归本工具
|
|
4
|
+
* ## 域结构(2026-10-19 owner 两条令后:**两域**)
|
|
8
5
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* | 域 | 管什么 |
|
|
7
|
+
* |---|---|
|
|
8
|
+
* | `config` | **本 CCC 的全部配置面**:说明目录/按章详情 + 轨迹约束(原 `role` 域,已并入) |
|
|
9
|
+
* | `msm` | MSM 注册表管理 + 手册(register/deregister/check/guide/catalog/ccc-config) |
|
|
10
|
+
*
|
|
11
|
+
* 🔴 **`role` 域已并入 `config`**(owner 2026-10-19 裁「1 并入」)。为什么不是三个平行域:
|
|
12
|
+
* `role` 管的本来就是"某条轨迹的约束面"——**一组配置**,与 `config` 是同一抽象层的两半。
|
|
13
|
+
* 分着放的代价是:用户在 `config` 里看不到"轨迹怎么约束",得先知道 `role` 这个词存在。
|
|
14
|
+
* ⚠️ **旧 `role` 域仍被接受**(过渡别名,指向同一实现)——存量 CCC 的文档/脚本里到处是
|
|
15
|
+
* `container_admin role validate`(实测本仓 30 处),硬切会让它们全部变成"未知域"。
|
|
16
|
+
* 别名**只保留读取路径**:schema 的 `enum` 只列新名,文案只教新名。
|
|
12
17
|
*
|
|
13
|
-
*
|
|
18
|
+
* ## 三个动作名为什么是这三个(P3 的实现形态)
|
|
19
|
+
* - `config docs`(无参)→ **使用说明目录**(第一层;只索引不复制)
|
|
20
|
+
* - `config docs <chapter>` → **使用说明详情**(第二层;按章获得)
|
|
21
|
+
* - `config view` → 配置**现值**(原来是唯一动作;现在是"看当前填了什么")
|
|
14
22
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* `ctx` 现**无消费者**,工厂形态保留只是为了让装配点签名不再变动(见 index.ts 注册处)。
|
|
23
|
+
* 归属(D23):**机制在 ACC**(有哪几章、怎么路由、怎么校验),**内容在 CCC**(填什么)。
|
|
24
|
+
* 语义(用户拍板"轨迹约束_admin 及系列 admin 合并成 container_admin"):
|
|
25
|
+
* container = CCC(具体认知容器);admin = 管理操作。
|
|
19
26
|
*/
|
|
20
27
|
import type { Context } from 'cordis';
|
|
21
28
|
export declare function createContainerAdminTool(ctx: Context): import("@deepseek-ai/dsh-tools").ToolDefinition;
|
|
@@ -8,6 +8,13 @@ import type { JsonValue } from '../../kernel/json.js';
|
|
|
8
8
|
type MsmAction = 'list' | 'exec' | 'register' | 'deregister' | 'check' | 'guide' | 'ccc-config' | 'catalog';
|
|
9
9
|
export declare const MSM_ACTIONS: readonly MsmAction[];
|
|
10
10
|
export declare const MSM_GUIDE = "MSM Development Manual (Mech & Semi-Mech framework)\n\n## What it is\nMSM = the executable-unit layer. Mech is pure TS with zero LLM reasoning; Semi-Mech is a TS framework + LLM decision points.\nMSM is ACC's deterministic executable-unit layer \u2014 all shell/exec operations go through MSM and cannot be bypassed.\n\n## Registering a new MSM (container_admin msm register)\n1. Write the script under <skill>/scripts/ (runnable via tsx; must include a main() CLI guard with an import.meta.url check)\n2. container_admin msm register --domain msm --action register <name> --skill <s> --path <script path relative to root> --category <mech|semi-mech> --description <desc>\n3. Auto-writes mech-registry.json (preserving the original format) + git commit (commits only the registry file)\n4. Validation: path must be inside root, script must exist, name must be globally unique\n\n## flag schema (v1)\nflags is a new-style object array for parameter validation and path-escape guarding:\n [{\"name\":\"output\",\"type\":\"string\",\"description\":\"output path\"},\n {\"name\":\"target\",\"type\":\"path\",\"description\":\"operation target (type:path enables in-root validation + symlink defense)\"},\n {\"name\":\"force\",\"type\":\"boolean\",\"description\":\"force mode\",\"default\":false}]\n- {name, type} format \u2014 new style, type:\"path\" enables the path-escape guard\n- {flag, description} format \u2014 old style, CLI flag description string\n- On registration, flags are passed via container_admin msm register --flags '<json>'\n\n## Script conventions\n- Top-of-file documentation: purpose / usage / exit codes\n- Exit codes: 0 success / 1 user / 2 system / 3 operator (per ACC protocol classification)\n- main() CLI guard (DC-M2): the script must start with\n if (import.meta.url === `file://${process.argv[1]}`) { main() }\n or an equivalent isMain / require.main === check \u2014 so vitest imports never trigger top-level code\n- A paired .test.ts or .spec.ts (DC-M1, vitest)\n- Business subprocess environment: SERENITY_ROOT / SERENITY_CCC / SERENITY_VERSION injected\n\n## Interaction & confirmation conventions (no blocking confirmation)\n- MSMs run in **user-less subprocesses** (spawn/execFile, 600s timeout) \u2014 **never** use\n readline / prompt / process.stdin etc. to block waiting for user input (it would hang until killed by the timeout)\n- When a second confirmation is needed: **directly return the confirmation request** (list the operation to perform and its impact + how to retry with the confirmation flag),\n returning a non-zero exit code (or an explicit hint)\n- After the agent confirms, **re-invoke the MSM with the confirmation flag** (e.g. --confirm / --yes / --force) to retry\n- Standard mode (two-phase):\n 1. First call: destructive/confirmation-requiring operation detected and no confirmation flag present \u2192 output the confirmation request (list operation/impact/rollback),\n exit non-zero (e.g. 1 user), **perform no changes**\n 2. After the agent evaluates, re-invoke: with the confirmation flag \u2192 execute and output the result\n- Applies to: delete/overwrite/push/batch operations and other irreversible or wide-impact operations\n- Anti-example (forbidden): readline waiting for user input, process.stdin.on('data') blocking waits\n (MSMs have no stdin interaction channel \u2014 they hang until the 600s timeout)\n\n## Quality checks (container_admin msm check, DC-M1~M4)\nDC-M1 has .test.ts/.spec.ts; DC-M2 has a main() guard (function main( / isMain / require.main === / import.meta.url);\nDC-M3 bidirectional: scripts unregistered + registry references missing scripts; DC-M4 path-type flags marked type:\"path\"\n\n## Self-description (protocol flags, first argument only)\nmsm(\"<name>\", [\"--list\"]) \u2014 list all MSMs\nmsm(\"<name>\", [\"--schema\", \"<n>\"]) \u2014 view a specific MSM's parameter schema\nmsm(\"<name>\", [\"--format=json\"]) \u2014 JSON output mode (remaining args passed through losslessly)\n";
|
|
11
|
+
/**
|
|
12
|
+
* CCC 配置参考(对齐 osp ccc-config action)。
|
|
13
|
+
*
|
|
14
|
+
* 🔴 **2026-10-19 起导出**:`container_admin config docs config` 的两层菜单把它作为
|
|
15
|
+
* 「config」章正文返回。**不另写一份**——同一段说明有第二份副本就会漂(本轨反复踩过)。
|
|
16
|
+
*/
|
|
17
|
+
export declare const CCC_CONFIG_REFERENCE = "\u2550\u2550\u2550 CCC Configuration Reference \u2550\u2550\u2550\n\nCCC-level features are configured in .opencode/serenity.json.\nBelow are all available configuration sections.\n\n\u2500\u2500 1. cheap-worker.models \u2500\u2500\ncheap-worker\uFF08\u6742\u5DE5\uFF09\u5DE5\u5177\u53EF\u7528\u6A21\u578B\u767D\u540D\u5355\uFF08provider/model \u5217\u8868\uFF09\uFF1B\u672A\u914D\u7F6E\u65F6 cheap-worker \u62A5\u9519\u8981\u6C42\u914D\u7F6E\u3002\n\u7F3A\u7701\u6A21\u578B = models[0]\uFF08\u53EF\u7528 cheap-worker.defaultModel \u6307\u5B9A\uFF0C\u5FC5\u987B \u2208 models\uFF09\u3002\n**CCC \u5E94\u628A\u8BE5\u767D\u540D\u5355\u6307\u5411\u4F4E\u6210\u672C\u6A21\u578B**\u2014\u2014cheap-worker \u662F\u6279\u91CF\u6267\u884C\u901A\u9053\u3002\n\uD83D\uDD34 \u6A21\u578B**\u4E0D\u53EF\u7531\u8C03\u7528\u65B9\u6307\u5B9A**\uFF08\u5DE5\u5177\u65E0 model \u53C2\u6570\uFF09\u21D2 \u672C\u767D\u540D\u5355\u662F\u6A21\u578B\u9009\u62E9\u7684\u552F\u4E00\u6765\u6E90\u3002\n\n Behaviour\uFF082026-10-14\uFF1Abackground \u6A21\u5F0F\u5DF2\u5220\u9664\uFF0C\u53EA\u5269\u524D\u53F0\u59D4\u6D3E\uFF09:\n cheap-worker(task, [label])\uFF1A\u4E00\u6B21\u524D\u53F0\u59D4\u6D3E\uFF08\u5BBF\u4E3B\u59D4\u6D3E\u670D\u52A1 ctx.subagents.start(\"spawn\") +\n agentOptions \u6CE8\u5165\u6A21\u578B\uFF09\u2014\u2014\u4E0D\u5FAA\u73AF\u3001\u4E0D\u6821\u9A8C\u5B8C\u6210\u7801\u3001\u4E0D\u5199\u8FDB\u5EA6\u6587\u4EF6\uFF1B\u8FD4\u56DE\u5B50 agent \u6700\u7EC8\u6587\u672C\u3002\n cheap-worker(jobs=[{task,label?},...])\uFF1A\u5E76\u884C\u6247\u51FA\uFF0C\u4E0A\u9650 10\uFF08\u786C\u7F16\u7801\uFF09\uFF0C\u7ED3\u679C\u4FDD\u6301\u4F20\u5165\u987A\u5E8F\u3002\n \u21D2 **\u65E0 background \u6A21\u5F0F\u3001\u65E0\u8FDB\u5EA6\u6587\u4EF6\u3001\u65E0\u7EED\u8DD1**\uFF08owner 2026-10-14 \u4EE4\u300C\u5220\u9664\u540E\u53F0\u8FD0\u884C\u80FD\u529B\u300D\uFF09\u3002\n\n Old key\uFF08\u517C\u5BB9\uFF09:\n \u8BFB\u4E0D\u5230 \"cheap-worker\" \u65F6**\u56DE\u843D\u5230\u65E7\u952E \"handyman\"**\uFF08\u540C\u5F62\u72B6\uFF1Amodels / defaultModel\uFF09\u3002\n \u65E7\u952E\u91CC\u7684 \"maxRounds\"\uFF0F\"maxParallel\" \u5DF2\u968F background \u9000\u573A\uFF0C\u7559\u7740\u65E0\u5BB3\u4F46\u4E0D\u518D\u751F\u6548\u3002\n\n Config:\n { \"cheap-worker\": { \"models\": [\"provider/model-name\"] } }\n\n Example:\n { \"cheap-worker\": { \"models\": [\"minimax-cn-coding-plan/MiniMax-M3\"], \"defaultModel\": \"minimax-cn-coding-plan/MiniMax-M3\" } }\n\n\u2500\u2500 2. sessionKeeper.threshold / sessionKeeper.sessionMdMaxKB \u2500\u2500\ncognitive-trajectory-assistant\uFF08COGNITIVE-TRAJECTORY-ASSISTANT \u00B7 CHECKPOINT\uFF09\u63D0\u9192\u673A\u5236\u7684\u79EF\u5206\u9608\u503C\uFF08\u975E headless \u4E3B agent\uFF09\u3002\n\u6309\u5DE5\u5177\u8C03\u7528\u52A0\u6743 + \u8017\u65F6\u8BA1\u5206\uFF1B\u8FBE\u5230\u9608\u503C\u6CE8\u5165\u63D0\u9192\uFF0C\u8981\u6C42\u6A21\u578B\u56DE\u590D ACK \u7801\u3002\n\n Config:\n { \"sessionKeeper\": { \"threshold\": 150, \"sessionMdMaxKB\": 200 } }\n\n \u8BA1\u5206\uFF1Awrite/edit = 3\uFF0Ctask = 10\uFF0Cread/grep/glob/msm \u7B49 = 1\uFF0C\u65F6\u95F4 = 1/\u5206\u949F\n \u9ED8\u8BA4\uFF1A150\n\n \u25B8 sessionMdMaxKB\uFF08v1.31.1 \u65B0\u589E\uFF0Cv1.31.2 \u7F3A\u7701 100\u2192200\uFF09\uFF1A**\u6D3B\u8DC3 SESSION.md \u4F53\u79EF\u4E0A\u9650\uFF08KB\uFF0C\u7F3A\u7701 200\uFF1B0 = \u5173\u95ED\uFF09**\u3002\n \u8D85\u8FC7 \u2192 \u6CE8\u5165 [COGNITIVE-TRAJECTORY-ASSISTANT \u00B7 LOGBOOK COMPACTION] \u63D0\u9192\uFF1A\u6682\u505C\u5F53\u524D\u5DE5\u4F5C \u2192\n \u52A0\u8F7D eap\uFF08praxis eap\uFF09\u2192 \u6309 EAP \u5206\u5C42\u9AA8\u67B6\u91CD\u5199 SESSION.md\u3002\u56DB\u6761\u539F\u5219\uFF08ACC \u5185\u5D4C\uFF0C\u968F\u63D0\u9192\u7ED9\u51FA\uFF09\uFF1A\n \u2460 \u4FDD\u7559 EAP \u5206\u5C42\u9AA8\u67B6\uFF08\u4E0D\u538B\u6210\u65F6\u95F4\u6D41\u6C34\u8D26\uFF09\u2461 \u5185\u5BB9\u53EF\u5916\u79FB\u5230 references \u6587\u4EF6\n \uFF08AGENT_SESSIONS/<\u4F1A\u8BDD>/references/*.md\uFF0CSESSION.md \u7559\u94FE\u63A5\uFF09\u2462 \u5141\u8BB8\u6574\u5408/\u5220\u9664\u4E0D\u91CD\u8981\u4E8B\u9879\n \uFF08\u88AB\u53D6\u4EE3\u7684\u51B3\u7B56\u3001\u5DF2\u89E3\u51B3\u95EE\u9898\u3001\u4E2D\u95F4\u6001\uFF09\u2463 \u81EA\u4E3B\u88C1\u91CF\u6743\u5145\u5206\u5141\u8BB8\uFF08\u552F\u4E00\u786C\u8981\u6C42 = \u9AA8\u67B6 +\n \u672A\u51B3\u9879/\u51B3\u7B56\u7406\u7531/\u4E0B\u4E00\u6B65\u4ECD\u53EF\u91CD\u5EFA\uFF09\u3002\u8D85\u9650\u6BCF\u8F6E\u63D0\u9192\uFF1B\u8FDE\u7EED 3 \u8F6E\u672A\u91CD\u5199 \u2192 \u5347\u7EA7\u5F3A\u5236\u8BED\u6C14\uFF1B\n \u6587\u4EF6\u56DE\u5230\u9650\u5185 \u2192 \u81EA\u52A8\u505C\u6B62\uFF08\u81EA\u6108\uFF09\u3002\u8F68\u8FF9\u63D0\u9192**\u4E0D\u673A\u68B0\u963B\u65AD\u5DE5\u4F5C**\uFF08\u4E0E rebuild \u63D0\u9192\u540C\u65CF\uFF09\u3002\n\n\u2500\u2500 3. localstore.gitTrack \u2500\u2500\nlocalstore.json \u7684 git \u7B56\u7565\uFF1Aallow \u53EF\u63D0\u4EA4 / deny \u7981\u63D0\u4EA4\uFF08\u9ED8\u8BA4 deny\uFF09\u3002\ndeny \u65F6\u5199\u5165\u81EA\u52A8\u786E\u4FDD .gitignore \u542B\u8BE5\u6587\u4EF6\uFF08\u7269\u7406\u4FDD\u8BC1\uFF09\uFF0Ccontainer_git commit \u4F1A\u68C0\u67E5\u62D2\u7EDD\u3002\n\n Config:\n { \"localstore\": { \"gitTrack\": \"allow\" } }\n\n\u2500\u2500 4. hooks.autoRestoreSession \u2500\u2500\n\u4F1A\u8BDD\u81EA\u52A8\u6062\u590D\uFF08\u9ED8\u8BA4 true\uFF1B\u53D7 events \u95E8\u63A7\u2014\u2014\u4EC5\u6839\u4F1A\u8BDD + \u5DF2\u6709\u5BF9\u8BDD\u5386\u53F2\u624D\u6062\u590D\uFF09\u3002\n\n Config:\n { \"hooks\": { \"autoRestoreSession\": false } }\n\n\u2500\u2500 5. safeMode\uFF08\u9ED1\u540D\u5355 \uFF0B \u5F00\u542F\u671F\u95F4\u9690\u85CF\u7684\u5DE5\u5177\uFF09\u2500\u2500\nsafe-mode \u7531 WebUI \u5F00\u5173\u63A7\u5236\uFF08\u5199 .serenity-safe-on \u6807\u8BB0\uFF09\uFF1B\u9ED1\u540D\u5355\u8DEF\u5F84\u53D7 guards seam \u62E6\u622A\u3002\n\n \u25B8 blacklist\uFF1A\u5199\u8DEF\u5F84\u9ED1\u540D\u5355\uFF08\u540C\u4E0B Config\uFF09\u3002\n \u25B8 hiddenTools\uFF08v1.51.4\uFF0Cowner 2026-10-09 \u4EE4\uFF09\uFF1A**\u4EC5\u5728\u5B89\u5168\u6A21\u5F0F\u5F00\u542F\u671F\u95F4**\u989D\u5916\u4ECE\u6A21\u578B\u5DE5\u5177\n \u6E05\u5355\u9690\u85CF\u7684\u5DE5\u5177\uFF08ACC \u57FA\u7840\u8868\u6052\u9690 bash\uFF09\u3002\u6253\u5F00 safe-mode \u751F\u6548\u3001**\u5173\u6389\u5373\u5168\u90E8\u6062\u590D**\uFF1B\n \u6539\u672C\u952E**\u70ED\u751F\u6548**\uFF08\u4E0B\u4E00\u4E2A pre-step \u91CD\u7B97\uFF0C\u65E0\u9700\u91CD\u542F\uFF09\u3002\u58F0\u660E\u5728 CCC\uFF08D23\uFF09\u2014\u2014ACC \u4EE3\u7801\u91CC\n \u4E0D\u51FA\u73B0\u4EFB\u4F55\u5177\u4F53\u5DE5\u5177\u540D\u3002\n \u26A0\uFE0F \u5199\u4E00\u4E2A**\u672C CCC \u672A\u6CE8\u518C**\u7684\u540D\u5B57\u4F1A\u8BA9**\u6574\u6B21 restrict \u5931\u8D25**\uFF08DSH \u5951\u7EA6\u9010\u5B57\uFF1A\"unknown\n names \u2026 fail\"\uFF09\u21D2 \u6B64\u65F6**\u9000\u5316\u4E3A\u53EA\u9690\u85CF\u57FA\u7840\u8868**\u5E76\u5728\u65E5\u5FD7\u54CD\u4EAE\u62A5\u9519\uFF08\u7EDD\u4E0D\u56E0\u4E00\u4E2A\u9519\u540D\u4E22\u6389\n safe-mode \u7684\u6838\u5FC3\u9690\u85CF\uFF09\u3002\u8BCA\u65AD\uFF1A`AGENT_SESSIONS/.restrict-diag.json` \u7684 `denyByKey`\u3002\n \u26A0\uFE0F \u9690\u85CF = **\u4ECE schema \u79FB\u9664**\uFF08agent \u6839\u672C\u770B\u4E0D\u5230\u8BE5\u5DE5\u5177\uFF09\u21D2 \u522B\u628A skill/\u6587\u6863\u8FD8\u5728\u6559\u7684\u5DE5\u5177\u5199\u8FDB\u6765\u3002\n\n Config:\n { \"safeMode\": { \"blacklist\": [\".secrets/\"], \"hiddenTools\": [\"workflow\", \"job_kill\"] } }\n\n\u2500\u2500 6. \u8F68\u8FF9\u7EA6\u675F.roles\uFF08F4 \u8BA4\u77E5\u5B50\u96C6\u89D2\u8272\uFF09\u2500\u2500\n\u8F68\u8FF9\u7EA6\u675F\u89D2\u8272 = \u5168\u77E5\u5168\u80FD cognitive trajectory \u7684\u4EFB\u610F\u5B50\u96C6\uFF08CCC \u5B9A\u4E49\uFF09\u3002\u6BCF\u89D2\u8272\u72EC\u7ACB\u6A21\u578B + \u53CC\u767D\u540D\u5355\n\uFF08MSM \u767D\u540D\u5355 msms[] \u4E0E\u975E MSM \u5DE5\u5177\u767D\u540D\u5355 tools[]\uFF0C\u767D\u540D\u5355\u5916\u5168\u9690\u85CF\uFF1Bskill \u52A0\u8F7D\u6052\u53EF\u7528\uFF09\u3002\ncognitive trajectory \u7EAA\u5F8B\u5B50\u96C6\uFF08session/keeper/rebuild \u53C2\u4E0E\u9879\uFF09\u9ED8\u8BA4\u5168\u5173 = \u5B8C\u5168\u72EC\u7ACB\u3002\nsystemPrompt \u5185\u8054 \u6216 systemPromptFile\uFF08.md \u5F15\u7528\uFF0C\u63A8\u8350\uFF09\u2014\u2014\u89D2\u8272\u4F1A\u8BDD\u7684\u5B8C\u6574\u4EBA\u683C/\u8FB9\u754C\u63D0\u793A\u8BCD\u3002\nvalidate \u6821\u9A8C / apply \u751F\u6548 / list \u67E5\u770B\uFF1Acontainer_admin config <guide|validate|apply|list>\uFF08\u539F role \u57DF\u5DF2\u5E76\u5165 config\uFF0C\u65E7\u540D\u4F5C\u8FC7\u6E21\u522B\u540D\u4ECD\u53EF\u7528\uFF09\u3002\n\n Config:\n { \"\u8F68\u8FF9\u7EA6\u675F\": { \"roles\": {\n \"qa\": {\n \"model\": \"provider/model\",\n \"msms\": [\"web-search\", \"vlm-describe\"],\n \"tools\": [\"read\", \"grep\", \"glob\"],\n \"systemPromptFile\": \".opencode/skiff/qa.md\"\n } } } }\n\n\u2500\u2500 7. cognitive_trajectory\uFF08\u8F68\u8FF9 + \u5524\u9192\u6CE8\u518C\u8868\uFF0CD58\uFF09\u2500\u2500\nCCC \u7684\u4E00\u6761 cognitive trajectory = \u6301\u4E45\u8EAB\u4F53\uFF08SESSION.md\uFF09+ \u65F6\u95F4\u8F74\uFF08AGENT_SESSIONS/ \u76EE\u5F55 + \u5524\u9192\u6CE8\u518C\u8868\uFF09\u3002\n\u4E00\u4E2A CCC \u5185\u53EF\u591A\u6761\u5E76\u884C\uFF1B\u6761\u76EE\u5168\u90E8\u7531\u4EBA\u7C7B/agent \u663E\u5F0F\u767B\u8BB0\u3002\n\u26A0\uFE0F ACC \u4E0D\u518D\u63D0\u4F9B**\u5468\u671F\u81EA\u5524\u9192**\uFF08\u539F autopilot\uFF0C2026-09-15 \u6574\u6BB5\u9000\u573A\uFF1A\u673A\u5236/\u65F6\u949F/container_admin autopilot\n\u57DF/\u9762\u677F\u533A\u5757\u4E00\u5E76\u5220\u9664\uFF09\u3002\u81EA\u4E3B\u5DE1\u822A\u6539\u7531 CCC \u81EA\u5DF1\u9A71\u52A8\uFF08home-serenity \u4FA7 msm autopilot-round \u6BCF\u8F6E\u81EA\u6392\u4E0B\u4E00\u8F6E\uFF0C\n\u771F\u76F8\u6E90 = S151 SESSION.md \u00A71/\u00A71b/\u00A71c\uFF09\u3002**\u672C\u8F6E\u7684 cognitiveTrajectory.autopilot \u914D\u7F6E\u6BB5\u4FDD\u7559**\uFF08\u89C1\u4E0B\u8868\uFF09\u2014\u2014\n\u5B83\u73B0\u7531 **CCC \u4FA7\u811A\u672C**\u8BFB\u53D6\uFF0CACC \u4E0D\u518D\u6D88\u8D39\u8BE5\u6BB5\u3002\n\u5524\u9192\u6CE8\u518C\u8868\uFF08cognitive_trajectory send-later\uFF09\uFF1A\u5524\u9192 = \u672A\u6765\u65F6\u523B + \u4E00\u6761 message\uFF0C\u53EF\u5524\u9192\u81EA\u5DF1\u6216\u522B\u7684 cognitive trajectory\uFF1B\n\u843D\u70B9 AGENT_SESSIONS/wake-registry.json\uFF0C\u4E2D\u5FC3\u8C03\u5EA6\u5668\u5230\u70B9\u6295\u9012\uFF08fire-and-forget\uFF1B\u65E0\u56DE\u6267\u3001\u65E0\u56DE\u6536\uFF09\u3002\n\u8FD0\u884C\u6001\u8BCA\u65AD\uFF08ACC \u8D1F\u8D23\u4EBA\u4E13\u7528\uFF09\uFF1Aacc-diag\uFF08\u2460 live \u8FD0\u884C\u6001 / \u2460b \u5524\u9192\u65F6\u949F / \u2462 \u5524\u9192\u6CE8\u518C\u8868\uFF09\u3002\n\n\u25B8 cognitiveTrajectory.skills\uFF08v1.44.0\uFF0C**CCC \u7EA7 skill \u4F9B\u7ED9**\uFF1Bowner \u4EE4 2026-09-20\u300C\u8981\u6C42\u5B9E\u73B0\u6211\u7684\u8BC9\u6C42\u2026\u2026\n \u6CE8\u5165\u662F\u52A8\u6001\u6CE8\u5165\u5C31\u884C\uFF1Bcreate \u5148\u4E0D\u89E6\u53D1\u5427\uFF1B**\u8F68\u8FF9\u7EA6\u675F\u4E5F\u652F\u6301**\u300D\uFF09\uFF1A\n **\u672C CCC \u7684\u6BCF\u6761\u8F68\u8FF9\u90FD\u5E26\u8FD9\u4E9B skill**\u2014\u2014\u58F0\u660E\u7684 skill \u5168\u6587\u5728\u8BE5\u8F68\u8FF9**\u88AB\u7ED1\u5B9A\u671F\u95F4**\u6CE8\u5165\u7CFB\u7EDF\u63D0\u793A\u8BCD\n \uFF08**\u52A8\u6001\u6CE8\u5165**\uFF1A\u6BCF\u8BF7\u6C42\u91CD\u65B0\u6C42\u503C\u3001\u4E0D\u7F13\u5B58 \u21D2 \u6539\u914D\u7F6E\u6216\u6539 frontmatter **\u5373\u65F6\u751F\u6548**\uFF0C\u65E0\u9700\u91CD\u65B0 use\u3001\u65E0\u9700\u91CD\u542F\uFF09\u3002\n \u4E24\u6761\u58F0\u660E\u6765\u6E90**\u5E76\u96C6**\uFF08\u4E0D\u662F\u4E8C\u9009\u4E00\uFF09\uFF1A\u672C\u952E **cognitiveTrajectory.skills**\uFF08\u5BB9\u5668\u7ED9\u7684\u5E95\u5EA7\uFF0C**\u5728\u524D**\uFF09\n \uFF0B \u8F68\u8FF9\u81EA\u5DF1 SESSION.md \u9876\u90E8 frontmatter \u7684 skills:\uFF08\u8FD9\u6761\u8F68\u8FF9\u989D\u5916\u7684\uFF0C**\u8FFD\u52A0**\uFF1B\u540C\u540D\u53BB\u91CD\uFF09\u3002\n \u2705 **\u542B \u8F68\u8FF9\u7EA6\u675F\u89D2\u8272\u4F1A\u8BDD**\uFF08\u65C1\u8DEF\u7684\u662F ACC \u8EAB\u4EFD\u4E0E\u7EAA\u5F8B\uFF1Bskill \u662F\"\u5DE5\u4F5C\u8D44\u6599\"\uFF0C\u7167\u7ED9\uFF09\u3002\n \u5B88\u536B\uFF1A\u540D\u5B57\u5148\u8FC7\u5B89\u5168\u6821\u9A8C\u624D\u7528\u4E8E\u62FC\u8DEF\u5F84\uFF08\u9632\u7A7F\u8D8A\uFF09\uFF5C**\u5408\u5E76\u540E**\u7EDF\u4E00 32 KB \u4E0A\u9650\u622A\u65AD\uFF5C\u627E\u4E0D\u5230\u54CD\u4EAE\u5199 [\u7F3A\u5931]\u3002\n \u26A0\uFE0F \u4E0E create **\u65E0\u5173**\uFF08create \u523B\u610F\u4E0D\u593A\u7ED1\u5B9A\uFF0CU6\uFF09\u21D2 \u6CE8\u5165\u7684\u95E8\u662F\"**\u5B58\u5728\u7ED1\u5B9A**\"\uFF08cognitive_trajectory use\uFF09\u3002\n \u5931\u8D25\u8BED\u4E49\uFF1A\u672A\u914D\u7F6E / \u5B57\u6BB5\u7F3A\u5931 / \u914D\u7F6E\u635F\u574F \u21D2 **\u7A7A\u6570\u7EC4**\uFF08= \u65E0 CCC \u7EA7\u4F9B\u7ED9\uFF1B\u8F68\u8FF9\u7EA7\u58F0\u660E\u7167\u65E7\u751F\u6548\uFF09\u3002\n \u5F52\u5C5E\uFF08D23\uFF09\uFF1A**\u673A\u5236\u5728 ACC**\uFF08\u8BFB\u53D6 + \u5408\u5E76 + \u6CE8\u5165 + \u5B88\u536B\uFF09\uFF0C**\u58F0\u660E\u5728 CCC**\uFF08\u672C\u952E\uFF09\u3002\n\n Config:\n { \"cognitiveTrajectory\": {\n \"skills\": [\"acc-session\", \"cce\"], // v1.44.0\uFF1A\u672C CCC \u7684\u6BCF\u6761\u8F68\u8FF9\u90FD\u5E26\uFF08\u542B \u8F68\u8FF9\u7EA6\u675F\u4F1A\u8BDD\uFF09\n \"autopilot\": { // \u539F autopilotTrajectory \u6BB5\uFF0C\u5B57\u6BB5\u4E0D\u53D8\uFF08\u65E7\u952E\u4ECD\u56DE\u9000\u8BFB\uFF09\n \"enabled\": true,\n \"intervalHours\": 2,\n \"session\": \"S151\",\n \"biasProvider\": \"autopilot-bias.ts\",\n \"topPrompt\": \"\u672C\u8F68\u8FF9\u6838\u5FC3\u76EE\u6807/\u7EAA\u5F8B/\u8D28\u91CF\u8981\u6C42\uFF08CCC \u81EA\u586B\uFF0C\u9632\u6F02\u79FB\uFF09\",\n \"avoidWakeHours\": { \"start\": 8, \"end\": 18 }\n } } }\n\n\u2500\u2500 8. weixin\uFF08\u5FAE\u4FE1\u6865 F4c-3\uFF0C\u542B\u6D88\u606F\u8BB0\u5F55 hook\uFF09\u2500\u2500\nCCC \u7EA7\u5FAE\u4FE1\u4E2A\u4EBA\u53F7\u63A5\u5165\uFF08iLink \u534F\u8BAE\uFF09\uFF1Adsh \u4E00\u8FDB\u7A0B\u591A CCC\uFF0C\u6BCF CCC \u72EC\u7ACB\u5BF9\u63A5\u5FAE\u4FE1\u6865\u3002\n\u8D26\u53F7/\u8DEF\u7531/\u5F00\u5173\u5728\u6B64\u6587\u4EF6\uFF1B**bot_token \u51ED\u636E\u5728 CCC localstore credential scope**\n\uFF08\u626B\u7801\u7ED1\u5B9A\u540E\u81EA\u52A8\u5199\u5165\uFF0C\u6C38\u4E0D\u8FDB git \u660E\u6587\u9762\uFF09\u3002\n\u8DEF\u7531 user \u2192 role\uFF1Aexact \u4F18\u5148\uFF0C* \u901A\u914D\u515C\u5E95\uFF1Brole \u5FC5\u987B \u2208 \u8BE5 CCC \u8F68\u8FF9\u7EA6\u675F.roles\u3002\n\u9762\u677F\uFF08WebUI \u8BBE\u7F6E \u2192 \u5FAE\u4FE1\u6865\uFF09\u53EF\u626B\u7801\u7ED1\u5B9A/\u79FB\u9664\u8D26\u53F7/\u7F16\u8F91\u8DEF\u7531\uFF1Bmsm(\"weixin-doctor\", [\"status\"|\"diag\"|\"verify\"|\"guide\"]) \u6392\u67E5 + \u5927\u800C\u5168\u6307\u5357\u3002\u51ED\u636E\u4E3B\u52A8\u67E5\u770B\uFF1Alocalstore get WEIXIN_<ACCOUNT>_TOKEN\u3002\n \u25B8 \u4E3B\u52A8\u53D1\u9001\uFF08v1.31.0\uFF1A**ACC \u5DE5\u5177 im-bridge**\uFF09\uFF1A\u8C03\n im-bridge({channel:\"weixin\", action:\"send\", user:\"<\u522B\u540D|id>\", text:\"<\u6587\u672C>\"}) \u7ED9\u7528\u6237\u53D1\u6D88\u606F\u2014\u2014\n **\u5DE5\u5177\u53EA\u80FD\u64CD\u4F5C\u672C\u4F1A\u8BDD CCC**\uFF08\u65E0 ccc \u53C2\u6570\uFF0C\u9632\u8BEF\u53D1\u4ED6\u5BB9\u5668\uFF09\u2192 weixin-bridge.sendProactiveText \u2192\n \u6210\u529F\u540E\u89E6\u53D1 outgoing hook\uFF08source=\"proactive\"\uFF09\u3002\u6587\u4EF6\u7528 action:\"send-file\" + file:\"<CCC \u5185\u8DEF\u5F84>\"\n \uFF08\u9003\u9038/\u7F3A\u5931/\u8D85 20MB \u62D2\u7EDD\uFF09+ \u53EF\u9009 caption\u3002**\u53EF\u89C1\u6027**\uFF1A\u672C CCC \u914D\u7F6E\u4E86 IM \u901A\u9053\n \uFF08weixin.enabled=true\uFF09\u624D\u51FA\u73B0\u5728\u6A21\u578B\u5DE5\u5177\u6E05\u5355\u91CC\uFF1B\u672A\u914D\u7F6E \u2192 \u7531 guards \u9010 agent\n tools.restrict({deny:['im-bridge']}) \u79FB\u9664\uFF08\u4E0D\u662F\"\u770B\u5F97\u5230\u4F46\u88AB\u62D2\"\uFF09\u3002\u8F68\u8FF9\u7EA6\u675F\u89D2\u8272\u53E6\u9700\u5728\n roles.<role>.tools \u767D\u540D\u5355\u5217\u51FA im-bridge\u3002\n \u5386\u53F2\uFF08v1.30.9~v1.30.x\uFF09\uFF1ACCC \u4FA7 MSM weixin-send\uFF08\u8D70 loopback HTTP \u5165\u53E3 3082\uFF09\u2014\u2014\n v1.31.0 \u5DF2\u9000\u5F79\uFF08\u811A\u672C\u5220\u9664 + \u6CE8\u518C\u8868\u6CE8\u9500\uFF09\uFF1B3082 \u5165\u53E3\u4FDD\u7559\u7ED9**\u975E agent \u8C03\u7528\u8005**\u3002\n\n \u25B8 weixin.autoReplyWithLastMessage\uFF08v1.30.10\uFF0C\u5173\u95ED\u6865\u7684\u81EA\u52A8\u8F93\u51FA\uFF09\uFF1A\n \u7F3A\u7701 true = \u73B0\u72B6\uFF1A\u6865\u5728 agent \u4E00\u8F6E\u7ED3\u675F\u540E\u628A**\u6700\u7EC8 assistant \u6587\u672C**\u81EA\u52A8\u56DE\u53D1\u7528\u6237\uFF08source=\"reply\"\uFF09\u3002\n \u663E\u5F0F false = \u5173\u95ED\uFF1A\u6865**\u4E0D\u518D\u8F6C\u53D1\u6700\u7EC8\u6587\u672C**\uFF0C\u8F93\u51FA\u6743\u4EA4\u7ED9 agent\u2014\u2014\u6BCF\u8F6E\u5728\u7528\u6237\u6D88\u606F**\u672B\u5C3E**\u8FFD\u52A0\n **\u673A\u5236\u6807\u8BB0** [serenity:weixin-manual-output] + \u4E00\u884C\u5DF2\u586B\u597D\u53C2\u6570\u7684 im-bridge \u8C03\u7528\n \uFF08\u8D26\u53F7/\u7528\u6237 id\uFF09\uFF0Cagent \u81EA\u5DF1\u51B3\u5B9A\u53D1\u4EC0\u4E48\u3001\u53D1\u51E0\u6761\uFF08\u5168\u90E8\u8BB0 source=\"proactive\"\uFF09\u3002\n **ACC \u53EA\u7ED9\u673A\u5236\u4E0E\u6570\u636E\uFF0C\u7EAA\u5F8B\u63AA\u8F9E\u5F52 CCC**\uFF08v1.30.16\uFF09\uFF1A\u600E\u4E48\u5199/\u5FC5\u987B\u600E\u4E48\u505A/\u540E\u679C\u662F\u4EC0\u4E48\u5199\u5728\n CCC \u89D2\u8272\u63D0\u793A\u8BCD\u6587\u4EF6\u91CC\uFF08\u5982 .opencode/skiff/<role>.md\uFF09\uFF0C\u53EF\u70ED\u6539\uFF08v1.30.15 \u8D77\u89D2\u8272\u63D0\u793A\u8BCD\u70ED\u91CD\u8F7D\uFF09\u3002\n \u673A\u68B0\u95F8\u95E8\uFF08v1.30.16\uFF09\uFF1A\u672C\u8F6E turn \u7ED3\u675F\u4ECD\u672A\u6210\u529F\u8C03\u7528 im-bridge\uFF08send / send-file\uFF1B\u517C\u5BB9\u65E7\n msm(\"weixin-send\") \u5F62\u6001\uFF09\u2192 agent \u88AB\u6253\u56DE\uFF08\u22642 \u6B21\uFF0C\u63D0\u793A = \u6807\u8BB0 + \u4E8B\u5B9E\uFF09\uFF1B\u8FBE\u4E0A\u9650\u653E\u5F03\u5E76\u54CD\u4EAE\u544A\u8B66\u3002\n \u5931\u8D25\u8C03\u7528\u4E0D\u7B97\u5DF2\u9001\u8FBE\u3002\n \u8BED\u4E49\u8FB9\u754C\uFF08\u7528\u6237\u62CD\u677F\uFF09\uFF1A\u53EA\u5173\u6700\u7EC8\u6587\u672C\uFF1B\u7CFB\u7EDF\u7C7B\u6D88\u606F\uFF08\u65B0\u5BF9\u8BDD\u901A\u77E5 / \u8BED\u97F3\u65E0\u6CD5\u89E3\u6790\u63D0\u793A\uFF09\u4FDD\u7559\uFF1B\n typing \u6307\u793A\u4E0E incoming hook \u4E0D\u53D7\u5F71\u54CD\u3002\n\n \u25B8 weixin.fallbackOnNoSend\uFF08v1.30.17\uFF0C\u624B\u52A8\u6A21\u5F0F\u7684**\u515C\u5E95**\uFF1B\u7F3A\u7701 false\uFF09\uFF1A\n \u4EC5\u5728 autoReplyWithLastMessage=false \u65F6\u751F\u6548\u3002true \u2192 \u4E00\u8F6E\u7ED3\u675F\u65F6\u82E5 agent **\u4E00\u6B21\u90FD\u6CA1\u6210\u529F**\n \u8C03\u7528\u8F93\u51FA\u5DE5\u5177\uFF08\u95F8\u95E8\u6253\u56DE\u7528\u5C3D\uFF09\uFF0C\u6865\u628A\u8BE5\u8F6E\u6700\u7EC8\u6587\u672C\u8F6C\u53D1\u7ED9\u7528\u6237\uFF08\u8BB0\u5F55 source=\"reply-fallback\"\uFF0C\n \u65E5\u5FD7\u7559\u54CD\u4EAE\u544A\u8B66\uFF09\u2014\u2014\u4FDD\u8BC1\"\u4E0D\u4E22\u6D88\u606F\"\u3002agent \u81EA\u5DF1\u53D1\u8FC7 \u2192 \u4E0D\u515C\u5E95\uFF08\u8F93\u51FA\u6743\u4ECD\u5728 agent\uFF09\u3002\n \u4E3A\u4EC0\u4E48\u9700\u8981\uFF08\u5B9E\u8BC1\uFF09\uFF1Av1.30.16 \u95F8\u95E8\u4F1A\u6253\u56DE \u22642 \u6B21\uFF0C\u4F46\u5B9E\u6D4B\u67D0\u6A21\u578B\u5728**\u5BD2\u6684\u7C7B\u6D88\u606F**\u4E0A\u8FDE\u7EED 4 \u8F6E\u3001\n \u8DE8 3 \u7248 CCC \u63D0\u793A\u8BCD\u4ECD\u4E0D\u8C03\u5DE5\u5177 \u2192 \u6253\u56DE\u7528\u5C3D\u540E\u7528\u6237\u4EC0\u4E48\u90FD\u6536\u4E0D\u5230\uFF1B\u63D0\u793A\u8BCD\u4E0E\u95F8\u95E8\u5747\u5DF2\u6392\u9664\u3002\n \u4EE3\u4EF7\uFF08\u663E\u5F0F\uFF09\uFF1A\u89D2\u8272\u5931\u53BB\"\u6545\u610F\u9759\u9ED8\"\u80FD\u529B\uFF08\u5B83\u603B\u4F1A\u4EA7\u51FA\u4E00\u6BB5\u6700\u7EC8\u6587\u672C\uFF09\u2192 \u9700\u4E25\u683C\u9759\u9ED8\u7684\u89D2\u8272\u4FDD\u6301\u7F3A\u7701\u3002\n \u4E09\u6001\uFF1A\u2460 autoReplyWithLastMessage=true\uFF08\u7F3A\u7701\uFF09\u6865\u603B\u662F\u56DE\u53D1\uFF1B\u2461 =false + fallbackOnNoSend=true\n = agent \u4F18\u5148\u3001\u6865\u515C\u5E95\uFF08\u63A8\u8350\uFF09\uFF1B\u2462 \u4E24\u8005\u7686 false\uFF08\u7F3A\u7701\uFF09= \u4E25\u683C\u9759\u9ED8\uFF08v1.30.10 \u8BED\u4E49\uFF09\u3002\n \u26A0\uFE0F \u515C\u5E95\u53EA\u5728**\u95F8\u95E8\u88C5\u914D\u6210\u529F**\u65F6\u751F\u6548\uFF08\u672A\u88C5\u914D\u5219\u65E0\u6CD5\u5224\u5B9A\u662F\u5426\u53D1\u9001\u8FC7 \u2192 \u4E0D\u5192\u91CD\u590D\u53D1\u9001\u98CE\u9669\uFF09\u3002\n\n Config:\n { \"weixin\": {\n \"enabled\": true,\n \"hook\": \"scripts/weixin-message-hook.ts\",\n \"autoReplyWithLastMessage\": true,\n \"fallbackOnNoSend\": false,\n \"accounts\": [{ \"accountId\": \"wechat-1\", \"name\": \"\u5BB6\u5EAD\u52A9\u624B\", \"enabled\": true }],\n \"routes\": [{ \"user\": \"*\", \"role\": \"my-role\" }]\n } }\n\n \u25B8 weixin.hook\uFF08\u6D88\u606F\u8BB0\u5F55 hook\uFF0Cv1.27.13\uFF09\uFF1A\n \u5FAE\u4FE1\u6865\u6BCF\u6536/\u53D1\u4E00\u6761\u6D88\u606F\u89E6\u53D1\u4E00\u6B21 CCC \u81EA\u5199\u811A\u672C\uFF0C\u7531 CCC \u81EA\u884C\u6301\u4E45\u5316\u4FDD\u5B58\uFF08\u5B58\u54EA/\u5B58\u6210\u4EC0\u4E48\n /\u662F\u5426\u5165\u5E93\u5168\u5F52 CCC\u2014\u2014ACC \u4E0D\u7ED1\u5B9A\u5B58\u50A8\uFF09\u3002\u672A\u914D\u7F6E hook \u2192 \u96F6\u53D8\u5316\uFF08\u4E0D\u89E6\u53D1\uFF09\u3002\n\n \u89E6\u53D1\uFF08\u53CC\u5411\uFF09\uFF1A\n incoming = \u7528\u6237 \u2192 bot\uFF1A\u8DEF\u7531\u547D\u4E2D\u540E\u3001\u5A92\u4F53\u843D\u76D8\u540E\u89E6\u53D1\uFF08\u6587\u672C\u542B\u8BED\u97F3\u8F6C\u5199\uFF1B\u5A92\u4F53\u5E26\u843D\u76D8 relPath\uFF09\n outgoing = bot \u2192 \u7528\u6237\uFF1A\u53D1\u9001\u6210\u529F\u540E\u89E6\u53D1\uFF08reply = \u7528\u6237\u5B9E\u9645\u6536\u5230\u7684\u7EAF\u6587\u672C\uFF0C\u5DF2\u5265\u79BB think\uFF09\n \u00B7 source=\"reply\"\uFF08\u7F3A\u7701\uFF09= \u56DE\u590D\u7528\u6237\u6D88\u606F\uFF1Bsource=\"proactive\"\uFF08v1.30.9\uFF09= bot \u4E3B\u52A8\u53D1\u8D77\n \uFF08CCC \u7ECF im-bridge \u5DE5\u5177\uFF08v1.31.0\uFF1B\u65E7 weixin-send MSM \u5DF2\u9000\u5F79\uFF09\u2192 sendProactiveText\uFF09\uFF1B\n source=\"reply-fallback\"\uFF08v1.30.17\uFF09= \u624B\u52A8\u6A21\u5F0F\u4E0B agent \u672C\u8F6E\u672A\u53D1\u9001 \u2192 \u6865\u515C\u5E95\u8F6C\u53D1\u6700\u7EC8\u6587\u672C\n \u00B7 file\uFF08\u4EC5 send-file \u8865\u8BB0\uFF09\uFF1A{ \"name\": \"\u62A5\u544A.pdf\", \"size\": 12345, \"caption\": \"\u53EF\u9009\" }\n\n \u811A\u672C\u7EA6\u5B9A\uFF08\u4E8B\u4EF6 JSON \u5355\u884C\u7ECF stdin \u4F20\u5165\uFF1Bbun \u4F18\u5148 node \u515C\u5E95\uFF09\uFF1A\n #!/usr/bin/env bun \u6216 node script.js \u2014\u2014 \u8BFB process.stdin \u6574\u6BB5 JSON.parse\n const ev = JSON.parse(await new Response(process.stdin).text())\n ev.event === 'incoming' | 'outgoing'\n\n \u4E8B\u4EF6 schema\uFF08**\u4E0D\u542B\u4EFB\u4F55\u4F1A\u8BDD\u51ED\u636E**\u2014\u2014context_token/bot_token/token/aes_key \u5747\u4E0D\u51FA\u73B0\uFF09\uFF1A\n { \"event\": \"incoming\", \"ts\": 1788359941488, \"cccRoot\": \"/path/ccc\",\n \"accountId\": \"wechat-1\", \"userId\": \"u1@im.wechat\",\n \"sessionId\": \"skiff-weixin-xxx\", \"role\": \"my-role\",\n \"message\": { \"text\": \"\u4F60\u597D\", \"media\": [{ \"kind\": \"image\", \"relPath\": \"_tmp/weixin-inbound/<hash>/img_x.jpg\" }] } }\n { \"event\": \"outgoing\", \"ts\": ..., \"cccRoot\": ..., \"accountId\": ...,\n \"userId\": ..., \"sessionId\": ..., \"role\": ...,\n \"reply\": \"\u5DF2\u8BB0\u5F55\uFF08\u7EAF\u6587\u672C\uFF09\", \"source\": \"reply\" | \"proactive\" | \"reply-fallback\" }\n\n \u793A\u4F8B\u811A\u672C\uFF08\u8FFD\u52A0\u5230\u6309\u65E5\u6587\u4EF6\u2014\u2014\u6301\u4E45\u5316\u5F52 CCC \u81EA\u9009\uFF1A\u6587\u4EF6/DB/\u8FDC\u7AEF\u5747\u53EF\uFF09\uFF1A\n const fs = require('node:fs'); const p = '/path/ccc/AGENT_SESSIONS/_weixin-log.jsonl';\n fs.appendFileSync(p, JSON.stringify(ev) + '\\n');\n\n \u6267\u884C\u8BED\u4E49\uFF08\u65C1\u8DEF\u5BB9\u5FCD\uFF09\uFF1A\u5F02\u6B65 fire-and-forget + 15s \u8D85\u65F6 kill + \u5931\u8D25\u4EC5\u65E5\u5FD7\u2014\u2014\n \u5FAE\u4FE1\u6865\u6D88\u606F\u5904\u7406/\u56DE\u590D\u4E0D\u53D7 hook \u5F71\u54CD\uFF1B\u811A\u672C\u987B\u5728 CCC \u6839\u5185\uFF08\u8DEF\u5F84\u9003\u9038\u62D2\u7EDD\uFF09\u3002\n \u5A92\u4F53 relPath \u6307\u5411 _tmp/weixin-inbound/\uFF08\u4E34\u65F6\u76EE\u5F55\uFF09\u2014\u2014\u9700\u6301\u4E45\u4FDD\u5B58\u5A92\u4F53\u6587\u4EF6\u8BF7\u81EA\u884C copy\u3002\n\n\u2500\u2500 9. exclusiveTools\uFF08\u4E13\u5C5E\u5DE5\u5177\u58F0\u660E\uFF0Cv1.33\uFF09\u2500\u2500\n**ACC \u6CE8\u518C\u4F46\u9ED8\u8BA4\u5BF9\u6240\u6709 CCC \u9690\u85CF**\u7684\u5DE5\u5177\uFF0C\u53EA\u6709\u5728\u81EA\u5DF1\u8FD9\u91CC**\u70B9\u540D**\u7684 CCC \u53EF\u89C1\u3002\n\u8FD9\u662F\u901A\u7528\u673A\u5236\uFF08\u4EFB\u4F55\u5DE5\u5177\u540D\u7686\u53EF\uFF09\uFF0C\u5224\u636E\u7531 CCC \u58F0\u660E\u2014\u2014ACC \u4EE3\u7801\u91CC\u4E0D\u51FA\u73B0\u4EFB\u4F55\u5177\u4F53 CCC \u7684\u540D\u5B57\u3002\n\u5F53\u524D\u4E13\u5C5E\u5DE5\u5177\uFF1Aacc-diag\uFF08\u8FD0\u884C\u6001\u8BCA\u65AD\u2014\u2014live \u4F1A\u8BDD / agent \u5B9A\u4F4D / \u5524\u9192\u6CE8\u518C\u8868 / \u5524\u8D77\u6761\u4EF6\u94FE\uFF09\u3002\n\n \u25B8 \u53EF\u89C1\u6027\u8BED\u4E49\uFF1A\u672A\u58F0\u660E \u21D2 \u7531 guards \u9010 agent tools.restrict({deny:[tool]}) \u4ECE**\u6A21\u578B\u5DE5\u5177\u6E05\u5355\u79FB\u9664**\n \uFF08\u4E0D\u662F\"\u770B\u5F97\u5230\u4F46\u88AB\u62D2\"\uFF09\u3002\u914D\u7F6E\u70ED\u66F4\u65B0\uFF1A\u6539\u672C\u6587\u4EF6\u5373\u65F6\u751F\u6548\uFF08\u65E0\u9700\u91CD\u542F\uFF09\u3002\n \u25B8 \u5931\u8D25\u65B9\u5411 **fail-closed**\uFF1A\u672A\u914D\u7F6E / \u5B57\u6BB5\u7F3A\u5931 / \u914D\u7F6E\u635F\u574F\uFF08JSON \u574F\uFF09\u21D2 \u4E00\u5F8B\u6309\"\u672A\u58F0\u660E\"\u5904\u7406\n \uFF08\u4E13\u5C5E\u5DE5\u5177\u4FDD\u6301\u9690\u85CF\uFF1B\u914D\u7F6E\u635F\u574F\u672C\u8EAB\u53E6\u6709\u54CD\u4EAE\u544A\u8B66\uFF09\u3002\u4E0E im-bridge \u76F8\u53CD\u2014\u2014\u9690\u85CF\u4E00\u4E2A**\u5DF2\u5728\u4F7F\u7528**\n \u7684\u901A\u9053\u624D\u4F1A\u9759\u9ED8\u635F\u5BB3\u80FD\u529B\uFF0C\u800C\u4E13\u5C5E\u5DE5\u5177\u7684\u9ED8\u8BA4\u6001\u672C\u5C31\u662F\u9690\u85CF\u3002\n \u25B8 \u914D\u7F6E\u635F\u574F\u7684\u54CD\u4EAE\u544A\u8B66\u53EA\u51FA\u73B0\u4E00\u6B21\uFF08\u6BCF\u8DEF\u5F84\uFF09\uFF0Cdashboard health \u540C\u6837\u80FD\u770B\u5230\u3002\n\n Config:\n { \"exclusiveTools\": [\"acc-diag\"] }\n";
|
|
11
18
|
interface MsmFlag {
|
|
12
19
|
name: string;
|
|
13
20
|
type?: string;
|