@shgroup/dsh-serenity-hooks 1.104.0 → 1.107.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 +4 -3
- package/dsh.plugin.json +2 -3
- package/lib/{profile-Dpg3wYO5.js → bind-file-B0TuOP89.js} +1 -333
- package/lib/{ccc-B-h_A7uc.js → ccc-BmpE3cQz.js} +64 -12
- package/lib/{ccc-roots-BIdg0EyM.js → ccc-roots-DPMwBywc.js} +15 -3
- package/lib/{channels-BItMJUO8.js → channels-Dty_NIl_.js} +2 -146
- package/lib/contract-BiNzzd77.js +2197 -0
- package/lib/host/access.d.ts +30 -0
- package/lib/index.js +176 -6355
- package/lib/invariant.js +1 -2
- package/lib/kernel/ccc.d.ts +60 -13
- package/lib/kernel/invariant.d.ts +2 -2
- package/lib/message-source-BTIe2cVO.js +254 -0
- package/lib/observation-BWpkA865.js +210 -0
- package/lib/profile-BjBn_-be.js +336 -0
- package/lib/{route-CmEoKp9w.js → route-reyv8qcB.js} +2 -2
- package/lib/rules-BLkYTPUy.js +261 -0
- package/lib/scheduler-B0pB9mxI.js +3603 -0
- package/lib/seams/guards.d.ts +0 -4
- package/lib/{service-Cndtf7q4.js → service-Z3aSR1cn.js} +1 -1
- package/lib/service-xvjwsX3p.js +249 -0
- package/lib/{session-CaNqSHVB.js → session-BlgUdKH4.js} +55 -6
- package/lib/settings-DY4_DYYY.js +145 -0
- package/lib/subscriptions-CyrfNpcG.js +273 -0
- package/lib/tools/diag/service.d.ts +74 -24
- package/lib/tools/kit/service.d.ts +1 -1
- package/lib/tools/msm/service.d.ts +2 -2
- package/lib/trajectory/subscriptions.d.ts +170 -0
- package/package.json +2 -2
- package/lib/message-source-CKJPJCzc.js +0 -513
- package/lib/tools/diag/index.d.ts +0 -25
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ my-workspace/
|
|
|
60
60
|
|
|
61
61
|
## 3 装完多了什么
|
|
62
62
|
|
|
63
|
-
### 3.1
|
|
63
|
+
### 3.1 十二个工具(其中两个按条件出现)
|
|
64
64
|
|
|
65
65
|
> 这份清单**只在这里**(用户视角:能做什么)。**契约语义**(每个动作必须怎样)在标准的 §4,本文不复制。
|
|
66
66
|
|
|
@@ -77,10 +77,11 @@ my-workspace/
|
|
|
77
77
|
| `localstore` | 凭据与本地偏好:工作区根的 `localstore.json`,默认拒绝入库 |
|
|
78
78
|
| `container_admin` | 机务舱:`config`(说明目录 / 轨迹约束 / 当前配置)+ `msm`(注册表管理) |
|
|
79
79
|
| `im-bridge` ● | 给联系人发消息(微信 / 飞书):文本、文件、联系人、通道状态 |
|
|
80
|
-
| `acc-diag` ● | 运行态诊断:活跃会话 / 唤醒时钟 / 唤醒注册表的全报告。**只读** |
|
|
81
80
|
| `diagram` ● | 标签源码 → 图,**进程内**光栅化并贴进对话(不起浏览器、不落文件) |
|
|
82
81
|
|
|
83
|
-
● = **按条件出现**。条件不满足时**根本不注册**(AI 连看都看不到,也不占上下文):`im-bridge` 要有已启用的 IM 通道;`
|
|
82
|
+
● = **按条件出现**。条件不满足时**根本不注册**(AI 连看都看不到,也不占上下文):`im-bridge` 要有已启用的 IM 通道;`diagram` 是实验性功能,**默认关**,开关在设置面板「工具」组。
|
|
83
|
+
|
|
84
|
+
> **运行态诊断**(v1.106.0 起):原独立工具 `acc-diag` 已并入 **`dashboard` 的 `diag` 动作**(常驻可见,无需任何声明)——live 会话 / 唤醒时钟 / CRO 已启用轨迹 / 唤醒注册表(未来与已过期分列)。`exclusiveTools` 机制同批删除。
|
|
84
85
|
|
|
85
86
|
> **改名一律硬切、无兼容别名**:`cc_fs` → `container_fs`、`logbook` / `trajectory` → **`cognitive_trajectory`**、`eap` / `neat` / `cce` → `praxis`。读到旧名时按此表换算。
|
|
86
87
|
|
package/dsh.plugin.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-serenity-hooks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.107.0",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
|
-
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——
|
|
5
|
+
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——12 个工具(container_fs/cognitive_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/localstore/container_admin;另两个 im-bridge/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 认知轨迹日志与原地重建 + 网页登录入口/IM 桥/认知轨迹唤醒注册表。轨迹声明 = 轨迹目录下的 trajectory.json(约束面 + 旧标识 uid + CRO 机器绑定 cro.host;旧名 trajectory-constraint.json / skiff.json 仍在读取族里);轨迹提示词 = 轨迹目录下的 PROMPT.md(一条轨迹「是谁、按什么章程工作」,所有轨迹通用,追加在容器层与质量层之后,不替换它们)。适配 DSH 0.1.7-rc.1 / 0.2.0-rc.1 / 0.2.1-rc.1(三档,deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
|
7
7
|
"dsh": ">=0.1.7-rc.1"
|
|
8
8
|
},
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"localstore",
|
|
18
18
|
"container_admin",
|
|
19
19
|
"im-bridge",
|
|
20
|
-
"acc-diag",
|
|
21
20
|
"diagram",
|
|
22
21
|
"ontology",
|
|
23
22
|
"serenity-skill-creator"
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { n as __exportAll } from "./rolldown-runtime-B4iAMlE-.js";
|
|
2
|
-
import { g as resolveInside, h as readUtf8 } from "./ccc-B-h_A7uc.js";
|
|
3
1
|
import { basename, dirname, join } from "node:path";
|
|
4
2
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
5
3
|
//#region src/kernel/time.ts
|
|
@@ -1252,334 +1250,4 @@ function claimBinding(sessionsRoot, dirName, decl, opts = {}) {
|
|
|
1252
1250
|
};
|
|
1253
1251
|
}
|
|
1254
1252
|
//#endregion
|
|
1255
|
-
|
|
1256
|
-
/** sessionId → 绑定的轨迹(**进程内**;跨重启的权威来源是 `trajectory/bound.ts` 的持久绑定) */
|
|
1257
|
-
const trajectorySessions = /* @__PURE__ */ new Map();
|
|
1258
|
-
/** 登记/更新一个会话 → 轨迹的映射 */
|
|
1259
|
-
function registerTrajectorySession(sessionId, trajectoryDirName, ccc) {
|
|
1260
|
-
trajectorySessions.set(sessionId, {
|
|
1261
|
-
trajectoryDirName,
|
|
1262
|
-
ccc
|
|
1263
|
-
});
|
|
1264
|
-
}
|
|
1265
|
-
/** 解绑(会话销毁 / 轨迹失效 ⇒ 换身份) */
|
|
1266
|
-
function unregisterTrajectorySession(sessionId) {
|
|
1267
|
-
trajectorySessions.delete(sessionId);
|
|
1268
|
-
}
|
|
1269
|
-
/** 查会话承载的轨迹目录名(无 → null);`guards`/`system-prompt` 的同步热路径用 */
|
|
1270
|
-
function trajectoryDirNameForSession(sessionId) {
|
|
1271
|
-
const b = trajectorySessions.get(sessionId);
|
|
1272
|
-
return b === void 0 || b.trajectoryDirName === "" ? null : b.trajectoryDirName;
|
|
1273
|
-
}
|
|
1274
|
-
//#endregion
|
|
1275
|
-
//#region src/trajectory/policy/profile.ts
|
|
1276
|
-
/**
|
|
1277
|
-
* trajectory/policy/profile.ts — **轨迹约束的唯一判据**:目录下有 `trajectory-constraint.json` 的认知轨迹(零 DSH 依赖,可独立单测)
|
|
1278
|
-
*
|
|
1279
|
-
* ## 🔴 owner 2026-10-19 重做令(逐字,本文件存在的全部理由)
|
|
1280
|
-
*
|
|
1281
|
-
* > 「轨迹约束 复杂的约束和提示词体系都干掉,改为这样的实现:
|
|
1282
|
-
* > **轨迹约束本身是认知轨迹的一个特殊情况,即目录下拥有 `trajectory-constraint.json` 的认知轨迹自动是一个 轨迹约束**
|
|
1283
|
-
* > (json 里配置上个版本就有的各种约束),**会话跑在认知轨迹上且发现 `trajectory-constraint.json`,则运行时实现各类约束**」
|
|
1284
|
-
*
|
|
1285
|
-
* ## 旧模型 → 新模型(**一条判据取代四条**)
|
|
1286
|
-
*
|
|
1287
|
-
* | 项 | 旧 | 新 |
|
|
1288
|
-
* |---|---|---|
|
|
1289
|
-
* | 轨迹约束是什么 | `serenity.json` 的 `轨迹约束.roles.<name>` 一条配置 | **轨迹目录里有 `trajectory-constraint.json`** |
|
|
1290
|
-
* | 怎么认出 轨迹约束会话 | dsh sessionId 前缀 `轨迹约束-` | **它绑定的轨迹有 `trajectory-constraint.json`** |
|
|
1291
|
-
* | 工作台从哪来 | `ensureTrajectorySession` 另建一个 SESSION | **就是该轨迹自己的 SESSION.md** |
|
|
1292
|
-
* | 身份 | 角色名 | **轨迹编码**(`trajectory/core.ts` 的 `parseTrajectoryCode`) |
|
|
1293
|
-
*
|
|
1294
|
-
* ⇒ 收益(owner:「理解难度大幅下降」的实际内容):四个各自会漂的机制收敛为**一条文件存在性判据**。
|
|
1295
|
-
* 删掉 `trajectory-constraint.json` ⇒ 该轨迹**当场**退化为普通轨迹(工具面、提示词、keeper 全部恢复默认)。
|
|
1296
|
-
*
|
|
1297
|
-
* ## 归属(D23)
|
|
1298
|
-
* **机制在 ACC**(文件叫什么、怎么读、怎么判、缺省值、如何施加约束);
|
|
1299
|
-
* **内容在 CCC**(`trajectory-constraint.json` 里填什么:模型、白名单、提示词路径)。
|
|
1300
|
-
* ⇒ ACC 代码里**不出现任何具体角色名**,也不读 `serenity.json` 的 轨迹约束段(该段已退役)。
|
|
1301
|
-
*
|
|
1302
|
-
* ## S12(2026-10-19,轨迹中心重构):此前位于 `role/轨迹约束/` 下(该目录已随本重构消失)
|
|
1303
|
-
*
|
|
1304
|
-
* 落点 = `trajectory/policy/`。判据(判读表 §3.1):本文件判的是**某条轨迹的约束面**,
|
|
1305
|
-
* 主语是轨迹 ⇒ 它一直就是轨迹切面,只是旧目录把它挂在"角色"这个**平行概念**下。
|
|
1306
|
-
* ⚠️ **文件名 `profile` 与 `trajectory-constraint.json` / `TrajectoryConstraint` 等符号名一律不动**:
|
|
1307
|
-
* 那是有具体指称的东西(一个固定文件名 + 它的解析结果),不是组织单位。
|
|
1308
|
-
*/
|
|
1309
|
-
var profile_exports = /* @__PURE__ */ __exportAll({
|
|
1310
|
-
TRAJECTORY_CONSTRAINT_FILENAME: () => TRAJECTORY_CONSTRAINT_FILENAME,
|
|
1311
|
-
findDirNameByCode: () => findDirNameByCode,
|
|
1312
|
-
isTrajectoryConstrained: () => isTrajectoryConstrained,
|
|
1313
|
-
listTrajectoryConstraints: () => listTrajectoryConstraints,
|
|
1314
|
-
readTrajectoryConstraintAt: () => readTrajectoryConstraintAt,
|
|
1315
|
-
readTrajectoryConstraintByCode: () => readTrajectoryConstraintByCode,
|
|
1316
|
-
replacesDefaultIdentity: () => replacesDefaultIdentity,
|
|
1317
|
-
trajectoryCodeForSession: () => trajectoryCodeForSession,
|
|
1318
|
-
trajectoryConstraintForSession: () => trajectoryConstraintForSession
|
|
1319
|
-
});
|
|
1320
|
-
/**
|
|
1321
|
-
* 🆕 **声明文件的文件名**(2026-10-19 owner 裁 Q2:短名 `trajectory.json`)。
|
|
1322
|
-
*
|
|
1323
|
-
* ⚠️ **判据不是"这个名字在不在"**,而是**族内任一存在**(`TRAJECTORY_FILENAME_FAMILY`)。
|
|
1324
|
-
* 这个名字只是**写入目标**与**提示文案里该印的那个**。
|
|
1325
|
-
*/
|
|
1326
|
-
const TRAJECTORY_CONSTRAINT_FILENAME = TRAJECTORY_FILENAME;
|
|
1327
|
-
/**
|
|
1328
|
-
* 已告警过的坏 `trajectory-constraint.json`(进程级去重:同一坏文件不刷屏,但**绝不静默**)。
|
|
1329
|
-
*
|
|
1330
|
-
* 🔴 为什么必须响亮(同源先例 = `loadSerenityConfig` 的 F-07):一份坏 JSON 会让
|
|
1331
|
-
* **工具白名单静默失效**——而白名单正是 轨迹约束的权限边界 ⇒ 静默 = 权限面悄悄放开或收死,
|
|
1332
|
-
* 两种都查不到原因。
|
|
1333
|
-
*/
|
|
1334
|
-
const warnedBrokenProfiles = /* @__PURE__ */ new Set();
|
|
1335
|
-
/** 活跃轨迹目录名(跳过 `_`/`.` 前缀 —— 归档区与日志区不是轨迹;判据同 `readAllSessions`) */
|
|
1336
|
-
function activeTrajectoryDirNames(root) {
|
|
1337
|
-
try {
|
|
1338
|
-
return readdirSync(sessionsRoot(root), { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
|
|
1339
|
-
} catch {
|
|
1340
|
-
return [];
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
/**
|
|
1344
|
-
* 读一个目录下的 `trajectory-constraint.json`(**纯读,不施加约束**)。
|
|
1345
|
-
*
|
|
1346
|
-
* @param trajectoryDir 轨迹目录绝对路径
|
|
1347
|
-
* @param root CCC 根(仅用于 `systemPromptFile` 的逃逸拒绝)
|
|
1348
|
-
* @returns 归一后的约束面;**无该文件 → `null`(= 这不是 轨迹约束,常态,不是错误)**
|
|
1349
|
-
*
|
|
1350
|
-
* ⚠️ **形态容错**:数组元素非字符串 → 丢弃该项(不整份作废);`cognitiveTrajectory`
|
|
1351
|
-
* 缺项 → 各自取 **true**(见 R↓);`model` 空白 → undefined(回退缺省)。
|
|
1352
|
-
* 坏 JSON ⇒ 告警 + `null`(**按"不是 轨迹约束"处理**:宁可让它退回普通轨迹,也不要带着
|
|
1353
|
-
* 半份读不懂的权限面运行)。
|
|
1354
|
-
*/
|
|
1355
|
-
function readTrajectoryConstraintAt(trajectoryDir, root) {
|
|
1356
|
-
const dirName = trajectoryDir.split("/").filter(Boolean).pop() ?? "";
|
|
1357
|
-
const code = parseTrajectoryCode(dirName);
|
|
1358
|
-
if (code === null) return null;
|
|
1359
|
-
const found = findTrajectoryFile(trajectoryDir);
|
|
1360
|
-
if (found === null) return null;
|
|
1361
|
-
let raw;
|
|
1362
|
-
try {
|
|
1363
|
-
raw = JSON.parse(readUtf8(found));
|
|
1364
|
-
} catch (err) {
|
|
1365
|
-
if (!warnedBrokenProfiles.has(found)) {
|
|
1366
|
-
warnedBrokenProfiles.add(found);
|
|
1367
|
-
console.warn(`[serenity-hooks] ✗ ${TRAJECTORY_FILENAME} 解析失败 ⇒ 该轨迹**按普通轨迹处理**(工具白名单与提示词约束全部不施加)。请修 JSON: ${found} — ${String(err?.message ?? err)}`);
|
|
1368
|
-
}
|
|
1369
|
-
return null;
|
|
1370
|
-
}
|
|
1371
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
1372
|
-
if (!warnedBrokenProfiles.has(found)) {
|
|
1373
|
-
warnedBrokenProfiles.add(found);
|
|
1374
|
-
console.warn(`[serenity-hooks] ✗ ${TRAJECTORY_FILENAME} 顶层不是对象 ⇒ 按普通轨迹处理: ${found}`);
|
|
1375
|
-
}
|
|
1376
|
-
return null;
|
|
1377
|
-
}
|
|
1378
|
-
const obj = raw;
|
|
1379
|
-
const file = found;
|
|
1380
|
-
/**
|
|
1381
|
-
* 白名单字段的**两态**读取(D181,owner 2026-10-20 裁「不写当然不收窄」):
|
|
1382
|
-
*
|
|
1383
|
-
* | 文件里 | 返回 | 语义 |
|
|
1384
|
-
* |---|---|---|
|
|
1385
|
-
* | 字段**不存在** | `undefined` | **不收窄**(这条轨迹要的是别的设定,比如只写 `resident`) |
|
|
1386
|
-
* | `[]`(显式空数组) | `[]` | **全隐藏**(除恒可用的 `skill`)—— 用户明说了"我一个都不给" |
|
|
1387
|
-
* | `["a","b"]` | `["a","b"]` | 只给这些 |
|
|
1388
|
-
*
|
|
1389
|
-
* 🔴 **为什么不能归一成 `[]`**:那会把"我没提这件事"读成"我要禁止一切",
|
|
1390
|
-
* 于是「只想声明常驻」的人会被静默锁死(S196 实测踩到,见 D179(b))。
|
|
1391
|
-
* 判据是**字段在不在**,不是数组空不空。
|
|
1392
|
-
*/
|
|
1393
|
-
const strListMaybe = (v) => v === void 0 ? void 0 : Array.isArray(v) ? v.filter((x) => typeof x === "string" && x.trim() !== "").map((x) => x.trim()) : void 0;
|
|
1394
|
-
/** 布尔缺省 **true**(R↓ 见接口:工作台就是这条轨迹自己的身体) */
|
|
1395
|
-
const boolOrTrue = (v) => typeof v === "boolean" ? v : true;
|
|
1396
|
-
const ct = obj.cognitiveTrajectory && typeof obj.cognitiveTrajectory === "object" ? obj.cognitiveTrajectory : {};
|
|
1397
|
-
const model = typeof obj.model === "string" && obj.model.trim() !== "" ? obj.model.trim() : void 0;
|
|
1398
|
-
const systemPrompt = typeof obj.systemPrompt === "string" ? obj.systemPrompt : void 0;
|
|
1399
|
-
const rawFile = typeof obj.systemPromptFile === "string" ? obj.systemPromptFile.trim() : "";
|
|
1400
|
-
let systemPromptFile;
|
|
1401
|
-
if (rawFile !== "") try {
|
|
1402
|
-
resolveInside(root, rawFile);
|
|
1403
|
-
systemPromptFile = rawFile;
|
|
1404
|
-
} catch (err) {
|
|
1405
|
-
console.warn(`[serenity-hooks] ✗ ${TRAJECTORY_CONSTRAINT_FILENAME} 的 systemPromptFile 越界,已忽略(其余约束仍生效): ${file} — ${String(err?.message ?? err)}`);
|
|
1406
|
-
}
|
|
1407
|
-
const residentRaw = obj.resident;
|
|
1408
|
-
let resident;
|
|
1409
|
-
if (residentRaw && typeof residentRaw === "object" && !Array.isArray(residentRaw)) {
|
|
1410
|
-
const serves = residentRaw.serves;
|
|
1411
|
-
resident = typeof serves === "string" && serves.trim() !== "" ? { serves: serves.trim() } : {};
|
|
1412
|
-
}
|
|
1413
|
-
const tools = strListMaybe(obj.tools);
|
|
1414
|
-
const msms = strListMaybe(obj.msms);
|
|
1415
|
-
const writes = strListMaybe(obj.writes);
|
|
1416
|
-
/**
|
|
1417
|
-
* 提示词注入模式(owner 2026-10-20):只搬运,不判决。
|
|
1418
|
-
*
|
|
1419
|
-
* 🔴 判决在 `planPromptInjection()` —— 那里有唯一的合法性表与降级规则。
|
|
1420
|
-
* 这里若也判一次(比如把未知值归一成 append),就会有两处真相:
|
|
1421
|
-
* 一处静默改值、一处告警,读数是矛盾的(D151 同族)。
|
|
1422
|
-
*/
|
|
1423
|
-
const promptRaw = obj.prompt;
|
|
1424
|
-
const prompt = promptRaw !== null && typeof promptRaw === "object" && !Array.isArray(promptRaw) ? {
|
|
1425
|
-
...typeof promptRaw.injection === "string" ? { injection: promptRaw.injection } : {},
|
|
1426
|
-
...strListMaybe(promptRaw.replaces) !== void 0 ? { replaces: strListMaybe(promptRaw.replaces) } : {}
|
|
1427
|
-
} : void 0;
|
|
1428
|
-
return {
|
|
1429
|
-
dirName,
|
|
1430
|
-
code,
|
|
1431
|
-
path: file,
|
|
1432
|
-
...model !== void 0 ? { model } : {},
|
|
1433
|
-
...tools !== void 0 ? { tools } : {},
|
|
1434
|
-
...msms !== void 0 ? { msms } : {},
|
|
1435
|
-
...writes !== void 0 ? { writes } : {},
|
|
1436
|
-
...resident !== void 0 ? { resident } : {},
|
|
1437
|
-
...prompt !== void 0 ? { prompt } : {},
|
|
1438
|
-
cognitiveTrajectory: {
|
|
1439
|
-
session: boolOrTrue(ct.session),
|
|
1440
|
-
keeper: boolOrTrue(ct.keeper),
|
|
1441
|
-
rebuild: boolOrTrue(ct.rebuild)
|
|
1442
|
-
},
|
|
1443
|
-
...systemPrompt !== void 0 ? { systemPrompt } : {},
|
|
1444
|
-
...systemPromptFile !== void 0 ? { systemPromptFile } : {}
|
|
1445
|
-
};
|
|
1446
|
-
}
|
|
1447
|
-
/**
|
|
1448
|
-
* 按**轨迹编码**解析 轨迹约束面(`list`/`admin`/调试页/路由解析用)。
|
|
1449
|
-
*
|
|
1450
|
-
* @returns 约束面;轨迹不存在 / 无 `trajectory-constraint.json` → `null`
|
|
1451
|
-
*/
|
|
1452
|
-
function readTrajectoryConstraintByCode(root, code) {
|
|
1453
|
-
const dirName = findDirNameByCode(root, code);
|
|
1454
|
-
if (dirName === null) return null;
|
|
1455
|
-
return readTrajectoryConstraintAt(join(sessionsRoot(root), dirName), root);
|
|
1456
|
-
}
|
|
1457
|
-
/** 扫全部活跃轨迹,返回全部 轨迹约束。**顺序按目录名**(确定性,便于对读)。 */
|
|
1458
|
-
function listTrajectoryConstraints(root) {
|
|
1459
|
-
const out = [];
|
|
1460
|
-
for (const name of activeTrajectoryDirNames(root)) {
|
|
1461
|
-
const p = readTrajectoryConstraintAt(join(sessionsRoot(root), name), root);
|
|
1462
|
-
if (p) out.push(p);
|
|
1463
|
-
}
|
|
1464
|
-
return out;
|
|
1465
|
-
}
|
|
1466
|
-
/**
|
|
1467
|
-
* 编码 → 轨迹目录名(活跃轨迹内)。找不到 → `null`。
|
|
1468
|
-
*
|
|
1469
|
-
* ⚠️ 与 `findSession` 的分工:这里**只按编码精确**匹配(不做模糊),
|
|
1470
|
-
* 因为它的调用方(路由 / 约束施加)要的是**确定性**,模糊匹配会把"手抖打错的名字"
|
|
1471
|
-
* 静默投到一条相近的轨迹上——那正是最难查的一类串味。
|
|
1472
|
-
*/
|
|
1473
|
-
function findDirNameByCode(root, code) {
|
|
1474
|
-
const hits = [];
|
|
1475
|
-
for (const name of activeTrajectoryDirNames(root)) if (parseTrajectoryCode(name) === code) hits.push(name);
|
|
1476
|
-
if (hits.length > 1) throw new Error(`编码「${code}」在本 CCC 有 ${hits.length} 条轨迹同时占用,无法确定要施加到哪一条:\n` + hits.map((n) => ` · ${n}`).join("\n") + "\n编码是终身身份(AXIOM 3)⇒ 不替你任选其一。改用**完整目录名**指定。");
|
|
1477
|
-
return hits[0] ?? null;
|
|
1478
|
-
}
|
|
1479
|
-
/**
|
|
1480
|
-
* **会话级**判据(J2):这个 dsh 会话是不是 轨迹约束会话 —— 唯一入口。
|
|
1481
|
-
*
|
|
1482
|
-
* 判据 = **它绑定的轨迹有 `trajectory-constraint.json`**(不是 sessionId 前缀,也不是配置里有没有角色)。
|
|
1483
|
-
*
|
|
1484
|
-
* ## 为什么"绑定的轨迹"从两个来源取(R↓,一个失败模式)
|
|
1485
|
-
* ① **持久绑定**(`readLastBound`,宿主存储域/`.bindings.json`)—— 权威,跨重启成立;
|
|
1486
|
-
* ② **内存注册表**(`trajectory/policy/window`)—— 覆盖绑定的**窗口期**(轨迹刚定、bound 还没落盘)。
|
|
1487
|
-
* ⇒ 只取 ① 会在建会话的第一轮判成"不是 轨迹约束"(工具面不收窄,模型看见不该有的工具);
|
|
1488
|
-
* 只取 ② 会在进程重启后全判成"不是"(轨迹约束 失去约束,**权限面静默放开**)。
|
|
1489
|
-
* ⇒ **两来源并取**,都不中才 `null`。
|
|
1490
|
-
*
|
|
1491
|
-
* @param root CCC 根
|
|
1492
|
-
* @param sessionId dsh 会话 id
|
|
1493
|
-
* @param boundDirName 调用方已解析的绑定目录名(可选;给了就省一次读绑定)
|
|
1494
|
-
* @returns 约束面;不是 轨迹约束会话 → `null`
|
|
1495
|
-
*/
|
|
1496
|
-
function trajectoryConstraintForSession(root, sessionId, boundDirName) {
|
|
1497
|
-
const dirName = boundDirName ?? registeredDirName(sessionId);
|
|
1498
|
-
if (dirName === null || dirName === "") return null;
|
|
1499
|
-
return readTrajectoryConstraintAt(join(sessionsRoot(root), dirName), root);
|
|
1500
|
-
}
|
|
1501
|
-
/** 内存登记的轨迹目录名(注册表单一真相源在 `./registry.ts`;此处只做一次转发) */
|
|
1502
|
-
function registeredDirName(sessionId) {
|
|
1503
|
-
if (typeof sessionId !== "string" || sessionId === "") return null;
|
|
1504
|
-
return trajectoryDirNameForSession(sessionId);
|
|
1505
|
-
}
|
|
1506
|
-
/**
|
|
1507
|
-
* **会话 → 认知轨迹编码**(供工具可见性这类"只有 sessionId、没有 agent 对象"的调用方用)。
|
|
1508
|
-
*
|
|
1509
|
-
* ## 为什么需要它(而不是复用 `trajectoryConstraintForSession`)
|
|
1510
|
-
*
|
|
1511
|
-
* 那条路的判据是"**绑定的轨迹有 `trajectory-constraint.json`**"——它回答的是
|
|
1512
|
-
* 「这条会话是不是一条**约束会话**」。而工具可见性问的是另一个问题:
|
|
1513
|
-
* 「这条会话属于**哪条**轨迹」。前者对**普通轨迹**恒返回 `null`(它们没有约束文件),
|
|
1514
|
-
* ⇒ 拿它去判 IM 接线,会把所有普通轨迹一律判成"无归属"。
|
|
1515
|
-
*
|
|
1516
|
-
* ## 两个来源并取(与 `trajectoryConstraintForSession` 同一条纪律)
|
|
1517
|
-
*
|
|
1518
|
-
* ① **内存注册表**(`window.ts`)——覆盖"刚 `use`、绑定还没落盘"的窗口期;
|
|
1519
|
-
* ② **持久绑定**(`listBindDeclarations` 扫 `current.dsh_session_bind`)——跨重启成立。
|
|
1520
|
-
*
|
|
1521
|
-
* ⇒ 只取 ① 会在重启后全判成"没归属"(工具**静默消失**);
|
|
1522
|
-
* 只取 ② 会在建会话的第一轮判成"没归属"(同样是静默)。
|
|
1523
|
-
* 🔴 **这条纪律不是新发明的**:`trajectoryConstraintForSession` 的注释里已经付过一次代价。
|
|
1524
|
-
*
|
|
1525
|
-
* @param root CCC 根
|
|
1526
|
-
* @param sessionId dsh 会话 id
|
|
1527
|
-
* @returns 轨迹编码(`S###` 或自定义码);解析不到 ⇒ `null`
|
|
1528
|
-
*/
|
|
1529
|
-
function trajectoryCodeForSession(root, sessionId) {
|
|
1530
|
-
if (typeof sessionId !== "string" || sessionId === "") return null;
|
|
1531
|
-
const fromMemory = registeredDirName(sessionId);
|
|
1532
|
-
if (fromMemory !== null && fromMemory !== "") return parseTrajectoryCode(fromMemory) ?? fromMemory;
|
|
1533
|
-
try {
|
|
1534
|
-
for (const { dirName, decl } of listBindDeclarations(sessionsRoot(root))) {
|
|
1535
|
-
if (decl.sessionId !== sessionId) continue;
|
|
1536
|
-
return parseTrajectoryCode(dirName) ?? dirName;
|
|
1537
|
-
}
|
|
1538
|
-
} catch {}
|
|
1539
|
-
return null;
|
|
1540
|
-
}
|
|
1541
|
-
/**
|
|
1542
|
-
* 该 dsh 会话**是不是** 轨迹约束会话(布尔形态的 `trajectoryConstraintForSession`)。
|
|
1543
|
-
*
|
|
1544
|
-
* 存在的理由:调用点很多只要一个"是/不是"(seams 的旁路判定),
|
|
1545
|
-
* 让它们各自写 `!== null` 会把判据散开;**判据只能有一个入口**。
|
|
1546
|
-
*
|
|
1547
|
-
* 🔴 **D183(owner 2026-10-20):这里的 `true` 只表示"有声明",不再等于"该旁路默认行为"。**
|
|
1548
|
-
* 要判断后者请用 `replacesDefaultIdentity()` —— 两者**刻意分开**,因为:
|
|
1549
|
-
* 「我声明过」与「我声明了什么」是两件事,而旁路 ACC 身份只需要后者成立。
|
|
1550
|
-
*/
|
|
1551
|
-
function isTrajectoryConstrained(root, sessionId) {
|
|
1552
|
-
return trajectoryConstraintForSession(root, sessionId) !== null;
|
|
1553
|
-
}
|
|
1554
|
-
/**
|
|
1555
|
-
* 这条声明**是否真的取代了该轨迹的默认身份**(= 该不该旁路 ACC 身份/首轮/恢复等默认行为)。
|
|
1556
|
-
*
|
|
1557
|
-
* ## 为什么需要它(D183,owner 2026-10-20 逐字)
|
|
1558
|
-
*
|
|
1559
|
-
* > 「这个 `trajectory.json` 中**所有 key 都是可选的;不写就是不设定 不应影响默认行为**」
|
|
1560
|
-
*
|
|
1561
|
-
* 旧判据是**文件存在** ⇒ 只写一句 `resident`(对外用途自述)就会连带丢掉
|
|
1562
|
-
* ACC 身份播种、首轮锚定、自动恢复、compact 重注入 —— **完全超出用户预期**。
|
|
1563
|
-
*
|
|
1564
|
-
* ## 判据(哪些 key 真的改"这条轨迹是谁")
|
|
1565
|
-
*
|
|
1566
|
-
* | key | 取代默认身份? | 理由 |
|
|
1567
|
-
* |---|---|---|
|
|
1568
|
-
* | `tools` / `msms` | **否** | 它们收窄**能力**,但"我是谁、我按什么章程工作"没变 ⇒ 仍该拿 ACC 身份 |
|
|
1569
|
-
* | `model` | **否** | 换的只是**执行的模型**,不是身份 |
|
|
1570
|
-
* | `resident` | **否** | 纯对外自述,D173 明说"不碰任何默认行为" |
|
|
1571
|
-
* | `cro.host` | **否** | 管"哪台机器跑 CRO 程序",与身份无关 |
|
|
1572
|
-
* | `cognitiveTrajectory` | **否** | 管"参与哪些纪律",纪律是叠加不是取代 |
|
|
1573
|
-
* | `systemPromptFile` / `systemPrompt` | **是** | 它自带**章程** ⇒ 用户的提示词整段取代 ACC 的 |
|
|
1574
|
-
* | `PROMPT.md`(目录里) | **否** | 它**追加**在 ACC 身份之外(v1.72.0 起的机制),不取代 |
|
|
1575
|
-
*
|
|
1576
|
-
* @returns `true` ⇒ 该轨迹自带章程,应旁路 ACC 身份类默认行为;否则 `false`
|
|
1577
|
-
*/
|
|
1578
|
-
function replacesDefaultIdentity(profile) {
|
|
1579
|
-
if (!profile) return false;
|
|
1580
|
-
const hasFile = (profile.systemPromptFile ?? "").trim() !== "";
|
|
1581
|
-
const hasInline = (profile.systemPrompt ?? "").trim() !== "";
|
|
1582
|
-
return hasFile || hasInline;
|
|
1583
|
-
}
|
|
1584
|
-
//#endregion
|
|
1585
|
-
export { namingTitleFor as A, summarize as B, createSession as C, getLastActiveSessionInfo as D, getActiveSessionInfo as E, resolveSessionByTitle as F, readTrajectoryFile as G, useSession as H, sessionEvents as I, localHuman as J, isoLocal as K, sessionsRoot as L, parseTrajectoryCode as M, readActiveSessionMd as N, listActiveTrajectories as O, readTrajectoryUid as P, setActiveSessionInfo as R, clearActiveSessionInfo as S, findSession as T, TRAJECTORY_FILENAME as U, trajectoryDescOf as V, TRAJECTORY_LEGACY_FILENAMES as W, localIdStamp as Y, readBindDeclaration as _, profile_exports as a, UID_FILENAME as b, replacesDefaultIdentity as c, registerTrajectorySession as d, trajectoryDirNameForSession as f, listBindDeclarations as g, isBindUsable as h, listTrajectoryConstraints as i, parseSessionContextFromEvents as j, listSessions as k, trajectoryCodeForSession as l, claimBinding as m, findDirNameByCode as n, readTrajectoryConstraintAt as o, unregisterTrajectorySession as p, localFileStamp as q, isTrajectoryConstrained as r, readTrajectoryConstraintByCode as s, TRAJECTORY_CONSTRAINT_FILENAME as t, trajectoryConstraintForSession as u, COGNITIVE_TRAJECTORY_ACTIONS as v, extractSessionMdPathFromText as w, archiveSession as x, DEFAULT_SESSION_SCOPE as y, showSession as z };
|
|
1253
|
+
export { useSession as A, resolveSessionByTitle as C, showSession as D, setActiveSessionInfo as E, isoLocal as F, localFileStamp as I, localHuman as L, TRAJECTORY_LEGACY_FILENAMES as M, findTrajectoryFile as N, summarize as O, readTrajectoryFile as P, localIdStamp as R, readTrajectoryUid as S, sessionsRoot as T, listSessions as _, readBindDeclaration as a, parseTrajectoryCode as b, UID_FILENAME as c, createSession as d, extractSessionMdPathFromText as f, listActiveTrajectories as g, getLastActiveSessionInfo as h, listBindDeclarations as i, TRAJECTORY_FILENAME as j, trajectoryDescOf as k, archiveSession as l, getActiveSessionInfo as m, findTrajectoryHolding as n, COGNITIVE_TRAJECTORY_ACTIONS as o, findSession as p, isBindUsable as r, DEFAULT_SESSION_SCOPE as s, claimBinding as t, clearActiveSessionInfo as u, namingTitleFor as v, sessionEvents as w, readActiveSessionMd as x, parseSessionContextFromEvents as y };
|
|
@@ -152,20 +152,72 @@ function loadSerenityConfig(root, paths = DEFAULT_SERENITY_CONFIG_PATHS) {
|
|
|
152
152
|
return {};
|
|
153
153
|
}
|
|
154
154
|
/**
|
|
155
|
-
*
|
|
155
|
+
* (已删除)`readExclusiveTools` —— v1.106.0 随 `exclusiveTools` 机制整体删除。
|
|
156
|
+
* 原语义:读 CCC 声明的专属工具清单,fail-closed(读不到 ⇒ 空数组 ⇒ 专属工具保持隐藏)。
|
|
157
|
+
* 删除理由见 `SerenityConfig.exclusiveTools` 处的注释(表空 ⇒ 不可证伪)。
|
|
158
|
+
*/
|
|
159
|
+
/**
|
|
160
|
+
* 读取 CCC 声明的轨迹消息订阅表(`trajectorySubscriptions`,v1.107.0)。
|
|
161
|
+
*
|
|
162
|
+
* ## 失败方向 = **fail-open,但坏项逐条报告**(与另外两处刻意不同)
|
|
163
|
+
*
|
|
164
|
+
* 不订阅 ≠ 危险动作:它只是"没有通知",不会藏掉任何能力(对比 `safeMode.hiddenTools`
|
|
165
|
+
* 是 fail-open 因为**隐藏**才是危险方向)。⇒ 整体读不到 ⇒ 空表。
|
|
166
|
+
*
|
|
167
|
+
* 🔴 **但"坏项"不能一起吞掉**:配置里写了这一条、却因为成员名写错而**永远不触发**,
|
|
168
|
+
* 是与 `safeMode.hiddenTools` 写错工具名**同族的静默失效**(写了但不生效,且没人知道)。
|
|
169
|
+
* ⇒ 本函数返回 `{ subs, problems }`:合法项照常生效,坏项进 `problems` 供调用方响亮告警。
|
|
170
|
+
* ⚠️ 这与"整表读不到就空表"并不矛盾:前者是**文件级**失败(无法解析),
|
|
171
|
+
* 后者是**条目级**失败(能解析但内容不成立)—— **两个粒度、两种处置**(D233 同族)。
|
|
156
172
|
*
|
|
157
|
-
* 失败语义:无配置/字段缺失/配置损坏 → **空数组**(= 不声明任何专属工具 ⇒ 专属工具保持隐藏)。
|
|
158
|
-
* 这里选 **fail-closed**(与 im-bridge 的 fail-open 相反)的理由:专属工具的默认态就是"隐藏",
|
|
159
|
-
* 判据读不到 = 没有证据表明该 CCC 要它;而配置损坏本身已在 `loadSerenityConfig` 响亮告警
|
|
160
|
-
* (不会静默)。im-bridge 相反——隐藏一个**已在使用**的通道才会静默损害能力。
|
|
161
173
|
* @param root CCC 根
|
|
162
174
|
* @param paths 候选配置相对路径
|
|
163
|
-
* @returns
|
|
175
|
+
* @returns `subs` = 干净的订阅表;`problems` = 逐条可读的坏项说明(空数组 = 全好)
|
|
164
176
|
*/
|
|
165
|
-
function
|
|
166
|
-
const
|
|
167
|
-
if (!Array.isArray(
|
|
168
|
-
|
|
177
|
+
function readTrajectorySubscriptions(root, paths = DEFAULT_SERENITY_CONFIG_PATHS) {
|
|
178
|
+
const raw = loadSerenityConfig(root, paths).trajectorySubscriptions;
|
|
179
|
+
if (!Array.isArray(raw)) return {
|
|
180
|
+
subs: [],
|
|
181
|
+
problems: []
|
|
182
|
+
};
|
|
183
|
+
const subs = [];
|
|
184
|
+
const problems = [];
|
|
185
|
+
raw.forEach((item, i) => {
|
|
186
|
+
const at = `trajectorySubscriptions[${i}]`;
|
|
187
|
+
if (typeof item !== "object" || item === null) {
|
|
188
|
+
problems.push(`${at}: 不是对象(应为 { watcher, members })`);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const rec = item;
|
|
192
|
+
const watcher = typeof rec.watcher === "string" ? rec.watcher.trim() : "";
|
|
193
|
+
if (watcher === "") {
|
|
194
|
+
problems.push(`${at}: watcher 缺失或为空(必须指定谁来收通知)`);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const membersRaw = Array.isArray(rec.members) ? rec.members : null;
|
|
198
|
+
if (membersRaw === null) {
|
|
199
|
+
problems.push(`${at}(watcher=${watcher}): members 不是数组`);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const members = membersRaw.filter((m) => typeof m === "string" && m.trim() !== "").map((m) => m.trim());
|
|
203
|
+
if (members.length === 0) {
|
|
204
|
+
problems.push(`${at}(watcher=${watcher}): members 为空 ⇒ 这条订阅永远不会触发`);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (members.some((m) => m === watcher)) problems.push(`${at}(watcher=${watcher}): members 含 watcher 自己 ⇒ 会形成自激通知,已剔除该项`);
|
|
208
|
+
const cleaned = members.filter((m) => m !== watcher);
|
|
209
|
+
if (cleaned.length === 0) return;
|
|
210
|
+
subs.push({
|
|
211
|
+
watcher,
|
|
212
|
+
members: cleaned,
|
|
213
|
+
enabled: rec.enabled === false ? false : true,
|
|
214
|
+
...typeof rec.note === "string" && rec.note.trim() !== "" ? { note: rec.note.trim() } : {}
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
return {
|
|
218
|
+
subs: subs.filter((s) => s.enabled !== false),
|
|
219
|
+
problems
|
|
220
|
+
};
|
|
169
221
|
}
|
|
170
222
|
/**
|
|
171
223
|
* 读取 CCC 声明的「安全模式期间隐藏的工具」清单(`safeMode.hiddenTools`,v1.51.4)。
|
|
@@ -173,7 +225,7 @@ function readExclusiveTools(root, paths = DEFAULT_SERENITY_CONFIG_PATHS) {
|
|
|
173
225
|
* 语义(R↓):**标记文件存在 ⇒ 才生效**。deny = `['bash', ...本清单]`(并集去重);
|
|
174
226
|
* 标记消失 ⇒ 连同 `bash` 一起解除(调用点在 `syncSafeModeRestriction`,与基础表同一处)。
|
|
175
227
|
*
|
|
176
|
-
* 失败方向 = **fail-open
|
|
228
|
+
* 失败方向 = **fail-open**(与已删除的 `exclusiveTools` 的 fail-closed 相反,理由不同):
|
|
177
229
|
* 未配置 / 字段缺失 / 配置损坏 ⇒ **空数组** = 只隐藏基础表。本键是**附加**屏蔽,
|
|
178
230
|
* 读不到声明就等于"没有证据要求多藏";且**隐藏是危险方向**(藏掉 agent 真正要用的工具
|
|
179
231
|
* 会静默损害能力),而配置损坏本身已有 `loadSerenityConfig` 的响亮告警(不静默)。
|
|
@@ -251,4 +303,4 @@ function matchBlacklist(relPath, rules) {
|
|
|
251
303
|
return null;
|
|
252
304
|
}
|
|
253
305
|
//#endregion
|
|
254
|
-
export { findSerenityRoot as a, matchBlacklist as c, readCccName as d, readCognitiveTrajectorySkills as f, resolveInside as g, readUtf8 as h, findGitRoot as i, pathInside as l,
|
|
306
|
+
export { findSerenityRoot as a, matchBlacklist as c, readCccName as d, readCognitiveTrajectorySkills as f, resolveInside as g, readUtf8 as h, findGitRoot as i, pathInside as l, readTrajectorySubscriptions as m, SAFE_MODE_MARKER as n, isSafeModeOn as o, readSafeModeHiddenTools as p, classifyPath as r, loadSerenityConfig as s, DEFAULT_SERENITY_CONFIG_PATHS as t, readBlacklist as u };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as __exportAll } from "./rolldown-runtime-B4iAMlE-.js";
|
|
2
|
-
import { a as findSerenityRoot } from "./ccc-
|
|
2
|
+
import { a as findSerenityRoot } from "./ccc-BmpE3cQz.js";
|
|
3
3
|
import { basename } from "node:path";
|
|
4
4
|
//#region src/host/access.ts
|
|
5
5
|
/**
|
|
@@ -73,6 +73,18 @@ function hostSettings(ctx) {
|
|
|
73
73
|
function hostWeb(ctx) {
|
|
74
74
|
return hostInjected(ctx, "web");
|
|
75
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* 宿主默认模型选择(**没显式指定模型时**该用的那个)。
|
|
78
|
+
*
|
|
79
|
+
* 🔴 为什么需要这个读取器(v1.105.0,P0 回归修复):
|
|
80
|
+
* `agents.create` **不传** `agentOptions` ⇒ `agent.options.model === undefined`
|
|
81
|
+
* ⇒ 宿主的 persona 模板 `powered by the {{model}} model` **严格插值抛错** ⇒ 整轮失败。
|
|
82
|
+
* ⇒ 「不传」不等于「安全」:**下游有依赖方要求这个值必须存在**。
|
|
83
|
+
* 详见 `trajectory/session.ts` 的 `resolveAgentModel`。
|
|
84
|
+
*/
|
|
85
|
+
function hostAgentDefaultModel(ctx) {
|
|
86
|
+
return hostInjected(ctx, "agentDefaultModel");
|
|
87
|
+
}
|
|
76
88
|
//#endregion
|
|
77
89
|
//#region src/kernel/ccc-roots.ts
|
|
78
90
|
/**
|
|
@@ -223,7 +235,7 @@ async function listCccs(ctx, opts = {}) {
|
|
|
223
235
|
if (typeof defaultRoot === "string" && defaultRoot !== "" && !c.roots.includes(defaultRoot)) c.roots.unshift(defaultRoot);
|
|
224
236
|
let rolesOf = null;
|
|
225
237
|
if (opts.withRoles === true) {
|
|
226
|
-
const { listTrajectoryConstraints } = await import("./profile-
|
|
238
|
+
const { listTrajectoryConstraints } = await import("./profile-BjBn_-be.js").then((n) => n.a);
|
|
227
239
|
rolesOf = (root) => {
|
|
228
240
|
try {
|
|
229
241
|
return listTrajectoryConstraints(root).map((p) => p.code);
|
|
@@ -239,4 +251,4 @@ async function listCccs(ctx, opts = {}) {
|
|
|
239
251
|
}));
|
|
240
252
|
}
|
|
241
253
|
//#endregion
|
|
242
|
-
export { ccc_roots_exports as a,
|
|
254
|
+
export { ccc_roots_exports as a, hostAgents as c, hostSessions as d, hostSettings as f, cccRootForExec as i, hostInjected as l, hostWebServer as m, agentCwdFor as n, listCccs as o, hostWeb as p, cccRootForCwd as r, hostAgentDefaultModel as s, NO_CCC_FROM_AGENT_CWD as t, hostService as u };
|