@shgroup/dsh-serenity-hooks 1.71.0 → 1.73.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/dsh.plugin.json +2 -2
- package/lib/{ccc-Dkoa2oW3.js → ccc-CZUOq3NY.js} +1 -1
- package/lib/{ccc-roots-jZYR2GVE.js → ccc-roots-BhoA7G-0.js} +3 -3
- package/lib/client.js +50 -58
- package/lib/{wake/cro.d.ts → cro/core.d.ts} +2 -2
- 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 +1 -1
- package/lib/{ilink-DEpmE3yi.js → ilink-BMk2w2KY.js} +1 -1
- package/lib/im/accounts.d.ts +105 -0
- package/lib/im/bridge.d.ts +33 -62
- package/lib/im/endpoint.d.ts +1 -1
- package/lib/im/feishu-account.d.ts +92 -0
- package/lib/im/inbound-event.d.ts +162 -0
- package/lib/im/route.d.ts +37 -2
- package/lib/im/weixin-account.d.ts +45 -0
- package/lib/index.d.ts +0 -22
- package/lib/index.js +1070 -996
- package/lib/kernel/ccc.d.ts +78 -2
- package/lib/kernel/ports.d.ts +2 -4
- package/lib/lib-TxscFKeo.js +119355 -0
- package/lib/{message-source-kVoNK0C5.js → message-source-ChyVfev9.js} +2 -2
- package/lib/{profile-DyMJ_bfr.js → profile-BIQ2widI.js} +14 -11
- package/lib/rolldown-runtime-B4iAMlE-.js +35 -0
- package/lib/{route-CPneN5iv.js → route-ItCgAsnz.js} +96 -35
- package/lib/seams/guards.d.ts +1 -1
- package/lib/seams/system-prompt.d.ts +3 -1
- package/lib/{settings-lt1i3OZv.js → settings-UcwIPJhM.js} +13 -62
- package/lib/skills/resource-index.d.ts +1 -1
- package/lib/surface/settings.d.ts +0 -6
- package/lib/surface/text.d.ts +72 -0
- package/lib/surface/usage.d.ts +2 -2
- package/lib/{role/worker/idle.d.ts → trajectory/carrier.d.ts} +12 -2
- package/lib/{role/worker → trajectory/delegate}/core.d.ts +7 -1
- package/lib/{role/worker → trajectory/delegate}/preset.d.ts +9 -2
- package/lib/{role/skiff → trajectory/policy}/profile.d.ts +9 -2
- package/lib/{role/skiff/config.d.ts → trajectory/policy/rules.d.ts} +9 -3
- package/lib/{role/skiff/registry.d.ts → trajectory/policy/window.d.ts} +7 -1
- package/lib/trajectory/prompt.d.ts +101 -0
- package/lib/{role/skiff/core.d.ts → trajectory/session.d.ts} +13 -4
- package/package.json +3 -2
- package/lib/role/skiff/debug.d.ts +0 -88
- package/lib/rolldown-runtime-8H4AJuhK.js +0 -14
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { r as cccRootForCwd } from "./ccc-roots-
|
|
2
|
-
import {
|
|
1
|
+
import { r as cccRootForCwd } from "./ccc-roots-BhoA7G-0.js";
|
|
2
|
+
import { T as parseTrajectoryCode, b as getLastActiveSessionInfo, k as sessionEvents, y as getActiveSessionInfo } from "./profile-BIQ2widI.js";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
5
5
|
//#region src/trajectory/bound.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { _ as resolveInside, g as readUtf8 } from "./ccc-
|
|
1
|
+
import { n as __exportAll } from "./rolldown-runtime-B4iAMlE-.js";
|
|
2
|
+
import { _ as resolveInside, g as readUtf8 } from "./ccc-CZUOq3NY.js";
|
|
3
3
|
import { basename, dirname, join } from "node:path";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
5
5
|
//#region src/kernel/time.ts
|
|
@@ -750,7 +750,7 @@ function archiveSession(root, key, dryRun = false) {
|
|
|
750
750
|
};
|
|
751
751
|
}
|
|
752
752
|
//#endregion
|
|
753
|
-
//#region src/
|
|
753
|
+
//#region src/trajectory/policy/window.ts
|
|
754
754
|
const skiffSessions = /* @__PURE__ */ new Map();
|
|
755
755
|
/** 登记/更新一个会话 → 轨迹的映射 */
|
|
756
756
|
function registerSkiffSession(sessionId, trajectoryDirName, ccc) {
|
|
@@ -768,14 +768,10 @@ function skiffTrajectoryDirNameFor(sessionId) {
|
|
|
768
768
|
const b = skiffSessions.get(sessionId);
|
|
769
769
|
return b === void 0 || b.trajectoryDirName === "" ? null : b.trajectoryDirName;
|
|
770
770
|
}
|
|
771
|
-
/** 查会话的完整绑定(轨迹 + CCC;无 → null)——追问延续时校验 (轨迹, CCC) 未串味 */
|
|
772
|
-
function skiffSessionInfo(sessionId) {
|
|
773
|
-
return skiffSessions.get(sessionId) ?? null;
|
|
774
|
-
}
|
|
775
771
|
//#endregion
|
|
776
|
-
//#region src/
|
|
772
|
+
//#region src/trajectory/policy/profile.ts
|
|
777
773
|
/**
|
|
778
|
-
*
|
|
774
|
+
* trajectory/policy/profile.ts — **skiff 的唯一判据**:目录下有 `skiff.json` 的认知轨迹(零 DSH 依赖,可独立单测)
|
|
779
775
|
*
|
|
780
776
|
* ## 🔴 owner 2026-10-19 重做令(逐字,本文件存在的全部理由)
|
|
781
777
|
*
|
|
@@ -799,6 +795,13 @@ function skiffSessionInfo(sessionId) {
|
|
|
799
795
|
* **机制在 ACC**(文件叫什么、怎么读、怎么判、缺省值、如何施加约束);
|
|
800
796
|
* **内容在 CCC**(`skiff.json` 里填什么:模型、白名单、提示词路径)。
|
|
801
797
|
* ⇒ ACC 代码里**不出现任何具体角色名**,也不读 `serenity.json` 的 skiff 段(该段已退役)。
|
|
798
|
+
*
|
|
799
|
+
* ## S12(2026-10-19,轨迹中心重构):此前位于 `role/skiff/` 下(该目录已随本重构消失)
|
|
800
|
+
*
|
|
801
|
+
* 落点 = `trajectory/policy/`。判据(判读表 §3.1):本文件判的是**某条轨迹的约束面**,
|
|
802
|
+
* 主语是轨迹 ⇒ 它一直就是轨迹切面,只是旧目录把它挂在"角色"这个**平行概念**下。
|
|
803
|
+
* ⚠️ **文件名 `profile` 与 `skiff.json` / `SkiffProfile` 等符号名一律不动**:
|
|
804
|
+
* 那是有具体指称的东西(一个固定文件名 + 它的解析结果),不是组织单位。
|
|
802
805
|
*/
|
|
803
806
|
var profile_exports = /* @__PURE__ */ __exportAll({
|
|
804
807
|
SKIFF_PROFILE_FILENAME: () => SKIFF_PROFILE_FILENAME,
|
|
@@ -930,7 +933,7 @@ function findDirNameByCode(root, code) {
|
|
|
930
933
|
*
|
|
931
934
|
* ## 为什么"绑定的轨迹"从两个来源取(R↓,一个失败模式)
|
|
932
935
|
* ① **持久绑定**(`readLastBound`,宿主存储域/`.bindings.json`)—— 权威,跨重启成立;
|
|
933
|
-
* ② **内存注册表**(`
|
|
936
|
+
* ② **内存注册表**(`trajectory/policy/window`)—— 覆盖绑定的**窗口期**(轨迹刚定、bound 还没落盘)。
|
|
934
937
|
* ⇒ 只取 ① 会在建会话的第一轮判成"不是 skiff"(工具面不收窄,模型看见不该有的工具);
|
|
935
938
|
* 只取 ② 会在进程重启后全判成"不是"(skiff 失去约束,**权限面静默放开**)。
|
|
936
939
|
* ⇒ **两来源并取**,都不中才 `null`。
|
|
@@ -960,4 +963,4 @@ function isSkiffSession(root, sessionId) {
|
|
|
960
963
|
return skiffProfileForSession(root, sessionId) !== null;
|
|
961
964
|
}
|
|
962
965
|
//#endregion
|
|
963
|
-
export {
|
|
966
|
+
export { sessionsRoot as A, namingTitleFor as C, readTrajectoryUid as D, readActiveSessionMd as E, isoLocal as F, localFileStamp as I, localHuman as L, showSession as M, summarize as N, resolveSessionByTitle as O, useSession as P, localIdStamp as R, listSessions as S, parseTrajectoryCode as T, extractSessionMdPathFromText as _, readSkiffProfileAt as a, getLastActiveSessionInfo as b, registerSkiffSession as c, COGNITIVE_TRAJECTORY_ACTIONS as d, DEFAULT_SESSION_SCOPE as f, createSession as g, clearActiveSessionInfo as h, profile_exports as i, setActiveSessionInfo as j, sessionEvents as k, skiffTrajectoryDirNameFor as l, archiveSession as m, isSkiffSession as n, readSkiffProfileByCode as o, UID_FILENAME as p, listSkiffProfiles as r, skiffProfileForSession as s, SKIFF_PROFILE_FILENAME as t, unregisterSkiffSession as u, findSession as v, parseSessionContextFromEvents as w, listActiveTrajectories as x, getActiveSessionInfo as y };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
10
|
+
var __exportAll = (all, no_symbols) => {
|
|
11
|
+
let target = {};
|
|
12
|
+
for (var name in all) __defProp(target, name, {
|
|
13
|
+
get: all[name],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
17
|
+
return target;
|
|
18
|
+
};
|
|
19
|
+
var __copyProps = (to, from, except, desc) => {
|
|
20
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
21
|
+
key = keys[i];
|
|
22
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
23
|
+
get: ((k) => from[k]).bind(null, key),
|
|
24
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return to;
|
|
28
|
+
};
|
|
29
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
30
|
+
value: mod,
|
|
31
|
+
enumerable: true
|
|
32
|
+
}) : target, mod));
|
|
33
|
+
var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
|
|
34
|
+
//#endregion
|
|
35
|
+
export { __toESM as i, __exportAll as n, __require as r, __commonJSMin as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { s as loadSerenityConfig, t as DEFAULT_SERENITY_CONFIG_PATHS } from "./ccc-
|
|
1
|
+
import { n as __exportAll } from "./rolldown-runtime-B4iAMlE-.js";
|
|
2
|
+
import { s as loadSerenityConfig, t as DEFAULT_SERENITY_CONFIG_PATHS } from "./ccc-CZUOq3NY.js";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
@@ -302,6 +302,8 @@ var route_exports = /* @__PURE__ */ __exportAll({
|
|
|
302
302
|
hasVoiceItem: () => hasVoiceItem,
|
|
303
303
|
matchWeixinRoute: () => matchWeixinRoute,
|
|
304
304
|
nextWeixinAccountId: () => nextWeixinAccountId,
|
|
305
|
+
readFeishuCredential: () => readFeishuCredential,
|
|
306
|
+
readImSettings: () => readImSettings,
|
|
305
307
|
readWeixinCredential: () => readWeixinCredential,
|
|
306
308
|
readWeixinSettings: () => readWeixinSettings,
|
|
307
309
|
removeWeixinAccount: () => removeWeixinAccount,
|
|
@@ -324,7 +326,7 @@ function accountKeyPart(accountId) {
|
|
|
324
326
|
* 微信桥 skiff 会话 id 前缀(守卫识别"外部面"用)。
|
|
325
327
|
*
|
|
326
328
|
* ⚠️ **2026-10-19 起它只是命名习惯,不再是判据** —— skiff 的身份是**轨迹**,
|
|
327
|
-
* 判据 = 「绑定的轨迹有 `skiff.json`」(`
|
|
329
|
+
* 判据 = 「绑定的轨迹有 `skiff.json`」(`trajectory/policy/profile.ts` 的 `isSkiffSession`)。
|
|
328
330
|
* 保留前缀只为:① 日志/会话列表里一眼认出这是外部面;② 存量会话目录名不变。
|
|
329
331
|
*/
|
|
330
332
|
const WEIXIN_SESSION_PREFIX = "skiff-weixin-";
|
|
@@ -367,43 +369,88 @@ function routeTarget(row) {
|
|
|
367
369
|
return "";
|
|
368
370
|
}
|
|
369
371
|
/**
|
|
370
|
-
*
|
|
371
|
-
*
|
|
372
|
+
* **统一 IM 配置的单一读取入口**(2026-10-19 owner 定向:微信与飞书只是账号实现不同,
|
|
373
|
+
* 整合到统一配置)。
|
|
374
|
+
*
|
|
375
|
+
* 读取顺序(**确定性,只有这一处**):
|
|
376
|
+
* ① `im` 段 —— 但**判据是 `accounts` 是数组**,不是"段存在"(见下 🔴)
|
|
377
|
+
* ② 旧 `weixin` 段 —— 存量 CCC 零迁移
|
|
378
|
+
* ③ 都没有 ⇒ 归一默认(`enabled:false`、空数组)
|
|
379
|
+
*
|
|
380
|
+
* 🔴 **为什么判据是「`accounts` 是数组」**:本 CCC 的配置里**曾经**有过一个 `im` 段
|
|
381
|
+
* (退役的 ACP 形态:`{channel:"acp", acp:{enabled, accounts:[…]}}`)。若只判"段存在",
|
|
382
|
+
* 那份残留会被当成新配置读 ⇒ 得到一个没有 `accounts` 数组 / 或 `accounts` 形状完全不同的对象
|
|
383
|
+
* ⇒ 表现为**"配置没生效"且不报错**。⇒ 用可判别的形状把它排除掉(退役残留继续被静默忽略,
|
|
384
|
+
* 与 v1.59.0 的裁决一致)。
|
|
385
|
+
*
|
|
386
|
+
* ⚠️ 本函数**只做归一**,不判断"这个通道实现有没有"——那是装配处的事
|
|
387
|
+
* (`syncMachinePollers` 里有"未实现的 channel 出声但不静默跳过")。
|
|
372
388
|
*/
|
|
373
|
-
function
|
|
389
|
+
function readImSettings(root, paths = DEFAULT_SERENITY_CONFIG_PATHS) {
|
|
390
|
+
const empty = () => ({
|
|
391
|
+
enabled: false,
|
|
392
|
+
accounts: [],
|
|
393
|
+
routes: []
|
|
394
|
+
});
|
|
374
395
|
try {
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
return {
|
|
382
|
-
enabled: w.enabled === true,
|
|
383
|
-
botType: typeof w.botType === "string" && w.botType !== "" ? w.botType : void 0,
|
|
384
|
-
hook: typeof w.hook === "string" && w.hook.trim() !== "" ? w.hook.trim() : void 0,
|
|
385
|
-
autoReplyWithLastMessage: w.autoReplyWithLastMessage !== false,
|
|
386
|
-
fallbackOnNoSend: w.fallbackOnNoSend === true,
|
|
387
|
-
accounts: Array.isArray(w.accounts) ? w.accounts.filter((a) => typeof a === "object" && a !== null && typeof a.accountId === "string" && a.accountId !== "").map((a) => ({
|
|
388
|
-
accountId: a.accountId,
|
|
389
|
-
name: typeof a.name === "string" ? a.name : void 0,
|
|
390
|
-
enabled: a.enabled !== false
|
|
391
|
-
})) : [],
|
|
392
|
-
routes: Array.isArray(w.routes) ? w.routes.filter((r) => typeof r === "object" && r !== null && typeof r.user === "string" && r.user !== "" && typeof routeTarget(r) === "string").map((r) => ({
|
|
393
|
-
user: r.user,
|
|
394
|
-
trajectory: routeTarget(r)
|
|
395
|
-
})) : [],
|
|
396
|
-
aliases: readAliases(w)
|
|
397
|
-
};
|
|
396
|
+
const cfg = loadSerenityConfig(root, paths);
|
|
397
|
+
const unified = cfg.im;
|
|
398
|
+
if (isUnifiedImSection(unified)) return normalizeImSection(unified, empty());
|
|
399
|
+
const legacy = cfg.weixin;
|
|
400
|
+
if (!legacy || typeof legacy !== "object") return empty();
|
|
401
|
+
return normalizeImSection(legacy, empty());
|
|
398
402
|
} catch {
|
|
399
|
-
return
|
|
400
|
-
enabled: false,
|
|
401
|
-
accounts: [],
|
|
402
|
-
routes: []
|
|
403
|
-
};
|
|
403
|
+
return empty();
|
|
404
404
|
}
|
|
405
405
|
}
|
|
406
406
|
/**
|
|
407
|
+
* 判别一个 `im` 段是不是**新的统一形态**。
|
|
408
|
+
*
|
|
409
|
+
* 判据 = `accounts` 是数组 **且** 每行(若有)不带退役 ACP 的 `accountId` 之外的 ACP 形状;
|
|
410
|
+
* 退役 ACP 形态的特征是顶层有 `channel:"acp"` 或 `acp` 对象。
|
|
411
|
+
* ⇒ 两者**任一命中**即判为"退役残留",不认。
|
|
412
|
+
*/
|
|
413
|
+
function isUnifiedImSection(v) {
|
|
414
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return false;
|
|
415
|
+
const obj = v;
|
|
416
|
+
if (obj.acp !== void 0 && (typeof obj.acp === "object" || typeof obj.acp === "string")) return false;
|
|
417
|
+
if (obj.channel === "acp") return false;
|
|
418
|
+
return Array.isArray(obj.accounts);
|
|
419
|
+
}
|
|
420
|
+
/** 段 → 归一形态(统一段与旧段**共用同一套归一语义**,避免两条读法各漂) */
|
|
421
|
+
function normalizeImSection(w, d) {
|
|
422
|
+
const src = w;
|
|
423
|
+
const accountsIn = Array.isArray(src.accounts) ? src.accounts : [];
|
|
424
|
+
return {
|
|
425
|
+
enabled: src.enabled === true,
|
|
426
|
+
botType: typeof src.botType === "string" && src.botType !== "" ? src.botType : void 0,
|
|
427
|
+
hook: typeof src.hook === "string" && src.hook.trim() !== "" ? src.hook.trim() : void 0,
|
|
428
|
+
autoReplyWithLastMessage: src.autoReplyWithLastMessage !== false,
|
|
429
|
+
fallbackOnNoSend: src.fallbackOnNoSend === true,
|
|
430
|
+
accounts: accountsIn.filter((a) => typeof a === "object" && a !== null && typeof a.accountId === "string" && a.accountId !== "").map((a) => ({
|
|
431
|
+
accountId: a.accountId,
|
|
432
|
+
channel: typeof a.channel === "string" && a.channel.trim() !== "" ? a.channel.trim() : "weixin",
|
|
433
|
+
name: typeof a.name === "string" ? a.name : void 0,
|
|
434
|
+
enabled: a.enabled !== false
|
|
435
|
+
})),
|
|
436
|
+
routes: Array.isArray(src.routes) ? src.routes.filter((r) => typeof r === "object" && r !== null && typeof r.user === "string" && r.user !== "" && typeof routeTarget(r) === "string").map((r) => ({
|
|
437
|
+
user: r.user,
|
|
438
|
+
trajectory: routeTarget(r)
|
|
439
|
+
})) : [],
|
|
440
|
+
aliases: readAliases(src)
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* 读取 CCC 微信桥配置(未配置/未启用 → 归一默认)。
|
|
445
|
+
*
|
|
446
|
+
* ⚠️ 2026-10-19 起它是 {@link readImSettings} 的**薄别名**(签名与返回形状不变):
|
|
447
|
+
* 旧调用点无需改动,但**配置来源已经统一**——`im` 段优先、`weixin` 段回退。
|
|
448
|
+
* 保留名字是为了让既有调用点与测试**逐字不动**(P1 是纯重构,读数必须不变)。
|
|
449
|
+
*/
|
|
450
|
+
function readWeixinSettings(root, paths = DEFAULT_SERENITY_CONFIG_PATHS) {
|
|
451
|
+
return readImSettings(root, paths);
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
407
454
|
* 别名表清洗(v1.56.10):键归一为小写、值必须是非空字符串;非法项静默丢弃。
|
|
408
455
|
* 空/缺省 → `{}`(此时别名解析不可用,只能用裸 iLink 用户 id)。
|
|
409
456
|
*/
|
|
@@ -446,6 +493,20 @@ function clearWeixinCredential(root, accountId) {
|
|
|
446
493
|
unsetEntry(root, "credential", lsKey(accountId, "BASEURL"));
|
|
447
494
|
unsetEntry(root, "credential", lsKey(accountId, "USERID"));
|
|
448
495
|
}
|
|
496
|
+
/** 飞书凭据键(credential scope: FEISHU_<ACCOUNT_ID>_<FIELD>) */
|
|
497
|
+
function feishuLsKey(accountId, field) {
|
|
498
|
+
return `FEISHU_${accountKeyPart(accountId)}_${field}`;
|
|
499
|
+
}
|
|
500
|
+
/** 读取飞书账号凭据(appId 或 appSecret 缺失 → null——账号未绑定) */
|
|
501
|
+
function readFeishuCredential(root, accountId) {
|
|
502
|
+
const appId = getEntry(root, "credential", feishuLsKey(accountId, "APPID"));
|
|
503
|
+
const appSecret = getEntry(root, "credential", feishuLsKey(accountId, "SECRET"));
|
|
504
|
+
if (!appId || !appSecret) return null;
|
|
505
|
+
return {
|
|
506
|
+
appId,
|
|
507
|
+
appSecret
|
|
508
|
+
};
|
|
509
|
+
}
|
|
449
510
|
/**
|
|
450
511
|
* 路由匹配:exact user 优先,通配 `*` 兜底。
|
|
451
512
|
* @returns 命中的**轨迹编码**;未命中 → null(无路由 → 消息不回复/忽略)
|
|
@@ -594,4 +655,4 @@ function setWeixinEnabled(root, enabled) {
|
|
|
594
655
|
return next;
|
|
595
656
|
}
|
|
596
657
|
//#endregion
|
|
597
|
-
export {
|
|
658
|
+
export { runLocalStore as _, readFeishuCredential as a, route_exports as c, weixinSessionIdForTrajectory as d, LOCALSTORE_SCOPES as f, readStore as g, readGitTrack as h, matchWeixinRoute as i, sanitizeFileName as l, localstorePath as m, extractWeixinText as n, readWeixinCredential as o, checkLocalstoreGitCompliance as p, hasVoiceItem as r, readWeixinSettings as s, extractWeixinMedia as t, weixinInboundDir as u };
|
package/lib/seams/guards.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import type { Context } from 'cordis';
|
|
10
10
|
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
11
11
|
import { type BlacklistRule } from '../kernel/ccc.js';
|
|
12
|
-
import { type SkiffProfile } from '../
|
|
12
|
+
import { type SkiffProfile } from '../trajectory/policy/profile.js';
|
|
13
13
|
export interface GuardInput {
|
|
14
14
|
root: string;
|
|
15
15
|
toolName: string;
|
|
@@ -109,7 +109,9 @@ export declare function sessionBlock(root: string, scope?: string): string;
|
|
|
109
109
|
* Principles 剥离 MSM 原则段(指令遵循约束)——用户文本承接两处风格;本体论/关系段/
|
|
110
110
|
* 操作边界(安全硬约束)永远保留。未配置 → 与 v1.23.0 逐字节一致(零影响)。
|
|
111
111
|
*/
|
|
112
|
-
export declare function serenitySystemPrompt(root: string, scope?: string
|
|
112
|
+
export declare function serenitySystemPrompt(root: string, scope?: string,
|
|
113
|
+
/** 活跃轨迹目录名(给了才有第 ⑧ 段;未绑定轨迹 ⇒ undefined,不注入) */
|
|
114
|
+
dirName?: string): string;
|
|
113
115
|
/**
|
|
114
116
|
* Code Mode 适配行:当前 scope 以 Code Mode 呈现工具时(run_code 可见),
|
|
115
117
|
* ACC 块按 native 语义指引"直接调用工具"会与"只有 run_code 可直接调用"的执行
|
|
@@ -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-BhoA7G-0.js";
|
|
2
|
+
import { _ as resolveInside, g as readUtf8 } from "./ccc-CZUOq3NY.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,20 +48,26 @@ 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
59
|
* | `./profile.ts` | **判据 + 读盘**("这是不是 skiff"、"约束面是什么") |
|
|
60
|
-
* | `./
|
|
61
|
-
* |
|
|
60
|
+
* | `./rules.ts`(本文件) | **从约束面派生出的纯函数**(白名单集合、提示词读取器、基础提示词文本) |
|
|
61
|
+
* | `../session-create.ts` | 会话创建/复用、提问、守门查询 |
|
|
62
62
|
*
|
|
63
63
|
* ⇒ 本文件**不再读 `serenity.json`**:`skiff.roles` 整段已退役(owner 2026-10-19 重做)。
|
|
64
64
|
* 它只接收一个已解析好的 `SkiffProfile`,因此**不涉及任何 IO**(除提示词文件,那是刻意懒读的)。
|
|
65
|
+
*
|
|
66
|
+
* ## S12(2026-10-19,轨迹中心重构)
|
|
67
|
+
*
|
|
68
|
+
* 原名 `role/skiff/config.ts`。改名理由(框架 §6.3「角色不是一个概念,是一段历史」):
|
|
69
|
+
* 它派生的是**某条轨迹的约束面**,与"配置读取"无关(本文件零配置读取,见上一段)
|
|
70
|
+
* ⇒ `config` 这个名字描述的是**它曾经的样子**,`rules` 描述它**现在做的事**。
|
|
65
71
|
*/
|
|
66
72
|
/** 白名单推导 ────────────────────────────────────────────────────────────── */
|
|
67
73
|
/** 提示词来源提示串(`apply` 回执与面板共用;避免两处措辞漂) */
|
|
@@ -202,57 +208,6 @@ function buildSkiffBasePrompt(code) {
|
|
|
202
208
|
].join("\n");
|
|
203
209
|
}
|
|
204
210
|
//#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
211
|
//#region src/surface/settings.ts
|
|
257
212
|
/**
|
|
258
213
|
* 设置面板命名空间 = **profile 条目 id**(v0.1.7 起;与旧 `settings.yaml` 段名逐字相同)。
|
|
@@ -263,8 +218,6 @@ function defaultSimpleSettings() {
|
|
|
263
218
|
return {
|
|
264
219
|
gatewayEnabled: false,
|
|
265
220
|
rebuildThresholdK: 400,
|
|
266
|
-
skiffEnabled: false,
|
|
267
|
-
skiffDebugPort: SKIFF_DEBUG_PORT,
|
|
268
221
|
croEnabled: true,
|
|
269
222
|
diagramEnabled: false,
|
|
270
223
|
humanChannel: defaultHumanChannelSettings()
|
|
@@ -358,8 +311,6 @@ function simpleSettingsFromConfig(config) {
|
|
|
358
311
|
return {
|
|
359
312
|
gatewayEnabled: unwrapVolatile(config.gatewayEnabled) ?? config.gateway?.enabled ?? d.gatewayEnabled,
|
|
360
313
|
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
314
|
croEnabled: unwrapVolatile(config.croEnabled) ?? d.croEnabled,
|
|
364
315
|
diagramEnabled: unwrapVolatile(config.diagramEnabled) ?? config.diagram?.enabled ?? d.diagramEnabled,
|
|
365
316
|
humanChannel: humanChannelSettingsFromConfig(config.humanChannel)
|
|
@@ -400,4 +351,4 @@ function registerSettingsSection(ctx, config) {
|
|
|
400
351
|
} catch {}
|
|
401
352
|
}
|
|
402
353
|
//#endregion
|
|
403
|
-
export {
|
|
354
|
+
export { buildSkiffBasePrompt as a, profileMsmWhitelist as c, resolveProfileSystemPrompt as d, ACC_VERSION as f, SKIFF_PROFILE_HINT as i, profileSystemPromptSource as l, readSimpleSettings as n, createProfilePromptReader as o, findPackageRoot as p, registerSettingsSection as r, profileCognitiveTrajectory 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 记号);取不到 ⇒ 留空,**不编**;
|
|
@@ -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,
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* surface/text.ts — 输出文本的清洗原语(**纯函数,零 listener、零宿主依赖**,可独立单测)
|
|
3
|
+
*
|
|
4
|
+
* ## 为什么它从调试面里拆出来(S11,2026-10-19,轨迹中心重构)
|
|
5
|
+
*
|
|
6
|
+
* 拆之前它是 `role/skiff/debug.ts` 的**后半段**,而那份文件是**混装件**:
|
|
7
|
+
* · 前半段 = **面 D** 的 HTTP 调试页(自起 listener,端口见 `kernel/ports.ts`)
|
|
8
|
+
* · 后半段 = **通用文本清洗**(本文件,已随重构搬到 `surface/text.ts`)
|
|
9
|
+
*
|
|
10
|
+
* 判据(实测,不是猜):本文件的导出被**两个与 skiff 无关的模块**直接使用 ——
|
|
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 renderSkiffMarkdown(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
|
*
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* trajectory/carrier.ts — 等待 agent 空闲(含销毁竞速,S142 review F-08)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* ## 为什么在 `trajectory/` 而不是某个委派子域(S14,2026-10-19,轨迹中心重构)
|
|
5
|
+
*
|
|
6
|
+
* 它的两个消费者分属**不同的层**:`trajectory/session.ts`(轨迹的载体管理)与
|
|
7
|
+
* `cheap-worker`(轨迹 × 轨迹的委派)。⇒ 它**不是哪一家的私有件**,
|
|
8
|
+
* 而是"载体这一轮跑完没有"这个问题的**公共原语**——凡与载体打交道的地方都可能在用。
|
|
9
|
+
*
|
|
10
|
+
* 🔴 名字从 `idle` 改为 `carrier`:`idle` 描述的是**状态**(宿主 agent 空闲),
|
|
11
|
+
* 而本模块回答的是**关于载体的问题**(它空闲了/它被销毁了/会话先没了)。
|
|
12
|
+
* 三个结算条件(见下)里有两条与"空闲"无关 —— 名字取窄了会误导调用方以为只需等 idle。
|
|
13
|
+
*
|
|
14
|
+
* 为什么单独成模块:`askSkiff`(问答)与 `cheap-worker`(杂工循环)都要"等这一轮做完",
|
|
5
15
|
* 此前各自复制了一份只监听 `agent/status → idle` 的实现。该实现有一个静默挂死:
|
|
6
16
|
* **agent 先被销毁(会话关闭/进程回收/显式 dispose)就永远不会再发 idle 事件**,
|
|
7
17
|
* 等待方 Promise 永不结算 → 问答/杂工永久卡住(宿主的 disposal 语义:
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* trajectory/delegate/core.ts — cheap-worker(杂工)纯逻辑层(零 DSH 依赖,可独立单测)
|
|
3
3
|
*
|
|
4
4
|
* 🆕 2026-10-14(owner 令「删除后台运行能力」):**进度文件 / stop token / 轮次循环**整族已退场 ——
|
|
5
5
|
* 它们**只**服务于 background 模式。本模块现存 = 前台委派真正需要的三件:
|
|
6
6
|
* 模型串解析 / 白名单校验 / provider 可用性判读(+ 使用指引文本)。
|
|
7
|
+
*
|
|
8
|
+
* ## S14(2026-10-19,轨迹中心重构):此前位于 `role/worker/` 下(该目录已消失)
|
|
9
|
+
*
|
|
10
|
+
* 落点 = `trajectory/delegate/`。判据(判读表 §3.1):它是**轨迹 × 轨迹**那种合法形态 ——
|
|
11
|
+
* 主语是「主轨迹把活交给子 agent」,既不是某一条轨迹的切面,也不是容器宪法。
|
|
12
|
+
* ⚠️ 它**不属于** `policy/`:policy 管"这条轨迹允许什么",本模块管"一条轨迹怎么把活派出去"。
|
|
7
13
|
*/
|
|
8
14
|
/** 解析 model 字符串(provider/model)→ {provider, model};无 / 视为 model-only */
|
|
9
15
|
export declare function splitModel(model: string): {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* trajectory/delegate/preset.ts — cheap-worker worker 的 preset 继承 + 工具面收窄(纯函数,可单测)
|
|
3
3
|
*
|
|
4
4
|
* v1.24.0:loop → cheap-worker 重命名。对齐 subagent 先例(applyChildComposition →
|
|
5
5
|
* agentPresets.composeFrom):cheap-worker worker 在创建窗口内 join 发起方 agent 的 standing
|
|
@@ -16,7 +16,14 @@
|
|
|
16
16
|
* (在 agent 未发布前执行 composeFrom + restrict,失败由创建事务回滚)。
|
|
17
17
|
*
|
|
18
18
|
* 仅依赖 cordis 的 Context 类型(type-only,运行时擦除)——保持可被 vitest
|
|
19
|
-
* 直接加载(与 kernel/ccc.ts /
|
|
19
|
+
* 直接加载(与 kernel/ccc.ts / trajectory/delegate/core.ts 同级的纯模块约定)。
|
|
20
|
+
*
|
|
21
|
+
* ## S14(2026-10-19,轨迹中心重构):此前位于 `role/worker/` 下(该目录已消失)
|
|
22
|
+
*
|
|
23
|
+
* 落点 = `trajectory/delegate/`,与 `./core.ts` 同域。这里的"preset 继承"是**委派关系**的
|
|
24
|
+
* 一部分(子 agent join 父的 standing preset),主语仍是"主轨迹怎么把活派出去"。
|
|
25
|
+
* 🔴 递归防护(`deny: ['cheap-worker']`)也住在这里 —— 它是委派**方向的守卫**,不是容器宪法:
|
|
26
|
+
* 换一条轨迹,它照样生效,但它约束的是"派出去之后再派"这件事。
|
|
20
27
|
*/
|
|
21
28
|
import type { Context } from 'cordis';
|
|
22
29
|
/** 从父 agent ctx 解析 preset 继承的创建期组合。 */
|