@shgroup/dsh-serenity-hooks 1.34.0 → 1.34.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dsh.plugin.json +1 -1
- package/lib/acp-core.d.ts +2 -22
- package/lib/acp-http.d.ts +8 -0
- package/lib/api.d.ts +12 -4
- package/lib/autopilot-chain.d.ts +76 -0
- package/lib/autopilot-core-DCRkiWEe.js +229 -0
- package/lib/autopilot-core.d.ts +132 -0
- package/lib/autopilot-ops.d.ts +48 -0
- package/lib/autopilot-trajectory-D9Znxo75.js +782 -0
- package/lib/autopilot-trajectory.d.ts +64 -97
- package/lib/ccc-roots-Bd_SjEs7.js +152 -0
- package/lib/ccc-roots.d.ts +105 -0
- package/lib/ccc.d.ts +3 -6
- package/lib/client.js +2 -2
- package/lib/clock-runtime.d.ts +197 -0
- package/lib/config-ops.d.ts +9 -14
- package/lib/constants.d.ts +0 -2
- package/lib/container-status.d.ts +183 -0
- package/lib/diag-ops.d.ts +25 -10
- package/lib/face-host.d.ts +110 -0
- package/lib/fs-ops.d.ts +3 -2
- package/lib/gateway-auth.d.ts +2 -5
- package/lib/gateway.d.ts +0 -34
- package/lib/git-ops.d.ts +3 -2
- package/lib/handyman-ops.d.ts +3 -2
- package/lib/handyman-preset-inherit.d.ts +2 -1
- package/lib/host/access.d.ts +8 -7
- package/lib/host/contract.d.ts +17 -6
- package/lib/host/type-contract.d.ts +1 -2
- package/lib/im-bridge.d.ts +6 -5
- package/lib/index.js +8345 -5607
- package/lib/invariant.d.ts +0 -15
- package/lib/invariant.js +1 -1
- package/lib/kit-ops.d.ts +11 -31
- package/lib/localstore-ops.d.ts +3 -17
- package/lib/msm-ops.d.ts +34 -52
- package/lib/opencode-provider.d.ts +4 -5
- package/lib/output-guard-seam.d.ts +0 -3
- package/lib/output-guard.d.ts +12 -3
- package/lib/ports.d.ts +59 -0
- package/lib/rebuild.d.ts +1 -1
- package/lib/seams/bootstrap.d.ts +4 -3
- package/lib/seams/compact.d.ts +2 -1
- package/lib/seams/context.d.ts +2 -4
- package/lib/seams/env.d.ts +2 -1
- package/lib/seams/guards.d.ts +4 -43
- package/lib/seams/keeper.d.ts +1 -1
- package/lib/seams/system-prompt.d.ts +1 -5
- package/lib/session-cleanup.d.ts +3 -2
- package/lib/{settings-section-BuPGQv_H.js → settings-section-DTYZjwUs.js} +65 -9
- package/lib/settings-section.d.ts +3 -31
- package/lib/skiff-core.d.ts +4 -9
- package/lib/skiff-debug.d.ts +15 -21
- package/lib/skiff-registry-FTjoWQTQ.js +25 -0
- package/lib/skiff-registry.d.ts +2 -1
- package/lib/{skiff-role-DAfPb6YQ.js → skiff-role-CEHL5cek.js} +1 -1
- package/lib/skiff-role.d.ts +2 -2
- package/lib/skills/opencode-scan.d.ts +3 -2
- package/lib/skills-discovery.d.ts +15 -2
- package/lib/status.d.ts +2 -1
- package/lib/tools/cce.d.ts +1 -2
- package/lib/tools/container-admin.d.ts +7 -3
- package/lib/tools/eap.d.ts +2 -3
- package/lib/tools/handyman.d.ts +0 -29
- package/lib/tools/msm.d.ts +0 -4
- package/lib/tools/neat.d.ts +1 -2
- package/lib/tools/praxis.d.ts +0 -1
- package/lib/tools/skiff-admin.d.ts +2 -2
- package/lib/tools/trajectory.d.ts +7 -15
- package/lib/totp.d.ts +0 -4
- package/lib/trajectory-assistant.d.ts +2 -1
- package/lib/trajectory-bound-Cax1p9ut.js +190 -0
- package/lib/trajectory-bound.d.ts +3 -4
- package/lib/{trajectory-bound-C8DUxi6_.js → trajectory-ops-mrXK0H0I.js} +2 -159
- package/lib/trajectory-ops.d.ts +4 -9
- package/lib/trajectory-skills.d.ts +71 -0
- package/lib/{wake-registry-D0Vj0WXb.js → wake-registry-CYxIb484.js} +7 -20
- package/lib/wake-registry.d.ts +3 -11
- package/lib/wake-scheduler.d.ts +13 -49
- package/lib/web-fetch-provider.d.ts +0 -21
- package/lib/{weixin-api-PjEhmjlZ.js → weixin-api-CtFYm53S.js} +3 -9
- package/lib/weixin-api.d.ts +6 -37
- package/lib/weixin-bridge.d.ts +5 -24
- package/lib/weixin-hook.d.ts +6 -12
- package/lib/weixin-output-guard.d.ts +2 -1
- package/lib/{weixin-route-D1ND823E.js → weixin-route-B2ajFypI.js} +4 -5
- package/lib/weixin-route.d.ts +0 -2
- package/lib/weixin-send-api.d.ts +15 -6
- package/package.json +2 -4
- package/experiments/autopilot-trajectory/SKILL.md +0 -115
- package/experiments/autopilot-trajectory/scripts/autopilot-trajectory.ts +0 -546
- package/lib/autopilot-script.d.ts +0 -40
- package/lib/skiff-debug-D83-Njy7.js +0 -2867
- package/lib/{ccc-eu_IPF94.js → ccc-NlLr_sxy.js} +1 -1
- package/lib/{session-cleanup-CMT4mHWt.js → session-cleanup-B6IHZgww.js} +1 -1
package/README.md
CHANGED
|
@@ -275,6 +275,7 @@ DSH 一个进程可以同时带多个工作区,每个工作区各自对接自
|
|
|
275
275
|
- **多个工作区各自独立**:每个工作区自己的间隔/会话/焦点/窗口,互不干扰
|
|
276
276
|
- **有审计**:每次唤醒都记一笔,面板里能看到最近几次;失败会指数退避重试
|
|
277
277
|
- **还能预约未来某一刻**:用 `container_trajectory wake-later` 登记一条"唤醒"= 未来某时刻 + 一条消息——可以给自己预约,也可以唤醒别的轨迹;落在工作区内的 `AGENT_SESSIONS/wake-registry.json`(可读可审计),到点由中心调度器投递,不阻塞、不等待、也不回执
|
|
278
|
+
- **轨迹可以自带 skill**:在它的 `SESSION.md` 顶部 frontmatter 写 `skills: [名字, …]`,这条轨迹**被绑定期间**的每个请求都会注入这些 skill 的全文(适合把某个领域的做事方法直接挂在轨迹上);skill 名来自工作区数据,**先过安全校验才会用于拼路径**,找不到会在提示里明说"缺失"而**不静默跳过**
|
|
278
279
|
- 没有"每天最多唤醒几次"的限制——频率只由间隔和窗口决定
|
|
279
280
|
|
|
280
281
|
### 6.6 安全模型
|
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-serenity-hooks",
|
|
3
|
-
"version": "1.34.
|
|
3
|
+
"version": "1.34.1",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——11 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/im-bridge/acc-diag;后两个按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 轨迹日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/trajectory 唤醒注册表。适配 DSH 0.1.5-rc.2(deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
package/lib/acp-core.d.ts
CHANGED
|
@@ -17,14 +17,7 @@
|
|
|
17
17
|
* 未启用时本模块零副作用(无监听、无 agent)。
|
|
18
18
|
*/
|
|
19
19
|
import type { Context } from 'cordis';
|
|
20
|
-
|
|
21
|
-
export interface JsonRpcRequest {
|
|
22
|
-
jsonrpc: '2.0';
|
|
23
|
-
id?: string | number;
|
|
24
|
-
method: string;
|
|
25
|
-
params?: Record<string, unknown>;
|
|
26
|
-
}
|
|
27
|
-
export interface JsonRpcResponse {
|
|
20
|
+
interface JsonRpcResponse {
|
|
28
21
|
jsonrpc: '2.0';
|
|
29
22
|
id: string | number | null;
|
|
30
23
|
result?: unknown;
|
|
@@ -34,11 +27,6 @@ export interface JsonRpcResponse {
|
|
|
34
27
|
data?: unknown;
|
|
35
28
|
};
|
|
36
29
|
}
|
|
37
|
-
export interface JsonRpcNotification {
|
|
38
|
-
jsonrpc: '2.0';
|
|
39
|
-
method: string;
|
|
40
|
-
params?: Record<string, unknown>;
|
|
41
|
-
}
|
|
42
30
|
/** JSON-RPC 错误码(对齐标准) */
|
|
43
31
|
export declare const RPC_ERROR: {
|
|
44
32
|
readonly PARSE: -32700;
|
|
@@ -47,13 +35,6 @@ export declare const RPC_ERROR: {
|
|
|
47
35
|
readonly INVALID_PARAMS: -32602;
|
|
48
36
|
readonly INTERNAL: -32603;
|
|
49
37
|
};
|
|
50
|
-
export interface AcpSessionHandle {
|
|
51
|
-
sessionId: string;
|
|
52
|
-
role: string;
|
|
53
|
-
ccc: string;
|
|
54
|
-
/** 会话是否可复用(进程内延续) */
|
|
55
|
-
continued: boolean;
|
|
56
|
-
}
|
|
57
38
|
/**
|
|
58
39
|
* ACP 会话管理器:持有 skiff agent 会话(与 skiff-core 注册表同源——
|
|
59
40
|
* 创建走 createSkiffAgent(自动注册),关闭走 unregisterSkiffSession)。
|
|
@@ -96,5 +77,4 @@ export declare class RpcInvalidParams extends Error {
|
|
|
96
77
|
* @returns 响应帧数组(请求有响应;通知无;解析失败 → 单错误响应)
|
|
97
78
|
*/
|
|
98
79
|
export declare function dispatchRpc(server: AcpServer, frame: unknown): Promise<JsonRpcResponse[]>;
|
|
99
|
-
|
|
100
|
-
export type { SessionId };
|
|
80
|
+
export {};
|
package/lib/acp-http.d.ts
CHANGED
|
@@ -17,10 +17,18 @@
|
|
|
17
17
|
* 实验性质:未开启时零资源占用(无监听、无 agent 创建)。
|
|
18
18
|
*/
|
|
19
19
|
import type { Context } from 'cordis';
|
|
20
|
+
import { type FaceSpec } from './face-host.js';
|
|
20
21
|
export declare function acpHttpActive(): boolean;
|
|
21
22
|
export declare function acpHttpPort(): number | null;
|
|
23
|
+
/**
|
|
24
|
+
* 本面的规格(C4 块 A/④:**只提供** name/port/host/enabled/handler)。
|
|
25
|
+
* 两个子面(ACP JSON-RPC / 对外问答页)的路由与鉴权仍全部归 {@link handle}——
|
|
26
|
+
* 面宿主不介入面语义,也**不合并** D/E 两面(两者共用会话核心但各有独立 listener/路由/HTML)。
|
|
27
|
+
*/
|
|
28
|
+
export declare function acpHttpSpec(ctx: Context, port: number, defaultRoot?: string): FaceSpec;
|
|
22
29
|
/**
|
|
23
30
|
* 启动 ACP HTTP JSON-RPC + 建议问答页服务(单实例;重复启动幂等返回既有实例)。
|
|
31
|
+
* C4 块 A:listener 的创建/监听/错误/端口占用/关闭归 `face-host`。
|
|
24
32
|
* @param ctx 插件上下文(AcpServer 内部经 skiff-core 创建 agent)
|
|
25
33
|
* @param port 监听端口(仅 127.0.0.1)
|
|
26
34
|
* @param defaultRoot 默认 CCC 根(问答页候选发现兜底;resolveSkiffRoot 传入)
|
package/lib/api.d.ts
CHANGED
|
@@ -10,13 +10,11 @@
|
|
|
10
10
|
* 经 ctx.webServer(webserver 服务,公开版由 httpServer 改名)注册;客户端与服务器同源,调用无信任围栏问题。
|
|
11
11
|
*/
|
|
12
12
|
import type { Context } from 'cordis';
|
|
13
|
+
import type { IncomingMessage } from 'node:http';
|
|
13
14
|
/** 图片落盘目录(CCC 根相对;S142 图片自动识别基础设施——粘贴图片落盘供 agent 经 CCC vlm MSM 自主处理) */
|
|
14
15
|
export declare const IMAGE_UPLOAD_DIR = "_tmp/images_from_user";
|
|
15
|
-
export declare const IMAGE_MEDIA_TYPES: Set<string>;
|
|
16
16
|
/** 文件落盘目录(CCC 根相对;v1.24.1 粘贴任意文件自动落盘——agent 经 CCC 既有 MSM(pdf-extract/archive-extract 等)自主处理) */
|
|
17
17
|
export declare const FILE_UPLOAD_DIR = "_tmp/files_from_user";
|
|
18
|
-
/** 拒绝的可执行/危险扩展名(安全边界:不落盘可执行文件,防 agent 被诱导执行) */
|
|
19
|
-
export declare const BLOCKED_FILE_EXTS: Set<string>;
|
|
20
18
|
/**
|
|
21
19
|
* 图片落盘核心逻辑(可测):校验 mediaType 白名单 + base64 解码 + 大小上限 →
|
|
22
20
|
* 写 CCC 根 _tmp/images_from_user/<ts>-<rand>.<ext>,返回相对路径。
|
|
@@ -34,7 +32,16 @@ export declare function sanitizeFileName(name: string): string;
|
|
|
34
32
|
* 校验失败抛 Error(handler 转 400)。
|
|
35
33
|
*/
|
|
36
34
|
export declare function saveFileToTmp(root: string, fileName: string, data: string): string;
|
|
37
|
-
|
|
35
|
+
/**
|
|
36
|
+
* WebUI 专属动作的来源判别(C4 块 C:此前 **9 处内联** `req.headers['x-serenity-ui'] !== '1'`)。
|
|
37
|
+
*
|
|
38
|
+
* ⚠️ 语义边界(勿误读为认证):这是**客户端判别头**——任何本机能发 HTTP 的进程都可自带它
|
|
39
|
+
* (无密钥、无签名、不校验来源,见现状取证 §② 面 A "认证与守卫")。它区分的是
|
|
40
|
+
* "WebUI 触发的动作"与"agent/curl 触发的动作"(如 safe-mode 不可由 agent 自行开关)。
|
|
41
|
+
* 本 helper 只做**同一判据的归一**,不放宽也不收紧:判据、状态码、文案均由调用方给出。
|
|
42
|
+
*/
|
|
43
|
+
export declare function senderIsWebUi(req: IncomingMessage): boolean;
|
|
44
|
+
interface StatusApiRegistration {
|
|
38
45
|
configPaths?: string[];
|
|
39
46
|
}
|
|
40
47
|
/**
|
|
@@ -45,3 +52,4 @@ export interface StatusApiRegistration {
|
|
|
45
52
|
*/
|
|
46
53
|
export declare function resolveWorkspaceCore(sessionCwd: string | undefined, workspaceParam: string | undefined, listCwds: () => string[], fallback: string): string;
|
|
47
54
|
export declare function registerStatusApi(ctx: Context, opts?: StatusApiRegistration): void;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* autopilot-chain.ts — **唤起条件链的唯一实现**("为什么这轮没被唤起")
|
|
3
|
+
*
|
|
4
|
+
* 为什么单独成模块(R↓,⑥ C6a 的硬约束):
|
|
5
|
+
* C6 裁决把 autopilot 拆两半——**入口**分两处(CCC 工具面 / 开发面),但**判据只能有一份**。
|
|
6
|
+
* 若开发面另写"文件读取版",刚消掉的分歧会在开发面复活。故:
|
|
7
|
+
* · `acc-diag` ④ 段(进程内,带运行态事实)—— `./diag-ops.ts` 调 {@link buildWakeChain}
|
|
8
|
+
* · 开发面 `dsh-develop diag [--ccc <path>]`(离线 bun 进程,无运行态事实)—— **import 同一实现**
|
|
9
|
+
* 两者的差别**只是传入的 facts**(进程内三项已知 / 离线三项不可知),判据本身不复制。
|
|
10
|
+
*
|
|
11
|
+
* 本模块**零 DSH 依赖**(只 node:fs/path + `ccc.js` + `autopilot-core.js`)——离线 bun 进程
|
|
12
|
+
* 才 import 得动。判据一律取自 {@link judgeWake}(判据唯一真相源),本模块只做**分解与分类**。
|
|
13
|
+
*
|
|
14
|
+
* 判决语义(§12.7 修复,**不得回退**):
|
|
15
|
+
* `✗` = 配置/环境问题(需人改,如 enabled=false / session 未命中 / agent 未加载)
|
|
16
|
+
* `⏸` = 等待中(到点/出窗口/上一轮跑完自会满足——**非**配置问题)
|
|
17
|
+
* `?` = 不可知(离线通道看不到的运行态;**不**当成满足)
|
|
18
|
+
* **只有 `✗` 与 `⏸` 都为空、且无 `?` 时才印 ✅**——旧实现只统计 `✗` ⇒ 每天北京 8~18 点
|
|
19
|
+
* (10 小时)都印「✅ 唤起条件全部满足」而插件实际不唤起(假阳性,已实测复现)。
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* 条件链的**运行态事实**(只有插件进程知道的那部分;离线通道传 null = 不可知)。
|
|
23
|
+
* 由 `autopilot-trajectory.ts` 的 `autopilotRuntimeFacts(ctx, root)` 产出。
|
|
24
|
+
*/
|
|
25
|
+
export interface WakeChainFacts {
|
|
26
|
+
/** 周期自唤醒全局闸(`autopilotGloballyEnabled()`);null = 不可知(离线通道) */
|
|
27
|
+
globalGate: boolean | null;
|
|
28
|
+
/** 该 CCC 是否已有唤起轮在进行中(重入守卫);null = 不可知 */
|
|
29
|
+
running: boolean | null;
|
|
30
|
+
/** live 运行态;null = 不可知(离线通道) */
|
|
31
|
+
live: {
|
|
32
|
+
/** 该 CCC 的 live 会话数 */
|
|
33
|
+
sessionCount: number;
|
|
34
|
+
/** 目标 agent 能否解析;null = 不适用(目标会话未命中,已由 session 条件判 ✗) */
|
|
35
|
+
agentResolved: boolean | null;
|
|
36
|
+
/** agent 不可解析时的诊断文本(`diagnoseTargetUnavailable`) */
|
|
37
|
+
diagnosis: string | null;
|
|
38
|
+
} | null;
|
|
39
|
+
}
|
|
40
|
+
/** 离线通道事实(三项运行态全不可知) */
|
|
41
|
+
export declare const NO_RUNTIME_FACTS: WakeChainFacts;
|
|
42
|
+
/** 判决档(`ready` 只有在**没有** unknowns 时才可能给出——离线通道永远不会印 ✅) */
|
|
43
|
+
export type WakeChainVerdict = 'ready' | 'waiting' | 'blocked' | 'unknown';
|
|
44
|
+
export interface WakeChainReport {
|
|
45
|
+
root: string;
|
|
46
|
+
/** 逐条件行(人读;行首 = ✓/✗/⏸/?/·) */
|
|
47
|
+
lines: string[];
|
|
48
|
+
/** `✗` 行(配置/环境问题,需人改) */
|
|
49
|
+
blockers: string[];
|
|
50
|
+
/** `⏸` 行(等待中) */
|
|
51
|
+
waiting: string[];
|
|
52
|
+
/** `?` 行(不可知——不当作满足) */
|
|
53
|
+
unknowns: string[];
|
|
54
|
+
/** 修复建议(仅在存在阻断点时输出) */
|
|
55
|
+
suggestions: string[];
|
|
56
|
+
verdict: WakeChainVerdict;
|
|
57
|
+
/** 判决行原文 */
|
|
58
|
+
judgement: string;
|
|
59
|
+
}
|
|
60
|
+
/** 运行偏见脚本的注入点(测试可替换;生产 = `fetchBiasContent`——插件 tick 的同一执行路径) */
|
|
61
|
+
export type BiasProbe = (root: string, providerRel: string) => Promise<{
|
|
62
|
+
text: string | null;
|
|
63
|
+
error: string | null;
|
|
64
|
+
}>;
|
|
65
|
+
/**
|
|
66
|
+
* 组装条件链(**唯一实现**)。
|
|
67
|
+
*
|
|
68
|
+
* @param root CCC 根
|
|
69
|
+
* @param facts 运行态事实(离线通道传 {@link NO_RUNTIME_FACTS})
|
|
70
|
+
* @param now 当前时刻(测试注入)
|
|
71
|
+
* @param biasProbe 偏见执行(默认 {@link fetchBiasContent}——**不另写 spawn**)
|
|
72
|
+
* @returns 结构化报告(渲染见 {@link renderWakeChain})
|
|
73
|
+
*/
|
|
74
|
+
export declare function buildWakeChain(root: string, facts?: WakeChainFacts, now?: number, biasProbe?: BiasProbe): Promise<WakeChainReport>;
|
|
75
|
+
/** 条件链渲染(④ 段文本;`renderAccDiag` 与开发面 `diag` 共用) */
|
|
76
|
+
export declare function renderWakeChain(r: WakeChainReport): string;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
+
import { h as resolveInside, s as loadSerenityConfig } from "./ccc-NlLr_sxy.js";
|
|
3
|
+
import { m as sessionsRoot, o as findSession } from "./trajectory-ops-mrXK0H0I.js";
|
|
4
|
+
import { basename, dirname, join } from "node:path";
|
|
5
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
6
|
+
import { spawnSync } from "node:child_process";
|
|
7
|
+
//#region src/autopilot-core.ts
|
|
8
|
+
/**
|
|
9
|
+
* autopilot-core.ts — autopilot **纯判据层**(零 DSH 依赖,可独立单测、可被开发面脚本 import)
|
|
10
|
+
*
|
|
11
|
+
* 为什么单独成模块(R↓,S142 §12.13 ⑥ C6a):
|
|
12
|
+
* C6 裁决把 autopilot 拆两半——**机制那半**(配置读写 / 状态报告 / 偏见执行 / 唤起判据)
|
|
13
|
+
* 进插件进程,**排障那半**(完整条件链)留开发面。但两侧**必须用同一份判据**——若各自
|
|
14
|
+
* 实现一遍,"为什么这轮没唤起"的报告就会与实际唤起行为分歧(这正是旧
|
|
15
|
+
* `experiments/autopilot-trajectory/scripts/autopilot-trajectory.ts` 的病:它只能读文件,
|
|
16
|
+
* 看不到 live 会话 / 全局闸 / agent 可解析性 ⇒ 8 项结构性分歧)。
|
|
17
|
+
*
|
|
18
|
+
* ⇒ 本模块承载**判据原语**(读配置 / 目标定位 / 间隔+窗口判决 / 偏见脚本执行),
|
|
19
|
+
* 由三个消费方共用,**没有任何一方自算**:
|
|
20
|
+
* · tick 与面板 —— `autopilot-trajectory.ts`(`shouldWake` / `getAutopilotStatus`)
|
|
21
|
+
* · CCC 工具面 —— `autopilot-ops.ts`(`container_admin autopilot status|init|generate-bias`)
|
|
22
|
+
* · 条件链报告 —— `autopilot-chain.ts`(`acc-diag` ④ 段 + 开发面 `dsh-develop diag`)
|
|
23
|
+
*
|
|
24
|
+
* 本模块**零 DSH 依赖**(只 node:fs/path/child_process + `ccc.ts` + `trajectory-ops.ts`)
|
|
25
|
+
* ——这是刻意的:开发面 `dsh-develop diag` 是独立 bun 进程,import 不了 cordis/DSH 面。
|
|
26
|
+
*/
|
|
27
|
+
var autopilot_core_exports = /* @__PURE__ */ __exportAll({
|
|
28
|
+
AUTO_DIR_SUFFIX: () => AUTO_DIR_SUFFIX,
|
|
29
|
+
DEFAULT_AVOID_HOURS: () => DEFAULT_AVOID_HOURS,
|
|
30
|
+
DEFAULT_BIAS_PROVIDER: () => DEFAULT_BIAS_PROVIDER,
|
|
31
|
+
LEGACY_BIAS_PROVIDER: () => LEGACY_BIAS_PROVIDER,
|
|
32
|
+
MIN_INTERVAL_HOURS: () => MIN_INTERVAL_HOURS,
|
|
33
|
+
MOTIVATION_MARKER: () => MOTIVATION_MARKER,
|
|
34
|
+
TICK_MINUTES: () => 5,
|
|
35
|
+
TICK_MS: () => TICK_MS,
|
|
36
|
+
beijingHour: () => beijingHour,
|
|
37
|
+
biasProviderAbsPath: () => biasProviderAbsPath,
|
|
38
|
+
fetchBiasContent: () => fetchBiasContent,
|
|
39
|
+
inAllowedWakeWindow: () => inAllowedWakeWindow,
|
|
40
|
+
isAutopilotSession: () => isAutopilotSession,
|
|
41
|
+
judgeWake: () => judgeWake,
|
|
42
|
+
readAutopilotSettings: () => readAutopilotSettings,
|
|
43
|
+
readSelfGeneratedMotivation: () => readSelfGeneratedMotivation,
|
|
44
|
+
readUtf8: () => readUtf8,
|
|
45
|
+
resolveTargetMd: () => resolveTargetMd,
|
|
46
|
+
shouldWake: () => shouldWake
|
|
47
|
+
});
|
|
48
|
+
/** 偏见内容提供者脚本缺省名(CCC 根目录下;正式版 autopilot-bias.ts) */
|
|
49
|
+
const DEFAULT_BIAS_PROVIDER = "autopilot-bias.ts";
|
|
50
|
+
/** 旧默认偏见脚本名(autotrajectory 时代;未显式配置时回退——pangu 等已配置 CCC 零迁移) */
|
|
51
|
+
const LEGACY_BIAS_PROVIDER = "autotrajectory-bias.ts";
|
|
52
|
+
/** 自主轨迹会话目录后缀标志(--auto 保留——简短且历史会话 S060--auto 已存在) */
|
|
53
|
+
const AUTO_DIR_SUFFIX = "--auto";
|
|
54
|
+
/** 调度 tick 周期(5min——用户"tick改为5分钟吧";0.01h 间隔下每 5min 评估一次) */
|
|
55
|
+
const TICK_MS = 3e5;
|
|
56
|
+
/** 间隔下限(支持小数——用户"让它支持小数行吗,这样可以配0.01";0.01h ≈ 36s) */
|
|
57
|
+
const MIN_INTERVAL_HOURS = .01;
|
|
58
|
+
/** SESSION.md 内「下一轮动机」段标记(自生偏见载体——轨迹预设自己的未来) */
|
|
59
|
+
const MOTIVATION_MARKER = "下一轮动机";
|
|
60
|
+
/** 缺省避开的高峰时段(北京时间 [start, end) 不唤起——用量峰谷省钱) */
|
|
61
|
+
const DEFAULT_AVOID_HOURS = {
|
|
62
|
+
start: 8,
|
|
63
|
+
end: 18
|
|
64
|
+
};
|
|
65
|
+
/** 偏见脚本输出上限(沙箱:截断防失控——正式版 v1.27.4) */
|
|
66
|
+
const BIAS_OUTPUT_MAX = 8192;
|
|
67
|
+
/** 偏见脚本执行超时(正式版沙箱;原 600s 过长阻塞 tick) */
|
|
68
|
+
const BIAS_RUN_TIMEOUT_MS = 6e4;
|
|
69
|
+
/** 读配置:`trajectory.autopilot`(D58 新键)优先 → 旧键 autopilotTrajectory → 旧键 autotrajectory */
|
|
70
|
+
function readAutopilotSettings(root) {
|
|
71
|
+
const cfg = loadSerenityConfig(root);
|
|
72
|
+
return cfg.trajectory?.autopilot ?? cfg.autopilotTrajectory ?? cfg.autotrajectory ?? null;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 北京时间(UTC+8)当前小时——不依赖服务器时区(服务器可能 UTC/本地任意)。
|
|
76
|
+
*/
|
|
77
|
+
function beijingHour(nowMs) {
|
|
78
|
+
return Math.floor((nowMs + 288e5) % 864e5 / 36e5);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 唤起窗口判定:北京时间 [avoidStart, avoidEnd) 内不唤起(缺省 8~18)。
|
|
82
|
+
* 单段避开(start<=end):窗口 = [0,start) ∪ [end,24);跨零点避开(start>end):窗口 = [end,start)。
|
|
83
|
+
*/
|
|
84
|
+
function inAllowedWakeWindow(nowMs, avoid) {
|
|
85
|
+
const start = avoid?.start ?? DEFAULT_AVOID_HOURS.start;
|
|
86
|
+
const end = avoid?.end ?? DEFAULT_AVOID_HOURS.end;
|
|
87
|
+
const h = beijingHour(nowMs);
|
|
88
|
+
if (start <= end) return h < start || h >= end;
|
|
89
|
+
return h >= end && h < start;
|
|
90
|
+
}
|
|
91
|
+
/** 标志位判定:SESSION.md 所在目录名以 --auto 结尾 → 自主轨迹形态 */
|
|
92
|
+
function isAutopilotSession(mdPath) {
|
|
93
|
+
return basename(dirname(mdPath)).endsWith(AUTO_DIR_SUFFIX);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 目标会话定位:**必须配置 cfg.session**(S###/目录名)——CCC 日常有多条 trajectory 在跑,
|
|
97
|
+
* 绝不默认唤起(缺省最近活跃会误伤其他正在运行的轨迹;用户拍板:必须配置才生效)。
|
|
98
|
+
* 未配置 session 或未命中 → null(不唤起)。
|
|
99
|
+
*/
|
|
100
|
+
function resolveTargetMd(root, cfg) {
|
|
101
|
+
if (!cfg?.session) return null;
|
|
102
|
+
const found = findSession(sessionsRoot(root), cfg.session);
|
|
103
|
+
if (!found) return null;
|
|
104
|
+
const md = join(found.path, "SESSION.md");
|
|
105
|
+
return existsSync(md) ? md : null;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* **唤起判据唯一真相源**(间隔 + 窗口):`shouldWake`(tick / 面板)、`autopilot-ops`
|
|
109
|
+
* (status/check)、`autopilot-chain`(条件链)三处共用本函数——**没有任何一方自算**。
|
|
110
|
+
*
|
|
111
|
+
* 为什么必须共用(v1.34.1 事故留档):旧实现在同一个脚本里存在**两份判断**——
|
|
112
|
+
* `status()` 算 `intervalOk && windowOk` 而条件链的判决行只统计 `✗` 开头项,把 `⏸`
|
|
113
|
+
* (间隔未到 / 高峰避开)排除在阻断之外 ⇒ **每天北京 8~18 点(10 小时)都印
|
|
114
|
+
* 「✅ 唤起条件全部满足」而插件实际不唤起**(假阳性,已实测复现)。合成一处后不可能再分叉。
|
|
115
|
+
*
|
|
116
|
+
* 间隔下限取 `MIN_INTERVAL_HOURS`(=0.01,与 tick 同源)。旧脚本取 `1`(`SCRIPT_MIN_INTERVAL_HOURS`)
|
|
117
|
+
* ——那会让配置 `intervalHours < 1` 的 CCC 在报告里**假阴性**(报"未到"而插件已唤起);
|
|
118
|
+
* 该分歧随独立脚本退场一并消失(报告与真实唤起行为同源,正是本轮的目标)。
|
|
119
|
+
*/
|
|
120
|
+
function judgeWake(settings, mdPath, now = Date.now()) {
|
|
121
|
+
const interval = Math.max(MIN_INTERVAL_HOURS, settings?.intervalHours ?? 12);
|
|
122
|
+
let idleHours = null;
|
|
123
|
+
if (mdPath) try {
|
|
124
|
+
idleHours = (now - statSync(mdPath).mtimeMs) / 36e5;
|
|
125
|
+
} catch {
|
|
126
|
+
idleHours = null;
|
|
127
|
+
}
|
|
128
|
+
const intervalOk = idleHours !== null && idleHours >= interval;
|
|
129
|
+
const windowOk = inAllowedWakeWindow(now, settings?.avoidWakeHours);
|
|
130
|
+
return {
|
|
131
|
+
interval,
|
|
132
|
+
idleHours,
|
|
133
|
+
intervalOk,
|
|
134
|
+
windowOk,
|
|
135
|
+
wakeable: intervalOk && windowOk
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* 唤起条件(纯逻辑,可测):enabled + 未在运行 + 目录标志 + mtime 超间隔 + 窗口允许。
|
|
140
|
+
* v1.27.12:移除每日唤起预算上限(用户"把这个上限删了吧,没意义"——高频实验不受限)。
|
|
141
|
+
*
|
|
142
|
+
* 判据来源全部来自本模块(`judgeWake` / `isAutopilotSession`)——本函数只做**组合**,
|
|
143
|
+
* 不重复实现时间/窗口计算。
|
|
144
|
+
*/
|
|
145
|
+
function shouldWake(settings, mdPath, nowMs, running, _history = []) {
|
|
146
|
+
if (!settings?.enabled || running) return false;
|
|
147
|
+
if (!mdPath || !isAutopilotSession(mdPath)) return false;
|
|
148
|
+
return judgeWake(settings, mdPath, nowMs).wakeable;
|
|
149
|
+
}
|
|
150
|
+
/** 自生动机读取:SESSION.md「下一轮动机」段内容(到下一个二级标题或文件尾;无 → null) */
|
|
151
|
+
function readSelfGeneratedMotivation(mdPath) {
|
|
152
|
+
try {
|
|
153
|
+
const content = readFileSync(mdPath, "utf-8");
|
|
154
|
+
const idx = content.indexOf(MOTIVATION_MARKER);
|
|
155
|
+
if (idx < 0) return null;
|
|
156
|
+
const rest = content.slice(idx + 5);
|
|
157
|
+
const nextHeading = rest.search(/\n## /);
|
|
158
|
+
return (nextHeading >= 0 ? rest.slice(0, nextHeading) : rest).trim() || null;
|
|
159
|
+
} catch {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* 偏见内容:直接运行 CCC 根目录下偏见提供者脚本(biasProvider,缺省 autopilot-bias.ts;
|
|
165
|
+
* 未显式配置且新默认缺失 → 回退旧默认 autotrajectory-bias.ts——pangu 兼容)→ stdout。
|
|
166
|
+
* 脚本缺失 → 返回 { text: null, error: 提示实现 }(唤起侧报错要求实现,不静默跳过)。
|
|
167
|
+
* 路径逃逸校验(resolveInside);bun 优先,node 兜底;**60s 超时 + 8KB 输出截断(沙箱)**。
|
|
168
|
+
*
|
|
169
|
+
* 唯一执行点(不另写 spawn):tick 的唤起路径(`performAutopilotWake`)、`container_admin
|
|
170
|
+
* autopilot generate-bias`、条件链的偏见就绪探测**三处都调本函数**(§12.13:`random` → 复用
|
|
171
|
+
* 插件 tick 里既有的偏见执行代码)。旧脚本另有一套 spawn 且**参数不同**(600s 超时、无 8KB
|
|
172
|
+
* 截断、无旧默认名回退)⇒ 那是"bias 运行参数"与"仅存旧名 bias 脚本时报假阴性"两项分歧的由来。
|
|
173
|
+
*/
|
|
174
|
+
async function fetchBiasContent(root, providerRel) {
|
|
175
|
+
let scriptAbs;
|
|
176
|
+
try {
|
|
177
|
+
scriptAbs = resolveInside(root, providerRel);
|
|
178
|
+
} catch {
|
|
179
|
+
return {
|
|
180
|
+
text: null,
|
|
181
|
+
error: `biasProvider 路径逃逸(须在 CCC 根内): ${providerRel}`
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
if (!existsSync(scriptAbs) && providerRel === "autopilot-bias.ts") {
|
|
185
|
+
const legacy = resolveInside(root, LEGACY_BIAS_PROVIDER);
|
|
186
|
+
if (existsSync(legacy)) scriptAbs = legacy;
|
|
187
|
+
}
|
|
188
|
+
if (!existsSync(scriptAbs)) return {
|
|
189
|
+
text: null,
|
|
190
|
+
error: `请在 CCC 根目录实现偏见内容提供者脚本: ${providerRel}(或旧默认 ${LEGACY_BIAS_PROVIDER};stdout 输出偏见内容一行;container_admin autopilot init 可生成模板)`
|
|
191
|
+
};
|
|
192
|
+
const runs = [["bun", [scriptAbs]], [process.execPath, [scriptAbs]]];
|
|
193
|
+
for (const [cmd, args] of runs) try {
|
|
194
|
+
const r = spawnSync(cmd, args, {
|
|
195
|
+
encoding: "utf-8",
|
|
196
|
+
timeout: BIAS_RUN_TIMEOUT_MS,
|
|
197
|
+
stdio: [
|
|
198
|
+
"ignore",
|
|
199
|
+
"pipe",
|
|
200
|
+
"pipe"
|
|
201
|
+
]
|
|
202
|
+
});
|
|
203
|
+
if (r.status === 0) return {
|
|
204
|
+
text: (r.stdout ?? "").trim().slice(0, BIAS_OUTPUT_MAX) || null,
|
|
205
|
+
error: null
|
|
206
|
+
};
|
|
207
|
+
if (r.error?.code === "ENOENT") continue;
|
|
208
|
+
return {
|
|
209
|
+
text: null,
|
|
210
|
+
error: `偏见内容提供者脚本执行失败(exit ${r.status ?? "?"}): ${r.stderr?.trim() || r.stdout?.trim() || ""}`
|
|
211
|
+
};
|
|
212
|
+
} catch {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
text: null,
|
|
217
|
+
error: "偏见内容提供者脚本无法运行(bun 与 node 均不可用)"
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/** 偏见提供者脚本绝对路径(根内强制——逃逸拒绝);供文件写入侧(init 生成模板)使用 */
|
|
221
|
+
function biasProviderAbsPath(root, providerRel) {
|
|
222
|
+
return resolveInside(root, providerRel);
|
|
223
|
+
}
|
|
224
|
+
/** 读 UTF-8(去 BOM)——init 写配置前的读回 */
|
|
225
|
+
function readUtf8(p) {
|
|
226
|
+
return readFileSync(p, "utf-8").replace(/^\uFEFF/, "");
|
|
227
|
+
}
|
|
228
|
+
//#endregion
|
|
229
|
+
export { shouldWake as _, TICK_MS as a, biasProviderAbsPath as c, isAutopilotSession as d, judgeWake as f, resolveTargetMd as g, readUtf8 as h, MIN_INTERVAL_HOURS as i, fetchBiasContent as l, readSelfGeneratedMotivation as m, DEFAULT_AVOID_HOURS as n, autopilot_core_exports as o, readAutopilotSettings as p, DEFAULT_BIAS_PROVIDER as r, beijingHour as s, AUTO_DIR_SUFFIX as t, inAllowedWakeWindow as u };
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* autopilot-core.ts — autopilot **纯判据层**(零 DSH 依赖,可独立单测、可被开发面脚本 import)
|
|
3
|
+
*
|
|
4
|
+
* 为什么单独成模块(R↓,S142 §12.13 ⑥ C6a):
|
|
5
|
+
* C6 裁决把 autopilot 拆两半——**机制那半**(配置读写 / 状态报告 / 偏见执行 / 唤起判据)
|
|
6
|
+
* 进插件进程,**排障那半**(完整条件链)留开发面。但两侧**必须用同一份判据**——若各自
|
|
7
|
+
* 实现一遍,"为什么这轮没唤起"的报告就会与实际唤起行为分歧(这正是旧
|
|
8
|
+
* `experiments/autopilot-trajectory/scripts/autopilot-trajectory.ts` 的病:它只能读文件,
|
|
9
|
+
* 看不到 live 会话 / 全局闸 / agent 可解析性 ⇒ 8 项结构性分歧)。
|
|
10
|
+
*
|
|
11
|
+
* ⇒ 本模块承载**判据原语**(读配置 / 目标定位 / 间隔+窗口判决 / 偏见脚本执行),
|
|
12
|
+
* 由三个消费方共用,**没有任何一方自算**:
|
|
13
|
+
* · tick 与面板 —— `autopilot-trajectory.ts`(`shouldWake` / `getAutopilotStatus`)
|
|
14
|
+
* · CCC 工具面 —— `autopilot-ops.ts`(`container_admin autopilot status|init|generate-bias`)
|
|
15
|
+
* · 条件链报告 —— `autopilot-chain.ts`(`acc-diag` ④ 段 + 开发面 `dsh-develop diag`)
|
|
16
|
+
*
|
|
17
|
+
* 本模块**零 DSH 依赖**(只 node:fs/path/child_process + `ccc.ts` + `trajectory-ops.ts`)
|
|
18
|
+
* ——这是刻意的:开发面 `dsh-develop diag` 是独立 bun 进程,import 不了 cordis/DSH 面。
|
|
19
|
+
*/
|
|
20
|
+
import { type AutopilotTrajectorySettings } from './ccc.js';
|
|
21
|
+
/** 偏见内容提供者脚本缺省名(CCC 根目录下;正式版 autopilot-bias.ts) */
|
|
22
|
+
export declare const DEFAULT_BIAS_PROVIDER = "autopilot-bias.ts";
|
|
23
|
+
/** 旧默认偏见脚本名(autotrajectory 时代;未显式配置时回退——pangu 等已配置 CCC 零迁移) */
|
|
24
|
+
export declare const LEGACY_BIAS_PROVIDER = "autotrajectory-bias.ts";
|
|
25
|
+
/** 自主轨迹会话目录后缀标志(--auto 保留——简短且历史会话 S060--auto 已存在) */
|
|
26
|
+
export declare const AUTO_DIR_SUFFIX = "--auto";
|
|
27
|
+
/** 调度 tick 周期(5min——用户"tick改为5分钟吧";0.01h 间隔下每 5min 评估一次) */
|
|
28
|
+
export declare const TICK_MS: number;
|
|
29
|
+
/**
|
|
30
|
+
* tick 周期(分钟)——**报告文案的唯一来源**:此前脚本文案写死 `10min`,与插件 `TICK_MS`
|
|
31
|
+
* (5min)不符,用户看到"等下个 10min tick"而实际 5min(§12.7 文案纠错)。由 `TICK_MS` 派生。
|
|
32
|
+
*/
|
|
33
|
+
export declare const TICK_MINUTES: number;
|
|
34
|
+
/** 间隔下限(支持小数——用户"让它支持小数行吗,这样可以配0.01";0.01h ≈ 36s) */
|
|
35
|
+
export declare const MIN_INTERVAL_HOURS = 0.01;
|
|
36
|
+
/** SESSION.md 内「下一轮动机」段标记(自生偏见载体——轨迹预设自己的未来) */
|
|
37
|
+
export declare const MOTIVATION_MARKER = "\u4E0B\u4E00\u8F6E\u52A8\u673A";
|
|
38
|
+
/** 缺省避开的高峰时段(北京时间 [start, end) 不唤起——用量峰谷省钱) */
|
|
39
|
+
export declare const DEFAULT_AVOID_HOURS: {
|
|
40
|
+
start: number;
|
|
41
|
+
end: number;
|
|
42
|
+
};
|
|
43
|
+
/** 读配置:`trajectory.autopilot`(D58 新键)优先 → 旧键 autopilotTrajectory → 旧键 autotrajectory */
|
|
44
|
+
export declare function readAutopilotSettings(root: string): AutopilotTrajectorySettings | null;
|
|
45
|
+
/**
|
|
46
|
+
* 北京时间(UTC+8)当前小时——不依赖服务器时区(服务器可能 UTC/本地任意)。
|
|
47
|
+
*/
|
|
48
|
+
export declare function beijingHour(nowMs: number): number;
|
|
49
|
+
/**
|
|
50
|
+
* 唤起窗口判定:北京时间 [avoidStart, avoidEnd) 内不唤起(缺省 8~18)。
|
|
51
|
+
* 单段避开(start<=end):窗口 = [0,start) ∪ [end,24);跨零点避开(start>end):窗口 = [end,start)。
|
|
52
|
+
*/
|
|
53
|
+
export declare function inAllowedWakeWindow(nowMs: number, avoid?: {
|
|
54
|
+
start?: number;
|
|
55
|
+
end?: number;
|
|
56
|
+
}): boolean;
|
|
57
|
+
/** 标志位判定:SESSION.md 所在目录名以 --auto 结尾 → 自主轨迹形态 */
|
|
58
|
+
export declare function isAutopilotSession(mdPath: string): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* 目标会话定位:**必须配置 cfg.session**(S###/目录名)——CCC 日常有多条 trajectory 在跑,
|
|
61
|
+
* 绝不默认唤起(缺省最近活跃会误伤其他正在运行的轨迹;用户拍板:必须配置才生效)。
|
|
62
|
+
* 未配置 session 或未命中 → null(不唤起)。
|
|
63
|
+
*/
|
|
64
|
+
export declare function resolveTargetMd(root: string, cfg: AutopilotTrajectorySettings): string | null;
|
|
65
|
+
/** 两次唤起之间的"等待"判据结果(`judgeWake` 返回值) */
|
|
66
|
+
export interface WakeJudge {
|
|
67
|
+
/** 生效的间隔阈值(小时;下限 `MIN_INTERVAL_HOURS`) */
|
|
68
|
+
interval: number;
|
|
69
|
+
/** 距上次轨迹活动(小时);目标会话不存在/不可 stat 时为 null */
|
|
70
|
+
idleHours: number | null;
|
|
71
|
+
/** 间隔条件是否满足 */
|
|
72
|
+
intervalOk: boolean;
|
|
73
|
+
/** 是否在允许唤起的窗口内 */
|
|
74
|
+
windowOk: boolean;
|
|
75
|
+
/** 两条件同时满足("此刻到点了") */
|
|
76
|
+
wakeable: boolean;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* **唤起判据唯一真相源**(间隔 + 窗口):`shouldWake`(tick / 面板)、`autopilot-ops`
|
|
80
|
+
* (status/check)、`autopilot-chain`(条件链)三处共用本函数——**没有任何一方自算**。
|
|
81
|
+
*
|
|
82
|
+
* 为什么必须共用(v1.34.1 事故留档):旧实现在同一个脚本里存在**两份判断**——
|
|
83
|
+
* `status()` 算 `intervalOk && windowOk` 而条件链的判决行只统计 `✗` 开头项,把 `⏸`
|
|
84
|
+
* (间隔未到 / 高峰避开)排除在阻断之外 ⇒ **每天北京 8~18 点(10 小时)都印
|
|
85
|
+
* 「✅ 唤起条件全部满足」而插件实际不唤起**(假阳性,已实测复现)。合成一处后不可能再分叉。
|
|
86
|
+
*
|
|
87
|
+
* 间隔下限取 `MIN_INTERVAL_HOURS`(=0.01,与 tick 同源)。旧脚本取 `1`(`SCRIPT_MIN_INTERVAL_HOURS`)
|
|
88
|
+
* ——那会让配置 `intervalHours < 1` 的 CCC 在报告里**假阴性**(报"未到"而插件已唤起);
|
|
89
|
+
* 该分歧随独立脚本退场一并消失(报告与真实唤起行为同源,正是本轮的目标)。
|
|
90
|
+
*/
|
|
91
|
+
export declare function judgeWake(settings: {
|
|
92
|
+
intervalHours?: number;
|
|
93
|
+
avoidWakeHours?: {
|
|
94
|
+
start?: number;
|
|
95
|
+
end?: number;
|
|
96
|
+
};
|
|
97
|
+
} | null, mdPath: string | null, now?: number): WakeJudge;
|
|
98
|
+
/** 审计记录(每 CCC ring buffer——正式版 v1.27.4:可回看、可分析) */
|
|
99
|
+
export interface WakeRecord {
|
|
100
|
+
time: number;
|
|
101
|
+
ok: boolean;
|
|
102
|
+
detail: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* 唤起条件(纯逻辑,可测):enabled + 未在运行 + 目录标志 + mtime 超间隔 + 窗口允许。
|
|
106
|
+
* v1.27.12:移除每日唤起预算上限(用户"把这个上限删了吧,没意义"——高频实验不受限)。
|
|
107
|
+
*
|
|
108
|
+
* 判据来源全部来自本模块(`judgeWake` / `isAutopilotSession`)——本函数只做**组合**,
|
|
109
|
+
* 不重复实现时间/窗口计算。
|
|
110
|
+
*/
|
|
111
|
+
export declare function shouldWake(settings: AutopilotTrajectorySettings, mdPath: string | null, nowMs: number, running: boolean, _history?: readonly WakeRecord[]): boolean;
|
|
112
|
+
/** 自生动机读取:SESSION.md「下一轮动机」段内容(到下一个二级标题或文件尾;无 → null) */
|
|
113
|
+
export declare function readSelfGeneratedMotivation(mdPath: string): string | null;
|
|
114
|
+
/**
|
|
115
|
+
* 偏见内容:直接运行 CCC 根目录下偏见提供者脚本(biasProvider,缺省 autopilot-bias.ts;
|
|
116
|
+
* 未显式配置且新默认缺失 → 回退旧默认 autotrajectory-bias.ts——pangu 兼容)→ stdout。
|
|
117
|
+
* 脚本缺失 → 返回 { text: null, error: 提示实现 }(唤起侧报错要求实现,不静默跳过)。
|
|
118
|
+
* 路径逃逸校验(resolveInside);bun 优先,node 兜底;**60s 超时 + 8KB 输出截断(沙箱)**。
|
|
119
|
+
*
|
|
120
|
+
* 唯一执行点(不另写 spawn):tick 的唤起路径(`performAutopilotWake`)、`container_admin
|
|
121
|
+
* autopilot generate-bias`、条件链的偏见就绪探测**三处都调本函数**(§12.13:`random` → 复用
|
|
122
|
+
* 插件 tick 里既有的偏见执行代码)。旧脚本另有一套 spawn 且**参数不同**(600s 超时、无 8KB
|
|
123
|
+
* 截断、无旧默认名回退)⇒ 那是"bias 运行参数"与"仅存旧名 bias 脚本时报假阴性"两项分歧的由来。
|
|
124
|
+
*/
|
|
125
|
+
export declare function fetchBiasContent(root: string, providerRel: string): Promise<{
|
|
126
|
+
text: string | null;
|
|
127
|
+
error: string | null;
|
|
128
|
+
}>;
|
|
129
|
+
/** 偏见提供者脚本绝对路径(根内强制——逃逸拒绝);供文件写入侧(init 生成模板)使用 */
|
|
130
|
+
export declare function biasProviderAbsPath(root: string, providerRel: string): string;
|
|
131
|
+
/** 读 UTF-8(去 BOM)——init 写配置前的读回 */
|
|
132
|
+
export declare function readUtf8(p: string): string;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* autopilot-ops.ts — `container_admin autopilot` 三动作的**进程内实现**(⑥ C6a 块 A)
|
|
3
|
+
*
|
|
4
|
+
* 为什么搬到进程内(R↓,S142 §12.8 裁决「拆两半、退掉独立脚本」):
|
|
5
|
+
* 三个动作(`status` / `init` / `generate-bias`)的逻辑原先**全在**独立脚本
|
|
6
|
+
* `experiments/autopilot-trajectory/scripts/autopilot-trajectory.ts` 里,插件只 spawn 转发。
|
|
7
|
+
* 该脚本是独立进程 ⇒ **只能读文件** ⇒ 看不到全局闸 / live 会话 / agent 可解析性 ⇒
|
|
8
|
+
* 它印出的"状态"与插件实际行为**结构性分歧**(8 项,见现状稿 §4.4;含"闸关着也印 ✅"
|
|
9
|
+
* 这种用户可见的假报告)。搬进进程内后,`status`/`check` 读的就是
|
|
10
|
+
* {@link autopilotRuntimeFacts}——**与 tick 同一份判据**。
|
|
11
|
+
*
|
|
12
|
+
* 三个动作(对外名字与语义不变):
|
|
13
|
+
* · `status` —— 一站式全报告:背景 + 就绪检查(条件链)+ 进程态 + 状态快照 + 下一步 + 指引
|
|
14
|
+
* · `init` —— 写/迁移 CCC 配置 `trajectory.autopilot`(**迁移后删旧键**)+ 生成偏见脚本模板
|
|
15
|
+
* · `generate-bias` —— 运行偏见提供者脚本,输出本轮偏见内容(**复用 tick 的 `fetchBiasContent`**)
|
|
16
|
+
*
|
|
17
|
+
* 边界(**不碰 tick**):本模块只做"报告 / 配置 / 跑偏见",**不参与**真正的唤起决策——
|
|
18
|
+
* 唤起决策仍在 `autopilot-trajectory.ts` 的 tick(D59 单例语义、串行链、per-CCC 重入守卫未动)。
|
|
19
|
+
*/
|
|
20
|
+
import type { Context } from 'cordis';
|
|
21
|
+
import { type WakeChainReport } from './autopilot-chain.js';
|
|
22
|
+
/** 一次动作的结果(`container_admin` 直接透出;`error` 非空即失败,不静默) */
|
|
23
|
+
export interface AutopilotActionResult {
|
|
24
|
+
action: 'status' | 'init' | 'generate-bias';
|
|
25
|
+
output: string;
|
|
26
|
+
error?: string;
|
|
27
|
+
}
|
|
28
|
+
/** 就绪检查(= 旧脚本 `check`):条件链的逐条件报告 + 判决(判据单一真相源 = `buildWakeChain`) */
|
|
29
|
+
export declare function autopilotCheck(root: string, ctx?: Context): Promise<WakeChainReport>;
|
|
30
|
+
/**
|
|
31
|
+
* `status` —— 一站式全报告(背景 + 就绪检查 + 进程态 + 状态 + 下一步 + 指引)。
|
|
32
|
+
* 由进程内数据组装(旧实现是 `bun` 子进程跑脚本,故看不到任何运行态)。
|
|
33
|
+
*/
|
|
34
|
+
export declare function autopilotStatus(root: string, ctx?: Context): Promise<AutopilotActionResult>;
|
|
35
|
+
/**
|
|
36
|
+
* `init` —— 写/迁移 CCC 配置 + 生成偏见脚本模板。
|
|
37
|
+
*
|
|
38
|
+
* 迁移语义(沿用旧脚本,理由写在码内):写入**新键** `trajectory.autopilot`(D58);
|
|
39
|
+
* 旧键 `autopilotTrajectory` / `autotrajectory` 存在则**迁移并删除**——保留两处会形成
|
|
40
|
+
* "改了不生效"的双真相源(读侧新键优先,旧键是死数据)。
|
|
41
|
+
*/
|
|
42
|
+
export declare function autopilotInit(root: string): AutopilotActionResult;
|
|
43
|
+
/**
|
|
44
|
+
* `generate-bias` —— 运行偏见提供者脚本并打印本轮内容(验证用)。
|
|
45
|
+
* **复用 tick 的 {@link fetchBiasContent}**(同一份执行代码:60s 超时 / 8KB 截断 /
|
|
46
|
+
* 旧默认名回退)——不另写 spawn(§12.13)。
|
|
47
|
+
*/
|
|
48
|
+
export declare function autopilotGenerateBias(root: string): Promise<AutopilotActionResult>;
|