@shgroup/dsh-serenity-hooks 1.30.1 → 1.30.4
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.4",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"description": "宁静号 ACC harness(Native Cordis 插件):真实 DSH 工具 container_fs/logbook/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/autopilot-trajectory + 拦截缝机械约束(safe-mode/路径守卫)+ 高级设定面板(双端口网关/账号管理)+ Skiff 认知子集角色(实验性)。适配 DSH 公开版(0.1.0-rc,deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
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-CX48YNUL.js";
|
|
3
3
|
import { a as resolveRoleSystemPrompt, i as readSkiffRoles, l as systemPromptSource, r as isSkiffSessionId, s as roleToolWhitelist } from "./skiff-role-LW4tjF9L.js";
|
|
4
|
-
import { C as
|
|
4
|
+
import { C as readProgress, D as writeProgress, E as writeFailedStatus, O as skiffRoleFor, S as newStopToken, T as splitModel, _ as workspaceTrajectoryLine, a as startSkiffDebugServer, b as handymanProgressPaths, c as askSkiff, d as getSkiffAgent, f as skiffMsmGate, g as unregisterSkiffSession, h as skiffTrajectoryEnabled, l as createSkiffAgent, m as skiffSessionSnapshot, n as jscSafeJsonText, o as stopSkiffDebugServer, p as skiffSessionInfo, r as renderSkiffMarkdown, s as stripThink, t as discoverCccs, u as ensureSkiffSession, v as HANDYMAN_GUIDE, w as requireWhitelistedModel, x as listActiveHandymen, y as buildRoundPrompt } from "./skiff-debug-gYigSgl_.js";
|
|
5
5
|
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-jA0qENOf.js";
|
|
6
6
|
import { C as useSession, S as summarize, _ as resolveSessionByTitle, a as archiveSessions, b as setActiveSessionInfo, c as extractSessionMdPathFromText, d as getActiveSessionInfo, f as healthCheck, g as readActiveSessionMd, h as qaCheck, i as SESSION_ACTIONS, l as findLatestActiveSessionMd, m as parseSessionContextFromEvents, n as readLastBound, o as closeSession, p as listSessions, r as DEFAULT_SESSION_SCOPE, s as createSession, t as appendBound, u as findSession, v as sessionEvents, x as showSession, y as sessionsRoot } from "./session-bound-p9oR9dj9.js";
|
|
7
7
|
import { n as registerSettingsSection, t as readSimpleSettings } from "./settings-section-BfVxgCZy.js";
|
|
@@ -603,6 +603,10 @@ function decideGuard(input) {
|
|
|
603
603
|
if (toolName === "skill") return { kind: "allow" };
|
|
604
604
|
const roleName = input.skiffSessionId ? skiffRoleFor(input.skiffSessionId) : null;
|
|
605
605
|
const role = roleName ? readSkiffRoles(root).get(roleName) : void 0;
|
|
606
|
+
if ((role?.msms ?? []).includes(toolName)) return {
|
|
607
|
+
deny: `"${toolName}" is a registered MSM, not a direct tool in this role — call it through the msm tool: msm("${toolName}", ["<args>"]) (pass "--help" or inspect=true for usage)`,
|
|
608
|
+
kind: "deny"
|
|
609
|
+
};
|
|
606
610
|
if (!roleToolWhitelist(role).has(toolName)) return {
|
|
607
611
|
deny: "tool not allowed in this skiff role",
|
|
608
612
|
kind: "deny"
|
|
@@ -6067,7 +6071,7 @@ function registerStatusApi(ctx, opts = {}) {
|
|
|
6067
6071
|
workspace: url.searchParams.get("workspace") ?? void 0
|
|
6068
6072
|
});
|
|
6069
6073
|
const root = findSerenityRoot(workspace) ?? "";
|
|
6070
|
-
const { discoverCccs } = await import("./skiff-debug-
|
|
6074
|
+
const { discoverCccs } = await import("./skiff-debug-gYigSgl_.js").then((n) => n.i);
|
|
6071
6075
|
sendJson$1(res, 200, { cccs: await discoverCccs(ctx, root) });
|
|
6072
6076
|
} catch (err) {
|
|
6073
6077
|
sendJson$1(res, 400, { error: err.message ?? String(err) });
|
|
@@ -9032,6 +9036,11 @@ async function handleIncoming(ctx, root, accountId, cred, msg) {
|
|
|
9032
9036
|
const sessionId = weixinSessionIdFor(fromUserId);
|
|
9033
9037
|
const existing = getSkiffAgent(sessionId);
|
|
9034
9038
|
const hc = readHandymanConfig(root);
|
|
9039
|
+
if (existing) try {
|
|
9040
|
+
ensureSkiffSession(root, existing, roleName, role);
|
|
9041
|
+
} catch (err) {
|
|
9042
|
+
console.warn(`[serenity-hooks] weixin-bridge ensure 失败(不影响处理): ${String(err?.message ?? err)}`);
|
|
9043
|
+
}
|
|
9035
9044
|
const ref = existing ? {
|
|
9036
9045
|
agent: existing,
|
|
9037
9046
|
sessionId,
|
|
@@ -9093,6 +9102,8 @@ async function handleIncoming(ctx, root, accountId, cred, msg) {
|
|
|
9093
9102
|
}
|
|
9094
9103
|
}
|
|
9095
9104
|
const parts = [];
|
|
9105
|
+
const activeWorkspace = getActiveSessionInfo(sessionId);
|
|
9106
|
+
if (activeWorkspace?.mdPath) parts.push(workspaceTrajectoryLine(activeWorkspace.mdPath));
|
|
9096
9107
|
if (text) parts.push(text);
|
|
9097
9108
|
parts.push(...mediaNotes, ...degradedNotes);
|
|
9098
9109
|
const question = parts.join("\n");
|
package/lib/skiff-core.d.ts
CHANGED
|
@@ -27,6 +27,32 @@ export declare function skiffSessionSnapshot(): ReadonlyMap<string, {
|
|
|
27
27
|
role: string;
|
|
28
28
|
ccc: string;
|
|
29
29
|
}>;
|
|
30
|
+
/**
|
|
31
|
+
* 系统提示词中的**工作台纪律块**(v1.30.4 升级:从单行路径 → 完整 ACC 层约束)。
|
|
32
|
+
* 用户点破(S142):只给路径 LLM 不会主动用——需注入「已绑定 + 使用纪律 + 动作指引」。
|
|
33
|
+
* SESSION = 工作台——skiff 与主舱同一套机制(零特调,用户拍板):
|
|
34
|
+
* 自动绑定已生效(无需 logbook use)、SESSION.md 是持久记忆载体(write/edit 维护)、
|
|
35
|
+
* rebuild 自动从本 SESSION 续接。注入 agent 系统提示词(用户对话面不可见)。
|
|
36
|
+
*/
|
|
37
|
+
export declare function workspaceTrajectoryLine(mdPath: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* 确保启用 session 能力的 skiff 会话拥有**专属 SESSION**(工作台):
|
|
40
|
+
* 懒绑定 + 幂等(per skiff 会话 scope 隔离——微信多用户各自独立,永不共享同一份)。
|
|
41
|
+
*
|
|
42
|
+
* 判定链:
|
|
43
|
+
* ① 角色未启用 session 能力(trajectory.session !== true)→ null(现状零变化)
|
|
44
|
+
* ② 会话日志已有**本机制自动创建**的 bound(note 前缀 auto-created)→ 恢复(重启/续接记得)
|
|
45
|
+
* ③ 无 → 自动创建专属 SESSION(createSession desc=`<role> skiff`——编号自动递增,用户不关心是谁)
|
|
46
|
+
*
|
|
47
|
+
* @returns 绑定后的 SESSION.md 绝对路径(供提示词注入);不适用/失败 → null
|
|
48
|
+
*/
|
|
49
|
+
export declare function ensureSkiffSession(root: string, agent: Agent, roleName: string, role: SkiffRoleConfig): string | null;
|
|
50
|
+
/** 当前 scope 是否已激活(幂等判定:getActiveSessionInfo 命中同 dirName)——测试用 */
|
|
51
|
+
export declare function skiffSessionActiveFor(sessionId: string): {
|
|
52
|
+
sessionId: string;
|
|
53
|
+
dirName: string;
|
|
54
|
+
mdPath: string;
|
|
55
|
+
} | null;
|
|
30
56
|
export interface SkiffAgentRef {
|
|
31
57
|
handle: AgentHandle;
|
|
32
58
|
agent: Agent;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
2
|
import { a as findSerenityRoot, f as readHandymanConfig } from "./ccc-CX48YNUL.js";
|
|
3
3
|
import { a as resolveRoleSystemPrompt, i as readSkiffRoles, n as buildSkiffBasePrompt, o as roleMsmWhitelist, r as isSkiffSessionId, u as trajectorySubset } from "./skiff-role-LW4tjF9L.js";
|
|
4
|
+
import { b as setActiveSessionInfo, n as readLastBound, s as createSession, t as appendBound } from "./session-bound-p9oR9dj9.js";
|
|
4
5
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
5
6
|
import { basename, join } from "node:path";
|
|
6
7
|
import { createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
@@ -244,6 +245,77 @@ function skiffSessionSnapshot() {
|
|
|
244
245
|
});
|
|
245
246
|
return out;
|
|
246
247
|
}
|
|
248
|
+
/** 自动创建的 bound 标记(readLastBound 恢复判定——只恢复本机制建的;手工 use 的旧 bound 不认) */
|
|
249
|
+
const AUTO_BOUND_NOTE_PREFIX = "auto-created for skiff role";
|
|
250
|
+
/**
|
|
251
|
+
* 系统提示词中的**工作台纪律块**(v1.30.4 升级:从单行路径 → 完整 ACC 层约束)。
|
|
252
|
+
* 用户点破(S142):只给路径 LLM 不会主动用——需注入「已绑定 + 使用纪律 + 动作指引」。
|
|
253
|
+
* SESSION = 工作台——skiff 与主舱同一套机制(零特调,用户拍板):
|
|
254
|
+
* 自动绑定已生效(无需 logbook use)、SESSION.md 是持久记忆载体(write/edit 维护)、
|
|
255
|
+
* rebuild 自动从本 SESSION 续接。注入 agent 系统提示词(用户对话面不可见)。
|
|
256
|
+
*/
|
|
257
|
+
function workspaceTrajectoryLine(mdPath) {
|
|
258
|
+
return [
|
|
259
|
+
"── Serenity Session Workspace ──",
|
|
260
|
+
"This role session is AUTO-BOUND to a trajectory workspace SESSION (no logbook use needed):",
|
|
261
|
+
` SESSION.md: ${mdPath}`,
|
|
262
|
+
"",
|
|
263
|
+
"Rules of the workspace:",
|
|
264
|
+
" 1. This SESSION.md is your persistent memory carrier (like the main cabin SESSION) — ",
|
|
265
|
+
" read it first when context feels thin or work spans turns.",
|
|
266
|
+
" 2. Record key decisions/progress/unresolved items INTO this SESSION.md with write/edit",
|
|
267
|
+
" (sections: 目标 / 状态 / 关键决策 / 进度记录 / 未解决的问题). Keep it current — it is",
|
|
268
|
+
" what a rebuild resumes from.",
|
|
269
|
+
" 3. When context pressure is high, run logbook rebuild — it auto-resumes from THIS SESSION.md",
|
|
270
|
+
" (no manual use; do not switch to or read other SESSIONs unless the user explicitly asks).",
|
|
271
|
+
" 4. Never expose this internal path in user-facing replies (chat stays clean).",
|
|
272
|
+
"── ──"
|
|
273
|
+
].join("\n");
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* 确保启用 session 能力的 skiff 会话拥有**专属 SESSION**(工作台):
|
|
277
|
+
* 懒绑定 + 幂等(per skiff 会话 scope 隔离——微信多用户各自独立,永不共享同一份)。
|
|
278
|
+
*
|
|
279
|
+
* 判定链:
|
|
280
|
+
* ① 角色未启用 session 能力(trajectory.session !== true)→ null(现状零变化)
|
|
281
|
+
* ② 会话日志已有**本机制自动创建**的 bound(note 前缀 auto-created)→ 恢复(重启/续接记得)
|
|
282
|
+
* ③ 无 → 自动创建专属 SESSION(createSession desc=`<role> skiff`——编号自动递增,用户不关心是谁)
|
|
283
|
+
*
|
|
284
|
+
* @returns 绑定后的 SESSION.md 绝对路径(供提示词注入);不适用/失败 → null
|
|
285
|
+
*/
|
|
286
|
+
function ensureSkiffSession(root, agent, roleName, role) {
|
|
287
|
+
if (!trajectorySubset(role).session) return null;
|
|
288
|
+
const session = agent.session;
|
|
289
|
+
const scope = String(agent.session.id ?? agent.id);
|
|
290
|
+
const lastBound = session ? readLastBound(session) : null;
|
|
291
|
+
if (lastBound && lastBound.note?.startsWith(AUTO_BOUND_NOTE_PREFIX) && existsSync(lastBound.mdPath)) {
|
|
292
|
+
setActiveSessionInfo(scope, {
|
|
293
|
+
sessionId: lastBound.sessionId ?? "",
|
|
294
|
+
dirName: lastBound.dirName,
|
|
295
|
+
mdPath: lastBound.mdPath
|
|
296
|
+
});
|
|
297
|
+
return lastBound.mdPath;
|
|
298
|
+
}
|
|
299
|
+
const desc = `${roleName} skiff`;
|
|
300
|
+
const created = createSession({
|
|
301
|
+
root,
|
|
302
|
+
desc,
|
|
303
|
+
dryRun: false
|
|
304
|
+
});
|
|
305
|
+
const mdPath = join(created.sessionPath, "SESSION.md");
|
|
306
|
+
setActiveSessionInfo(scope, {
|
|
307
|
+
sessionId: created.sessionId,
|
|
308
|
+
dirName: created.dirName,
|
|
309
|
+
mdPath
|
|
310
|
+
});
|
|
311
|
+
appendBound(session, "create", {
|
|
312
|
+
dirName: created.dirName,
|
|
313
|
+
mdPath,
|
|
314
|
+
sessionId: created.sessionId,
|
|
315
|
+
note: `${AUTO_BOUND_NOTE_PREFIX} ${roleName}`
|
|
316
|
+
});
|
|
317
|
+
return mdPath;
|
|
318
|
+
}
|
|
247
319
|
/** Skiff agent 挂载的 DSH preset(v1.25.3 修复:read/grep/glob 等平台工具由 preset 决定工具面;
|
|
248
320
|
* handyman 经 composeFrom 继承父、skiff 无父上下文——直接挂 DSH 默认 standard preset;
|
|
249
321
|
* guard 角色白名单再按角色过滤可见/可用面——白名单外工具仍 deny) */
|
|
@@ -278,11 +350,21 @@ async function createSkiffAgent(ctx, root, roleName, role, defaultModel, session
|
|
|
278
350
|
} catch (err) {
|
|
279
351
|
console.warn(`[serenity-hooks] skiff 角色 "${roleName}" 系统提示词解析失败(回退仅基础段): ${String(err?.message ?? err)}`);
|
|
280
352
|
}
|
|
353
|
+
let workspaceMdPath = null;
|
|
354
|
+
try {
|
|
355
|
+
workspaceMdPath = ensureSkiffSession(root, agent, roleName, role);
|
|
356
|
+
} catch (err) {
|
|
357
|
+
console.warn(`[serenity-hooks] skiff 角色 "${roleName}" 专属 SESSION 处理失败(不影响 agent 创建): ${String(err?.message ?? err)}`);
|
|
358
|
+
}
|
|
281
359
|
try {
|
|
282
360
|
agent.ctx.systemPrompt.section({
|
|
283
361
|
name: "serenity-skiff",
|
|
284
362
|
order: -60,
|
|
285
|
-
text: () => [
|
|
363
|
+
text: () => [
|
|
364
|
+
buildSkiffBasePrompt(roleName, role),
|
|
365
|
+
workspaceMdPath ? workspaceTrajectoryLine(workspaceMdPath) : "",
|
|
366
|
+
cccPrompt
|
|
367
|
+
].filter(Boolean).join("\n")
|
|
286
368
|
});
|
|
287
369
|
} catch (err) {
|
|
288
370
|
console.warn(`[serenity-hooks] skiff 系统提示词注册失败: ${String(err?.message ?? err)}`);
|
|
@@ -2666,4 +2748,4 @@ async function handle(ctx, defaultRoot, webPort, req, res) {
|
|
|
2666
2748
|
}
|
|
2667
2749
|
}
|
|
2668
2750
|
//#endregion
|
|
2669
|
-
export {
|
|
2751
|
+
export { readProgress as C, writeProgress as D, writeFailedStatus as E, skiffRoleFor$1 as O, newStopToken as S, splitModel as T, workspaceTrajectoryLine as _, startSkiffDebugServer as a, handymanProgressPaths as b, askSkiff as c, getSkiffAgent as d, skiffMsmGate as f, unregisterSkiffSession as g, skiffTrajectoryEnabled as h, skiff_debug_exports as i, createSkiffAgent as l, skiffSessionSnapshot as m, jscSafeJsonText as n, stopSkiffDebugServer as o, skiffSessionInfo as p, renderSkiffMarkdown as r, stripThink as s, discoverCccs as t, ensureSkiffSession as u, HANDYMAN_GUIDE as v, requireWhitelistedModel as w, listActiveHandymen as x, buildRoundPrompt as y };
|
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.4",
|
|
4
4
|
"description": "宁静号 ACC harness — Native Cordis 插件(DeepSeek Harness 运行时)。真实 DSH 工具注册(cc_fs/session/acc_msm 等 9 工具)+ 拦截缝机械约束(safe-mode/路径守卫/会话落盘)+ 系统提示词注入(ACC/CCE/Constraints/SKILL/Session 五块)。适配 DSH 公开版(deepseek-ai/deepseek-harness 0.1.0-rc)。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|