@shgroup/dsh-serenity-hooks 1.30.13 → 1.30.15
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-serenity-hooks",
|
|
3
|
-
"version": "1.30.
|
|
3
|
+
"version": "1.30.15",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——10 个工具(container_fs/logbook/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/autopilot-trajectory)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 工作日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/自主巡航。适配 DSH 0.1.2-rc.1(deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
package/lib/ccc.d.ts
CHANGED
|
@@ -178,6 +178,15 @@ export interface WeixinRouteConfig {
|
|
|
178
178
|
export interface SkiffRoleConfig {
|
|
179
179
|
/** 角色模型(provider/model;CCC 直接指定,无白名单校验——用户拍板) */
|
|
180
180
|
model?: string;
|
|
181
|
+
/**
|
|
182
|
+
* 角色类型(v1.30.15,S142 用户拍板"skiff 应该区分的类型是临时和长期"):
|
|
183
|
+
* - `temporary`:临时 skiff——不绑定 trajectory(无 SESSION.md 工作台),
|
|
184
|
+
* 提示词按创建时快照注入("注入发生一次")。
|
|
185
|
+
* - `persistent`:长期 skiff——绑定 trajectory(自动建/恢复 SESSION.md 工作台),
|
|
186
|
+
* 提示词**每轮动态重读文件**(改 `systemPromptFile` 即生效,无需重启)。
|
|
187
|
+
* 缺省(未写)= 隐式推断:调用方传入稳定 sessionId → persistent,否则 temporary。
|
|
188
|
+
*/
|
|
189
|
+
kind?: 'temporary' | 'persistent';
|
|
181
190
|
/** MSM 白名单(独立):该角色可 exec 的 MSM 名列表;缺省空 = 无 MSM 通道 */
|
|
182
191
|
msms?: string[];
|
|
183
192
|
/** 非 MSM 工具白名单(独立):平台/ACC 工具名列表;缺省空 = 仅 MSM 通道 */
|
|
@@ -191,7 +200,8 @@ export interface SkiffRoleConfig {
|
|
|
191
200
|
/** 角色系统提示词(CCC 完整定义:人格/认知边界/回答风格) */
|
|
192
201
|
systemPrompt?: string;
|
|
193
202
|
/** 角色系统提示词文件(推荐:相对 CCC 根引用 md 文件——超长提示词在 JSON 内嵌不可读;
|
|
194
|
-
* 优先于 systemPrompt;文件缺失/逃逸 → resolveRoleSystemPrompt
|
|
203
|
+
* 优先于 systemPrompt;文件缺失/逃逸 → resolveRoleSystemPrompt 抛错。
|
|
204
|
+
* persistent 型每轮重读(mtime 缓存),改文件即生效) */
|
|
195
205
|
systemPromptFile?: string;
|
|
196
206
|
}
|
|
197
207
|
/**
|
package/lib/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
2
|
import { a as findSerenityRoot, c as matchBlacklist, d as readCccName$2, f as readHandymanConfig, i as findGitRoot, l as pathInside, m as resolveInside, n as SAFE_MODE_MARKER, o as isSafeModeOn, r as classifyPath, s as loadSerenityConfig, t as DEFAULT_SERENITY_CONFIG_PATHS, u as readBlacklist } from "./ccc-DAsSHsub.js";
|
|
3
|
-
import { a as
|
|
4
|
-
import { A as skiffRoleFor, C as listActiveHandymen, D as splitModel, E as requireWhitelistedModel, O as writeFailedStatus, S as handymanProgressPaths, T as readProgress, _ as unregisterSkiffSession, a as startSkiffDebugServer, b as HANDYMAN_GUIDE, c as askSkiff, d as ensureWorkspacePromptSection, f as getSkiffAgent, g as skiffTrajectoryEnabled, h as skiffSessionSnapshot, k as writeProgress, l as createSkiffAgent, m as skiffSessionInfo, n as jscSafeJsonText, o as stopSkiffDebugServer, p as skiffMsmGate, r as renderSkiffMarkdown, s as stripThink, t as discoverCccs, u as ensureSkiffSession, v as workspaceTrajectoryLine, w as newStopToken, x as buildRoundPrompt, y as waitAgentIdle } from "./skiff-debug-
|
|
3
|
+
import { a as readSkiffRoles, d as systemPromptSource, i as isSkiffSessionId, l as roleToolWhitelist, o as resolveRoleSystemPrompt } from "./skiff-role-BYvNnwv1.js";
|
|
4
|
+
import { A as skiffRoleFor, C as listActiveHandymen, D as splitModel, E as requireWhitelistedModel, O as writeFailedStatus, S as handymanProgressPaths, T as readProgress, _ as unregisterSkiffSession, a as startSkiffDebugServer, b as HANDYMAN_GUIDE, c as askSkiff, d as ensureWorkspacePromptSection, f as getSkiffAgent, g as skiffTrajectoryEnabled, h as skiffSessionSnapshot, k as writeProgress, l as createSkiffAgent, m as skiffSessionInfo, n as jscSafeJsonText, o as stopSkiffDebugServer, p as skiffMsmGate, r as renderSkiffMarkdown, s as stripThink, t as discoverCccs, u as ensureSkiffSession, v as workspaceTrajectoryLine, w as newStopToken, x as buildRoundPrompt, y as waitAgentIdle } from "./skiff-debug-C5ulZKCa.js";
|
|
5
5
|
import { i as hostSessions, n as hostInjected, o as hostWeb, r as hostService, s as hostWebServer, t as hostAgents } from "./access-dU_vG1q8.js";
|
|
6
6
|
import { a as readWeixinCredential, c as weixinInboundDir, d as LOCALSTORE_SCOPES, f as checkLocalstoreGitCompliance, h as runLocalStore, i as matchWeixinRoute, l as weixinSessionIdFor, m as readGitTrack, n as extractWeixinText, o as readWeixinSettings, p as localstorePath, r as hasVoiceItem, s as sanitizeFileName$1, t as extractWeixinMedia } from "./weixin-route-BD_yYAZz.js";
|
|
7
7
|
import { C as useSession, S as summarize, _ as resolveSessionByTitle, a as archiveSessions, b as setActiveSessionInfo, c as createSession, d as getActiveSessionInfo, f as healthCheck, g as readActiveSessionMd, h as qaCheck, i as SESSION_ACTIONS, l as extractSessionMdPathFromText, m as parseSessionContextFromEvents, n as readLastBound, o as clearActiveSessionInfo, p as listSessions, r as DEFAULT_SESSION_SCOPE, s as closeSession, t as appendBound, u as findSession, v as sessionEvents, x as showSession, y as sessionsRoot } from "./session-bound-BpTayaIS.js";
|
|
@@ -6478,7 +6478,7 @@ function registerStatusApi(ctx, opts = {}) {
|
|
|
6478
6478
|
workspace: url.searchParams.get("workspace") ?? void 0
|
|
6479
6479
|
});
|
|
6480
6480
|
const root = findSerenityRoot(workspace) ?? "";
|
|
6481
|
-
const { discoverCccs } = await import("./skiff-debug-
|
|
6481
|
+
const { discoverCccs } = await import("./skiff-debug-C5ulZKCa.js").then((n) => n.i);
|
|
6482
6482
|
sendJson$2(res, 200, { cccs: await discoverCccs(ctx, root) });
|
|
6483
6483
|
} catch (err) {
|
|
6484
6484
|
sendJson$2(res, 400, { error: err.message ?? String(err) });
|
|
@@ -6675,7 +6675,7 @@ function registerStatusApi(ctx, opts = {}) {
|
|
|
6675
6675
|
return;
|
|
6676
6676
|
}
|
|
6677
6677
|
const { saveWeixinRoutes } = await import("./weixin-route-BD_yYAZz.js").then((n) => n.u);
|
|
6678
|
-
const { readSkiffRoles } = await import("./skiff-role-
|
|
6678
|
+
const { readSkiffRoles } = await import("./skiff-role-BYvNnwv1.js").then((n) => n.u);
|
|
6679
6679
|
const roles = readSkiffRoles(root);
|
|
6680
6680
|
for (const r of routes) if (!roles.has(r.role)) {
|
|
6681
6681
|
sendJson$2(res, 400, { error: `unknown role: ${r.role} (not in ${root} skiff.roles)` });
|
|
@@ -9897,7 +9897,7 @@ function matchCcc(input, candidates) {
|
|
|
9897
9897
|
}
|
|
9898
9898
|
/** 组装候选列表(discoverCccs 投影 + `.serenity` 名;动态 import 保持本模块静态依赖轻量) */
|
|
9899
9899
|
async function collectCandidates(ctx) {
|
|
9900
|
-
const { discoverCccs } = await import("./skiff-debug-
|
|
9900
|
+
const { discoverCccs } = await import("./skiff-debug-C5ulZKCa.js").then((n) => n.i);
|
|
9901
9901
|
const entries = await discoverCccs(ctx, process.cwd());
|
|
9902
9902
|
const seen = /* @__PURE__ */ new Set();
|
|
9903
9903
|
const out = [];
|
|
@@ -10464,12 +10464,20 @@ function apply(ctx, config) {
|
|
|
10464
10464
|
* `root ?? undefined` 而正常启动)。现形态三层触发(用户"锚定要准确"同源要求):
|
|
10465
10465
|
* ① 启动时同步一次 ② 定位失败 → 定时退避重试(1s/3s/8s/20s/40s,共 5 次)
|
|
10466
10466
|
* ③ 首个 live 会话就绪(`agent/session-start` / `session/created`)→ 立即再试一次。
|
|
10467
|
+
*
|
|
10468
|
+
* v1.30.14(重启日志实证后的收敛):**并发启动守卫** + 首次未定位降级为信息级日志。
|
|
10469
|
+
* - 实证(v1.30.13 重启日志):重试定时器与"会话就绪"事件几乎同时触发 → 两次 sync 都
|
|
10470
|
+
* 看到 `started === false` → **两次 start**(第一次绑定成功、第二次 `EADDRINUSE` 刷错误日志)。
|
|
10471
|
+
* → 加 `starting` 在飞标志(启动 Promise settle 前不再重复发起)。
|
|
10472
|
+
* - 首次未定位**不是失败**(apply 时无 live 会话是常态)→ 用 `console.log` 说明"等待 live 会话",
|
|
10473
|
+
* 只有**退避重试耗尽**才 `console.warn` 报错(失败语义只留给真正失败)。
|
|
10467
10474
|
*/
|
|
10468
10475
|
function registerSkiff(ctx) {
|
|
10469
10476
|
let started = false;
|
|
10477
|
+
let starting = false;
|
|
10470
10478
|
let retryTimer = null;
|
|
10471
10479
|
let retries = 0;
|
|
10472
|
-
let
|
|
10480
|
+
let informedRoot = false;
|
|
10473
10481
|
const clearRetry = () => {
|
|
10474
10482
|
if (retryTimer !== null) {
|
|
10475
10483
|
clearTimeout(retryTimer);
|
|
@@ -10478,7 +10486,7 @@ function registerSkiff(ctx) {
|
|
|
10478
10486
|
};
|
|
10479
10487
|
/** 退避重试定位 CCC root(幂等:已有待执行重试则不再排) */
|
|
10480
10488
|
const scheduleRootRetry = () => {
|
|
10481
|
-
if (retryTimer !== null || started) return;
|
|
10489
|
+
if (retryTimer !== null || started || starting) return;
|
|
10482
10490
|
if (retries >= SKIFF_ROOT_RETRY_DELAYS_MS.length) {
|
|
10483
10491
|
console.warn(`[serenity-hooks] ✗ Skiff 调试服务未启动:重试 ${retries} 次仍无法定位 CCC root(进程 cwd 与 live 会话均无 .serenity)`);
|
|
10484
10492
|
return;
|
|
@@ -10493,23 +10501,26 @@ function registerSkiff(ctx) {
|
|
|
10493
10501
|
};
|
|
10494
10502
|
function sync() {
|
|
10495
10503
|
const s = readSimpleSettings();
|
|
10496
|
-
if (s.skiffEnabled && !started) {
|
|
10504
|
+
if (s.skiffEnabled && !started && !starting) {
|
|
10497
10505
|
const root = resolveSkiffRoot(ctx);
|
|
10498
10506
|
if (!root) {
|
|
10499
|
-
if (!
|
|
10500
|
-
|
|
10501
|
-
console.
|
|
10507
|
+
if (!informedRoot) {
|
|
10508
|
+
informedRoot = true;
|
|
10509
|
+
console.log("[serenity-hooks] Skiff 调试服务等待 CCC root(此刻无 live 会话;已排入退避重试,会话就绪即试)");
|
|
10502
10510
|
}
|
|
10503
10511
|
scheduleRootRetry();
|
|
10504
10512
|
return;
|
|
10505
10513
|
}
|
|
10506
10514
|
clearRetry();
|
|
10507
10515
|
const webPort = readWebPort(ctx);
|
|
10516
|
+
starting = true;
|
|
10508
10517
|
startSkiffDebugServer(ctx, root, s.skiffDebugPort, webPort).then(() => {
|
|
10509
10518
|
started = true;
|
|
10510
10519
|
if (retries > 0) console.info(`[serenity-hooks] ✓ Skiff 调试服务已启动(重试 ${retries} 次后定位到 CCC root: ${root})`);
|
|
10511
10520
|
}).catch((err) => {
|
|
10512
10521
|
console.error(`[serenity-hooks] ✗ Skiff 调试服务启动失败: ${String(err?.message ?? err)}`);
|
|
10522
|
+
}).finally(() => {
|
|
10523
|
+
starting = false;
|
|
10513
10524
|
});
|
|
10514
10525
|
} else if (!s.skiffEnabled && started) {
|
|
10515
10526
|
stopSkiffDebugServer();
|
|
@@ -10517,7 +10528,7 @@ function registerSkiff(ctx) {
|
|
|
10517
10528
|
} else if (!s.skiffEnabled) {
|
|
10518
10529
|
clearRetry();
|
|
10519
10530
|
retries = 0;
|
|
10520
|
-
|
|
10531
|
+
informedRoot = false;
|
|
10521
10532
|
}
|
|
10522
10533
|
}
|
|
10523
10534
|
try {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
2
|
import { a as findSerenityRoot, f as readHandymanConfig } from "./ccc-DAsSHsub.js";
|
|
3
|
-
import { a as
|
|
3
|
+
import { a as readSkiffRoles, c as roleMsmWhitelist, f as trajectorySubset, i as isSkiffSessionId, n as buildSkiffBasePrompt, o as resolveRoleSystemPrompt, r as createRolePromptReader, s as resolveSkiffKind } from "./skiff-role-BYvNnwv1.js";
|
|
4
4
|
import { i as hostSessions, r as hostService, t as hostAgents } from "./access-dU_vG1q8.js";
|
|
5
5
|
import { b as setActiveSessionInfo, c as createSession, d as getActiveSessionInfo, n as readLastBound, t as appendBound } from "./session-bound-BpTayaIS.js";
|
|
6
6
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
@@ -458,15 +458,20 @@ async function createSkiffAgent(ctx, root, roleName, role, defaultModel, session
|
|
|
458
458
|
};
|
|
459
459
|
const handle = await createOrResumeAgent(ctx, id, root, model, setup, sessionId !== void 0);
|
|
460
460
|
const agent = handle.agent;
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
461
|
+
const kind = resolveSkiffKind(role, sessionId !== void 0);
|
|
462
|
+
const rolePrompt = kind === "persistent" ? createRolePromptReader(root, role) : (() => {
|
|
463
|
+
let snapshot = "";
|
|
464
|
+
try {
|
|
465
|
+
snapshot = resolveRoleSystemPrompt(root, role);
|
|
466
|
+
} catch (err) {
|
|
467
|
+
console.warn(`[serenity-hooks] skiff 角色 "${roleName}" 系统提示词解析失败(回退仅基础段): ${String(err?.message ?? err)}`);
|
|
468
|
+
}
|
|
469
|
+
return () => snapshot;
|
|
470
|
+
})();
|
|
471
|
+
rolePrompt();
|
|
467
472
|
let workspaceMdPath = null;
|
|
468
473
|
try {
|
|
469
|
-
workspaceMdPath = ensureSkiffSession(root, agent, roleName, role,
|
|
474
|
+
workspaceMdPath = ensureSkiffSession(root, agent, roleName, role, kind === "persistent");
|
|
470
475
|
} catch (err) {
|
|
471
476
|
console.warn(`[serenity-hooks] skiff 角色 "${roleName}" 专属 SESSION 处理失败(不影响 agent 创建): ${String(err?.message ?? err)}`);
|
|
472
477
|
}
|
|
@@ -474,7 +479,7 @@ async function createSkiffAgent(ctx, root, roleName, role, defaultModel, session
|
|
|
474
479
|
agent.ctx.systemPrompt.section({
|
|
475
480
|
name: "serenity-skiff",
|
|
476
481
|
order: -60,
|
|
477
|
-
text: () => [buildSkiffBasePrompt(roleName, role),
|
|
482
|
+
text: () => [buildSkiffBasePrompt(roleName, role), rolePrompt()].filter(Boolean).join("\n")
|
|
478
483
|
});
|
|
479
484
|
} catch (err) {
|
|
480
485
|
console.warn(`[serenity-hooks] skiff 系统提示词注册失败: ${String(err?.message ?? err)}`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
2
|
import { m as resolveInside, p as readUtf8, s as loadSerenityConfig, t as DEFAULT_SERENITY_CONFIG_PATHS } from "./ccc-DAsSHsub.js";
|
|
3
|
-
import { existsSync } from "node:fs";
|
|
3
|
+
import { existsSync, statSync } from "node:fs";
|
|
4
4
|
//#region src/skiff-role.ts
|
|
5
5
|
/**
|
|
6
6
|
* skiff-role.ts — Skiff(F4,v1.25.0 实验性)角色层纯逻辑(零 DSH 依赖,可独立单测)
|
|
@@ -15,9 +15,11 @@ import { existsSync } from "node:fs";
|
|
|
15
15
|
var skiff_role_exports = /* @__PURE__ */ __exportAll({
|
|
16
16
|
SKIFF_SESSION_PREFIX: () => SKIFF_SESSION_PREFIX,
|
|
17
17
|
buildSkiffBasePrompt: () => buildSkiffBasePrompt,
|
|
18
|
+
createRolePromptReader: () => createRolePromptReader,
|
|
18
19
|
isSkiffSessionId: () => isSkiffSessionId,
|
|
19
20
|
readSkiffRoles: () => readSkiffRoles,
|
|
20
21
|
resolveRoleSystemPrompt: () => resolveRoleSystemPrompt,
|
|
22
|
+
resolveSkiffKind: () => resolveSkiffKind,
|
|
21
23
|
roleMsmWhitelist: () => roleMsmWhitelist,
|
|
22
24
|
roleToolWhitelist: () => roleToolWhitelist,
|
|
23
25
|
systemPromptSource: () => systemPromptSource,
|
|
@@ -43,6 +45,7 @@ function readSkiffRoles(root, paths = DEFAULT_SERENITY_CONFIG_PATHS) {
|
|
|
43
45
|
if (name.trim() === "") continue;
|
|
44
46
|
out.set(name.trim(), {
|
|
45
47
|
model: typeof role.model === "string" ? role.model : void 0,
|
|
48
|
+
kind: role.kind === "temporary" || role.kind === "persistent" ? role.kind : void 0,
|
|
46
49
|
msms: Array.isArray(role.msms) ? role.msms.filter((m) => typeof m === "string") : void 0,
|
|
47
50
|
tools: Array.isArray(role.tools) ? role.tools.filter((t) => typeof t === "string") : void 0,
|
|
48
51
|
trajectory: role.trajectory && typeof role.trajectory === "object" ? {
|
|
@@ -103,6 +106,65 @@ function systemPromptSource(role) {
|
|
|
103
106
|
if (role?.systemPrompt?.trim()) return "inline";
|
|
104
107
|
return "none";
|
|
105
108
|
}
|
|
109
|
+
function resolveSkiffKind(role, hasStableId) {
|
|
110
|
+
const k = role?.kind;
|
|
111
|
+
if (k === "temporary" || k === "persistent") return k;
|
|
112
|
+
return hasStableId ? "persistent" : "temporary";
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* 角色提示词**读取器**(v1.30.15,方案 A:长期型热更新)。
|
|
116
|
+
*
|
|
117
|
+
* 为什么是函数而不是字符串(R↓):旧实现 `createSkiffAgent` 在创建时把
|
|
118
|
+
* `resolveRoleSystemPrompt(...)` 的结果**快照**进系统提示词段闭包 → CCC 改了
|
|
119
|
+
* `zhaocai.md` 必须重启 dsh web 才生效(本轮实证:改完 18KB 提示词,live agent 仍用旧文本)。
|
|
120
|
+
* 现形态返回一个读取函数,由系统提示词段的 `text()` **每轮调用**:
|
|
121
|
+
* - `systemPromptFile`:按 **mtime + size** 缓存重读(命中缓存零 IO;未变不解析)
|
|
122
|
+
* → 改文件即生效,**无需重启**;变更时打一行 info 日志(可观测,便于确认热更生效)
|
|
123
|
+
* - 内嵌 `systemPrompt`:静态(JSON 配置改动仍需重启/重载配置)
|
|
124
|
+
* - 读取失败:返回**上次成功内容**(绝不返回空——空提示词会让角色失去人格与纪律),
|
|
125
|
+
* 并按标签去重告警一次
|
|
126
|
+
* @param root CCC 根
|
|
127
|
+
* @param role 角色配置
|
|
128
|
+
*/
|
|
129
|
+
function createRolePromptReader(root, role) {
|
|
130
|
+
const file = role?.systemPromptFile?.trim();
|
|
131
|
+
if (!file) {
|
|
132
|
+
const inline = role?.systemPrompt ?? "";
|
|
133
|
+
return () => inline;
|
|
134
|
+
}
|
|
135
|
+
let abs = null;
|
|
136
|
+
try {
|
|
137
|
+
abs = resolveInside(root, file);
|
|
138
|
+
} catch (err) {
|
|
139
|
+
console.warn(`[serenity-hooks] ✗ skiff 角色提示词路径非法(${file}): ${String(err?.message ?? err)}`);
|
|
140
|
+
}
|
|
141
|
+
if (abs === null) return () => "";
|
|
142
|
+
const absPath = abs;
|
|
143
|
+
let cachedMtime = -1;
|
|
144
|
+
let cachedSize = -1;
|
|
145
|
+
let cachedText = "";
|
|
146
|
+
let warned = false;
|
|
147
|
+
return () => {
|
|
148
|
+
try {
|
|
149
|
+
const st = statSync(absPath);
|
|
150
|
+
if (st.mtimeMs === cachedMtime && st.size === cachedSize) return cachedText;
|
|
151
|
+
const text = readUtf8(absPath).trim();
|
|
152
|
+
const isReload = cachedMtime !== -1;
|
|
153
|
+
cachedMtime = st.mtimeMs;
|
|
154
|
+
cachedSize = st.size;
|
|
155
|
+
cachedText = text;
|
|
156
|
+
warned = false;
|
|
157
|
+
if (isReload) console.info(`[serenity-hooks] ↻ skiff 角色提示词已热重载(${file},${text.length} 字符)`);
|
|
158
|
+
return text;
|
|
159
|
+
} catch (err) {
|
|
160
|
+
if (!warned) {
|
|
161
|
+
warned = true;
|
|
162
|
+
console.warn(`[serenity-hooks] ✗ skiff 角色提示词读取失败(${file})——沿用上次成功内容: ${String(err?.message ?? err)}`);
|
|
163
|
+
}
|
|
164
|
+
return cachedText;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
106
168
|
/**
|
|
107
169
|
* Skiff 基础提示词(dsp 只给这部分;CCC 的 systemPrompt 段由调用方拼接):
|
|
108
170
|
* 身份 + 可用 MSM/工具清单 + 调用协议 + 边界声明。动态生成(清单来自角色白名单)。
|
|
@@ -125,4 +187,4 @@ function buildSkiffBasePrompt(roleName, role) {
|
|
|
125
187
|
return lines.join("\n");
|
|
126
188
|
}
|
|
127
189
|
//#endregion
|
|
128
|
-
export {
|
|
190
|
+
export { readSkiffRoles as a, roleMsmWhitelist as c, systemPromptSource as d, trajectorySubset as f, isSkiffSessionId as i, roleToolWhitelist as l, buildSkiffBasePrompt as n, resolveRoleSystemPrompt as o, createRolePromptReader as r, resolveSkiffKind as s, SKIFF_SESSION_PREFIX as t, skiff_role_exports as u };
|
package/lib/skiff-role.d.ts
CHANGED
|
@@ -43,6 +43,30 @@ export declare function roleMsmWhitelist(role: SkiffRoleConfig | undefined): Set
|
|
|
43
43
|
export declare function resolveRoleSystemPrompt(root: string, role: SkiffRoleConfig | undefined): string;
|
|
44
44
|
/** 角色系统提示词来源(validate/list 展示用) */
|
|
45
45
|
export declare function systemPromptSource(role: SkiffRoleConfig | undefined): 'file' | 'inline' | 'none';
|
|
46
|
+
/**
|
|
47
|
+
* 角色类型(v1.30.15,S142 用户拍板):
|
|
48
|
+
* - 显式 `role.kind` 优先(`temporary` / `persistent`)
|
|
49
|
+
* - 缺省 = 隐式推断:调用方给出**稳定 sessionId** → persistent;否则 temporary
|
|
50
|
+
* (存量配置零迁移;微信桥传固定会话 id → persistent,ACP/调试页随机 id → temporary)
|
|
51
|
+
*/
|
|
52
|
+
export type SkiffKind = 'temporary' | 'persistent';
|
|
53
|
+
export declare function resolveSkiffKind(role: SkiffRoleConfig | undefined, hasStableId: boolean): SkiffKind;
|
|
54
|
+
/**
|
|
55
|
+
* 角色提示词**读取器**(v1.30.15,方案 A:长期型热更新)。
|
|
56
|
+
*
|
|
57
|
+
* 为什么是函数而不是字符串(R↓):旧实现 `createSkiffAgent` 在创建时把
|
|
58
|
+
* `resolveRoleSystemPrompt(...)` 的结果**快照**进系统提示词段闭包 → CCC 改了
|
|
59
|
+
* `zhaocai.md` 必须重启 dsh web 才生效(本轮实证:改完 18KB 提示词,live agent 仍用旧文本)。
|
|
60
|
+
* 现形态返回一个读取函数,由系统提示词段的 `text()` **每轮调用**:
|
|
61
|
+
* - `systemPromptFile`:按 **mtime + size** 缓存重读(命中缓存零 IO;未变不解析)
|
|
62
|
+
* → 改文件即生效,**无需重启**;变更时打一行 info 日志(可观测,便于确认热更生效)
|
|
63
|
+
* - 内嵌 `systemPrompt`:静态(JSON 配置改动仍需重启/重载配置)
|
|
64
|
+
* - 读取失败:返回**上次成功内容**(绝不返回空——空提示词会让角色失去人格与纪律),
|
|
65
|
+
* 并按标签去重告警一次
|
|
66
|
+
* @param root CCC 根
|
|
67
|
+
* @param role 角色配置
|
|
68
|
+
*/
|
|
69
|
+
export declare function createRolePromptReader(root: string, role: SkiffRoleConfig | undefined): () => string;
|
|
46
70
|
/**
|
|
47
71
|
* Skiff 基础提示词(dsp 只给这部分;CCC 的 systemPrompt 段由调用方拼接):
|
|
48
72
|
* 身份 + 可用 MSM/工具清单 + 调用协议 + 边界声明。动态生成(清单来自角色白名单)。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shgroup/dsh-serenity-hooks",
|
|
3
|
-
"version": "1.30.
|
|
3
|
+
"version": "1.30.15",
|
|
4
4
|
"description": "宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:10 个工具(container_fs/logbook/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/autopilot-trajectory)+ 机械约束(安全模式/工作区围墙/密钥守卫/对外输出守卫)+ 工作日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/自主巡航。适配 DSH 0.1.2-rc.1。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|