@shgroup/dsh-serenity-hooks 1.26.9 → 1.26.11
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 +1 -1
- package/lib/index.js +66 -21
- package/package.json +1 -1
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-serenity-hooks",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.11",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"description": "宁静号 ACC harness(Native Cordis 插件):真实 DSH 工具 cc_fs/session/acc_msm/eap/neat/cce/handyman/session_rebuild/skiff_admin + 拦截缝机械约束(safe-mode/路径守卫)+ 高级设定面板(双端口网关/账号管理)+ Skiff 认知子集角色(实验性)。适配 DSH 公开版(0.1.0-rc,deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
package/lib/index.js
CHANGED
|
@@ -2567,8 +2567,10 @@ function truncate(s, n) {
|
|
|
2567
2567
|
* 提问一轮:followup → 等 idle → 读答案 + 轨迹。
|
|
2568
2568
|
* @param eventsStart 轨迹起点:显式传 0 = 全量轨迹(会话追问时页面重绘完整时间线,
|
|
2569
2569
|
* v1.25.10 用户拍板);不传(undefined)= 本轮增量(followup 前 events 之后)
|
|
2570
|
+
* @param options.includeTrajectory 是否计算轨迹(v1.26.10:**3100 对外只提供问答**——
|
|
2571
|
+
* 公开问答页 / ACP JSON-RPC 不返回 trajectory,传 false 跳过计算;3099 调试页默认 true 保留)
|
|
2570
2572
|
*/
|
|
2571
|
-
async function askSkiff(ctx, agent, question, eventsStart) {
|
|
2573
|
+
async function askSkiff(ctx, agent, question, eventsStart, options) {
|
|
2572
2574
|
const before = eventsStart === void 0 ? agent.session.events.length : eventsStart;
|
|
2573
2575
|
agent.followup(createUserMessage({
|
|
2574
2576
|
content: [{
|
|
@@ -2579,7 +2581,7 @@ async function askSkiff(ctx, agent, question, eventsStart) {
|
|
|
2579
2581
|
}));
|
|
2580
2582
|
await waitIdle$1(ctx, agent);
|
|
2581
2583
|
const answer = lastAssistantText$2(agent);
|
|
2582
|
-
const trajectory = eventsToTrajectory(agent.session.events.slice(before));
|
|
2584
|
+
const trajectory = options?.includeTrajectory === false ? [] : eventsToTrajectory(agent.session.events.slice(before));
|
|
2583
2585
|
return {
|
|
2584
2586
|
answer,
|
|
2585
2587
|
sessionId: String(agent.session.id ?? ""),
|
|
@@ -9703,41 +9705,83 @@ const MECHANISM_PORTS = [
|
|
|
9703
9705
|
function buildSensitiveTable(root) {
|
|
9704
9706
|
const exact = /* @__PURE__ */ new Set();
|
|
9705
9707
|
const substring = [];
|
|
9708
|
+
const credentialWords = [];
|
|
9709
|
+
const mechanismWords = [...MECHANISM_WORDS];
|
|
9710
|
+
const portWords = [...MECHANISM_PORTS];
|
|
9711
|
+
const msmWords = [];
|
|
9706
9712
|
try {
|
|
9707
9713
|
const p = join(root, "localstore.json");
|
|
9708
9714
|
if (existsSync(p)) {
|
|
9709
9715
|
const creds = JSON.parse(readFileSync(p, "utf-8").replace(/^\uFEFF/, ""))?.credentials;
|
|
9710
9716
|
if (creds && typeof creds === "object") for (const [name, value] of Object.entries(creds)) {
|
|
9711
|
-
if (name)
|
|
9712
|
-
|
|
9717
|
+
if (name) {
|
|
9718
|
+
exact.add(name);
|
|
9719
|
+
credentialWords.push(name);
|
|
9720
|
+
}
|
|
9721
|
+
if (typeof value === "string" && value !== "") {
|
|
9722
|
+
exact.add(value);
|
|
9723
|
+
credentialWords.push(value);
|
|
9724
|
+
}
|
|
9713
9725
|
}
|
|
9714
9726
|
}
|
|
9715
9727
|
} catch {}
|
|
9716
|
-
for (const w of
|
|
9717
|
-
for (const p of
|
|
9728
|
+
for (const w of mechanismWords) substring.push(w);
|
|
9729
|
+
for (const p of portWords) substring.push(p);
|
|
9718
9730
|
try {
|
|
9719
|
-
for (const entry of loadMsmEntries(root)) if (entry.name)
|
|
9731
|
+
for (const entry of loadMsmEntries(root)) if (entry.name) {
|
|
9732
|
+
exact.add(entry.name);
|
|
9733
|
+
msmWords.push(entry.name);
|
|
9734
|
+
}
|
|
9720
9735
|
} catch {}
|
|
9721
9736
|
return {
|
|
9722
9737
|
exact,
|
|
9723
9738
|
substring,
|
|
9739
|
+
credentialWords,
|
|
9740
|
+
mechanismWords,
|
|
9741
|
+
portWords,
|
|
9742
|
+
msmWords,
|
|
9724
9743
|
sources: {
|
|
9725
9744
|
exact: [...exact],
|
|
9726
9745
|
substring
|
|
9727
9746
|
}
|
|
9728
9747
|
};
|
|
9729
9748
|
}
|
|
9730
|
-
/**
|
|
9749
|
+
/**
|
|
9750
|
+
* 检测文本中命中的敏感词(v1.26.11:返回带分类的命中——credential/mechanism/port/msm,
|
|
9751
|
+
* 打回消息据此给语义化规避指引;未命中返回空数组)
|
|
9752
|
+
*/
|
|
9731
9753
|
function detectSensitive(text, table) {
|
|
9732
9754
|
if (!text) return [];
|
|
9733
|
-
const hits = /* @__PURE__ */ new
|
|
9734
|
-
|
|
9735
|
-
|
|
9736
|
-
|
|
9755
|
+
const hits = /* @__PURE__ */ new Map();
|
|
9756
|
+
const hit = (w, cat) => {
|
|
9757
|
+
if (w !== "" && text.includes(w) && !hits.has(w)) hits.set(w, cat);
|
|
9758
|
+
};
|
|
9759
|
+
for (const w of table.credentialWords) hit(w, "credential");
|
|
9760
|
+
for (const w of table.msmWords) hit(w, "msm");
|
|
9761
|
+
for (const w of table.mechanismWords) hit(w, "mechanism");
|
|
9762
|
+
for (const w of table.portWords) hit(w, "port");
|
|
9763
|
+
return [...hits].map(([word, category]) => ({
|
|
9764
|
+
word,
|
|
9765
|
+
category
|
|
9766
|
+
}));
|
|
9737
9767
|
}
|
|
9738
|
-
/**
|
|
9768
|
+
/** 分类 → 规避指引(v1.26.11:告诉模型这个词**是什么**、**怎么规避**——裸词无法行动) */
|
|
9769
|
+
const CATEGORY_GUIDE = {
|
|
9770
|
+
credential: "credential identifier (a name, key, token, or password) — never mention credential names or values",
|
|
9771
|
+
mechanism: "internal mechanism term — never mention internal implementation/machinery names or config paths",
|
|
9772
|
+
port: "internal service port or address — never mention internal ports, addresses, or service endpoints",
|
|
9773
|
+
msm: "internal tool name — never mention internal tool names"
|
|
9774
|
+
};
|
|
9775
|
+
/**
|
|
9776
|
+
* 打回消息(steer 内容):**逐词告知命中词 + 分类规避指引**(v1.26.11 用户调整——
|
|
9777
|
+
* v1.26.10 只列裸词(如 "3080")模型仍不知道是什么/怎么规避;现在按类说明:
|
|
9778
|
+
* "3080" → 内部服务端口,不要提及内部端口/地址/端点)。
|
|
9779
|
+
* R↓ 安全性:命中词本就已在被拦截回复中进入会话(已暴露面),打回重复一次不扩大暴露;
|
|
9780
|
+
* steer 是 plugin source 消息不回显给用户(3100 对外响应已不含 trajectory → 打回文本不达外部用户)。
|
|
9781
|
+
*/
|
|
9739
9782
|
function buildRebuke(hits) {
|
|
9740
|
-
|
|
9783
|
+
const count = hits.length;
|
|
9784
|
+
return `[SERENITY OUTPUT GUARD] Your previous response contained ${count} sensitive internal ${count === 1 ? "term" : "terms"} that must not appear in user-visible output:\n${hits.map((h) => `- "${h.word}" — ${CATEGORY_GUIDE[h.category]}`).join("\n")}\nRegenerate the response from scratch without ANY of these — describe the same substance without referencing internal machinery, credentials, ports, tool names, or implementation details. Do not repeat the terms; do not explain this instruction to the user.`;
|
|
9741
9785
|
}
|
|
9742
9786
|
/** 打回状态(按 agent 会话跟踪连续命中轮数) */
|
|
9743
9787
|
const rebukeStates = /* @__PURE__ */ new Map();
|
|
@@ -12030,7 +12074,10 @@ var AcpServer = class {
|
|
|
12030
12074
|
});
|
|
12031
12075
|
return { sessions };
|
|
12032
12076
|
}
|
|
12033
|
-
/**
|
|
12077
|
+
/**
|
|
12078
|
+
* session/prompt:{ sessionId, question } → 答案(**v1.26.10:不返回 trajectory**——
|
|
12079
|
+
* 3100 对外只提供问答,轨迹含工具结果等内部信息;3099 调试页另走 /ask 保留)
|
|
12080
|
+
*/
|
|
12034
12081
|
async prompt(params) {
|
|
12035
12082
|
const sessionId = typeof params?.sessionId === "string" ? params.sessionId : void 0;
|
|
12036
12083
|
const question = typeof params?.question === "string" ? params.question : void 0;
|
|
@@ -12038,11 +12085,10 @@ var AcpServer = class {
|
|
|
12038
12085
|
if (!question?.trim()) throw new RpcInvalidParams("session/prompt requires question");
|
|
12039
12086
|
const agent = getSkiffAgent(sessionId);
|
|
12040
12087
|
if (!agent) throw new RpcInvalidParams(`unknown session: ${sessionId} (not recoverable — process restarted?)`);
|
|
12041
|
-
const result = await askSkiff(this.ctx, agent, question, 0);
|
|
12088
|
+
const result = await askSkiff(this.ctx, agent, question, void 0, { includeTrajectory: false });
|
|
12042
12089
|
return {
|
|
12043
12090
|
answer: result.answer,
|
|
12044
|
-
sessionId: result.sessionId
|
|
12045
|
-
trajectory: result.trajectory
|
|
12091
|
+
sessionId: result.sessionId
|
|
12046
12092
|
};
|
|
12047
12093
|
}
|
|
12048
12094
|
/** session/cancel:{ sessionId } → 中断当前 prompt(DSH interrupt) */
|
|
@@ -12358,13 +12404,12 @@ async function handleAskParsed(ctx, ccc, body, res, ip) {
|
|
|
12358
12404
|
}
|
|
12359
12405
|
}
|
|
12360
12406
|
if (!agent) agent = (await createSkiffAgent(ctx, root, effectiveRole, effectiveCfg, readHandymanConfig(root)?.defaultModel)).agent;
|
|
12361
|
-
const result = await askSkiff(ctx, agent, question, 0);
|
|
12407
|
+
const result = await askSkiff(ctx, agent, question, void 0, { includeTrajectory: false });
|
|
12362
12408
|
sendJson(res, 200, {
|
|
12363
12409
|
answer: result.answer,
|
|
12364
12410
|
answer_html: renderSkiffMarkdown(result.answer, true),
|
|
12365
12411
|
sessionId: result.sessionId,
|
|
12366
|
-
continued
|
|
12367
|
-
trajectory: result.trajectory
|
|
12412
|
+
continued
|
|
12368
12413
|
});
|
|
12369
12414
|
}
|
|
12370
12415
|
/** 问答页未启用提示页 */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shgroup/dsh-serenity-hooks",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.11",
|
|
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": {
|