@shgroup/dsh-serenity-hooks 1.18.8 → 1.19.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/dsh.plugin.json +2 -2
- package/lib/index.js +46 -31
- package/package.json +1 -1
package/dsh.plugin.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-serenity-hooks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.1",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
|
-
"description": "宁静号 ACC harness(Native Cordis 插件):真实 DSH 工具 cc_fs/session/acc_msm/eap/neat/cce/loop + 拦截缝机械约束(safe-mode
|
|
5
|
+
"description": "宁静号 ACC harness(Native Cordis 插件):真实 DSH 工具 cc_fs/session/acc_msm/eap/neat/cce/loop + 拦截缝机械约束(safe-mode/路径守卫)。适配 DSH 公开版(0.1.0-rc,deepseek-ai/deepseek-harness)。私有(dsh-external 组织)。",
|
|
6
6
|
"engines": {
|
|
7
7
|
"dsh": ">=0.1.0-rc.5"
|
|
8
8
|
},
|
package/lib/index.js
CHANGED
|
@@ -1684,15 +1684,6 @@ function qaCheck(root, key) {
|
|
|
1684
1684
|
if (verified) lines.push(" • Session looks clean — no issues detected");
|
|
1685
1685
|
return lines.join("\n");
|
|
1686
1686
|
}
|
|
1687
|
-
/** 追加会话心跳(turn-stopping 机械落盘用) */
|
|
1688
|
-
function appendHeartbeat(sessionMd) {
|
|
1689
|
-
try {
|
|
1690
|
-
appendFileSync(sessionMd, `- ${(/* @__PURE__ */ new Date()).toISOString()} — [auto] turn heartbeat (dsh-serenity-hooks)\n`, "utf-8");
|
|
1691
|
-
return true;
|
|
1692
|
-
} catch {
|
|
1693
|
-
return false;
|
|
1694
|
-
}
|
|
1695
|
-
}
|
|
1696
1687
|
//#endregion
|
|
1697
1688
|
//#region src/tools/session.ts
|
|
1698
1689
|
/**
|
|
@@ -1906,6 +1897,32 @@ const sessionTool = defineTool({
|
|
|
1906
1897
|
*
|
|
1907
1898
|
* 对应 opencode-serenity-plugin 的 tool.execute.before 路径守卫 + bash 开关 + 黑名单。
|
|
1908
1899
|
*/
|
|
1900
|
+
/** 写类工具名(黑名单/治理文件只拦这些;读工具只做路径越界检查——对齐 osp) */
|
|
1901
|
+
const WRITE_TOOLS = /* @__PURE__ */ new Set([
|
|
1902
|
+
"write",
|
|
1903
|
+
"edit",
|
|
1904
|
+
"str_replace_editor",
|
|
1905
|
+
"cc_fs",
|
|
1906
|
+
"bash",
|
|
1907
|
+
"append",
|
|
1908
|
+
"touch"
|
|
1909
|
+
]);
|
|
1910
|
+
/** cc_fs 的写类子命令(mkdir/rm/mv/cp/touch/append);其余 9 子命令(root/resolve/exists/
|
|
1911
|
+
* list/tree/relative/reveal/info/find)为只读——只读子命令不查黑名单(同 read 语义) */
|
|
1912
|
+
const CC_FS_WRITE_ACTIONS = /* @__PURE__ */ new Set([
|
|
1913
|
+
"mkdir",
|
|
1914
|
+
"rm",
|
|
1915
|
+
"mv",
|
|
1916
|
+
"cp",
|
|
1917
|
+
"touch",
|
|
1918
|
+
"append"
|
|
1919
|
+
]);
|
|
1920
|
+
/** 判定工具是否为写类:普通工具按名;cc_fs 复合工具按子命令 action */
|
|
1921
|
+
function isWriteTool(toolName, action) {
|
|
1922
|
+
if (!WRITE_TOOLS.has(toolName)) return false;
|
|
1923
|
+
if (toolName === "cc_fs") return action !== void 0 && CC_FS_WRITE_ACTIONS.has(action);
|
|
1924
|
+
return true;
|
|
1925
|
+
}
|
|
1909
1926
|
/**
|
|
1910
1927
|
* 安全模式 + 黑名单 + P3 路径守卫的纯决策。
|
|
1911
1928
|
* 对齐 opencode-serenity-plugin 标准:安全模式 = **bash 禁用** + 写入黑名单;
|
|
@@ -1913,7 +1930,7 @@ const sessionTool = defineTool({
|
|
|
1913
1930
|
* 优先级:safe-mode bash > 路径越界 > 黑名单命中。
|
|
1914
1931
|
*/
|
|
1915
1932
|
function decideGuard(input) {
|
|
1916
|
-
const { root, toolName, safeModeOn, blacklist, pathArg } = input;
|
|
1933
|
+
const { root, toolName, safeModeOn, blacklist, pathArg, action } = input;
|
|
1917
1934
|
if (safeModeOn && toolName === "bash") return {
|
|
1918
1935
|
deny: `bash: 没有这个工具`,
|
|
1919
1936
|
kind: "deny"
|
|
@@ -1924,7 +1941,7 @@ function decideGuard(input) {
|
|
|
1924
1941
|
deny: `path escape blocked: "${pathArg}" 越出 CCC 根`,
|
|
1925
1942
|
kind: "deny"
|
|
1926
1943
|
};
|
|
1927
|
-
if (toolName
|
|
1944
|
+
if (isWriteTool(toolName, action)) {
|
|
1928
1945
|
const rel = relative(root, abs).split("\\").join("/");
|
|
1929
1946
|
if (rel === ".serenity-safe-on" || rel === ".serenity" || rel.startsWith(".serenity-safe-on/") || rel.startsWith(".serenity/")) return {
|
|
1930
1947
|
deny: `CCC 治理文件 "${rel}" 保留给用户,agent 不可写`,
|
|
@@ -2003,7 +2020,11 @@ function syncSafeModeRestriction(agent, root) {
|
|
|
2003
2020
|
}
|
|
2004
2021
|
writeRestrictDiag(root);
|
|
2005
2022
|
}
|
|
2006
|
-
/**
|
|
2023
|
+
/**
|
|
2024
|
+
* 从 exec 参数中提取常见路径字段(write/edit 工具);宽松读取。
|
|
2025
|
+
* cc_fs 复合工具:path(单路径)/ paths(数组)/ src / dst——取第一个命中(越界检查
|
|
2026
|
+
* 逐路径由 decideGuard 单 pathArg 覆盖;多路径字段取首个,避免漏检主体路径)。
|
|
2027
|
+
*/
|
|
2007
2028
|
function extractPathArg(exec) {
|
|
2008
2029
|
const args = exec.arguments;
|
|
2009
2030
|
if (args === null || typeof args !== "object") return void 0;
|
|
@@ -2012,11 +2033,21 @@ function extractPathArg(exec) {
|
|
|
2012
2033
|
"path",
|
|
2013
2034
|
"file_path",
|
|
2014
2035
|
"target",
|
|
2036
|
+
"src",
|
|
2015
2037
|
"dst"
|
|
2016
2038
|
]) {
|
|
2017
2039
|
const v = a[key];
|
|
2018
2040
|
if (typeof v === "string") return v;
|
|
2019
2041
|
}
|
|
2042
|
+
const paths = a["paths"];
|
|
2043
|
+
if (Array.isArray(paths) && paths.length > 0 && typeof paths[0] === "string") return paths[0];
|
|
2044
|
+
}
|
|
2045
|
+
/** 从 exec 参数提取 cc_fs 子命令 action;无则 undefined */
|
|
2046
|
+
function extractAction(exec) {
|
|
2047
|
+
const args = exec.arguments;
|
|
2048
|
+
if (args === null || typeof args !== "object") return void 0;
|
|
2049
|
+
const a = args;
|
|
2050
|
+
return typeof a.action === "string" ? a.action : void 0;
|
|
2020
2051
|
}
|
|
2021
2052
|
/**
|
|
2022
2053
|
* 注册守卫:tools/pre-execute 瀑布 + ctx.tools.guard 终局。
|
|
@@ -2030,12 +2061,14 @@ function registerGuards(ctx, opts = {}) {
|
|
|
2030
2061
|
const safeModeOn = isSafeModeOn(root);
|
|
2031
2062
|
const blacklist = readBlacklist(root, configPaths);
|
|
2032
2063
|
const pathArg = extractPathArg(exec);
|
|
2064
|
+
const action = extractAction(exec);
|
|
2033
2065
|
return decideGuard({
|
|
2034
2066
|
root,
|
|
2035
2067
|
toolName: exec.name,
|
|
2036
2068
|
safeModeOn,
|
|
2037
2069
|
blacklist,
|
|
2038
|
-
pathArg
|
|
2070
|
+
pathArg,
|
|
2071
|
+
action
|
|
2039
2072
|
});
|
|
2040
2073
|
};
|
|
2041
2074
|
ctx.on("tools/pre-execute", async (exec, next) => {
|
|
@@ -3816,22 +3849,6 @@ function registerBootstrap(ctx) {
|
|
|
3816
3849
|
}, { prepend: true });
|
|
3817
3850
|
}
|
|
3818
3851
|
//#endregion
|
|
3819
|
-
//#region src/seams/loop.ts
|
|
3820
|
-
/** 解析当前 dsh 会话 scope 的活跃会话 SESSION.md 绝对路径;无标记/越界返回 null */
|
|
3821
|
-
function resolveActiveSession(root, scope = DEFAULT_SESSION_SCOPE) {
|
|
3822
|
-
return readActiveSessionMd(root, scope);
|
|
3823
|
-
}
|
|
3824
|
-
/** 注册 agent/turn-stopping:CCC 内活动会话自动心跳落盘(按 dsh 会话隔离) */
|
|
3825
|
-
function registerTurnFlush(ctx) {
|
|
3826
|
-
ctx.on("agent/turn-stopping", async (payload) => {
|
|
3827
|
-
const agent = payload.agent;
|
|
3828
|
-
const root = findSerenityRoot(agent.session?.header?.cwd ?? process.cwd());
|
|
3829
|
-
if (!root) return;
|
|
3830
|
-
const sessionMd = resolveActiveSession(root, agent.session?.id ?? "default");
|
|
3831
|
-
if (sessionMd) appendHeartbeat(sessionMd);
|
|
3832
|
-
});
|
|
3833
|
-
}
|
|
3834
|
-
//#endregion
|
|
3835
3852
|
//#region src/seams/keeper.ts
|
|
3836
3853
|
const SCORES = {
|
|
3837
3854
|
write: 3,
|
|
@@ -4744,7 +4761,6 @@ const Config = z.object({
|
|
|
4744
4761
|
serenityConfigPaths: z.array(z.string()).default([...DEFAULT_SERENITY_CONFIG_PATHS]),
|
|
4745
4762
|
tools: z.boolean().default(true),
|
|
4746
4763
|
guards: z.boolean().default(true),
|
|
4747
|
-
turnFlush: z.boolean().default(true),
|
|
4748
4764
|
keeper: z.boolean().default(true),
|
|
4749
4765
|
keeperThreshold: z.number().default(150),
|
|
4750
4766
|
context: z.boolean().default(true),
|
|
@@ -4768,7 +4784,6 @@ function apply(ctx, config) {
|
|
|
4768
4784
|
ctx.tools.register(localstoreTool);
|
|
4769
4785
|
}
|
|
4770
4786
|
if (config.guards) registerGuards(ctx, { configPaths: config.serenityConfigPaths });
|
|
4771
|
-
if (config.turnFlush) registerTurnFlush(ctx);
|
|
4772
4787
|
if (config.keeper) registerKeeper(ctx, {
|
|
4773
4788
|
configPaths: config.serenityConfigPaths,
|
|
4774
4789
|
defaultThreshold: config.keeperThreshold
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shgroup/dsh-serenity-hooks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.1",
|
|
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": {
|