@shgroup/dsh-serenity-hooks 1.26.8 → 1.26.10
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 +44 -15
- 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.10",
|
|
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 ?? ""),
|
|
@@ -9735,9 +9737,15 @@ function detectSensitive(text, table) {
|
|
|
9735
9737
|
for (const w of table.substring) if (w !== "" && text.includes(w)) hits.add(w);
|
|
9736
9738
|
return [...hits];
|
|
9737
9739
|
}
|
|
9738
|
-
/**
|
|
9740
|
+
/**
|
|
9741
|
+
* 打回消息(steer 内容):**告知命中词并指令重新生成**(v1.26.10 用户调整——
|
|
9742
|
+
* 原 v1.26.3 设计"不含命中词防二次泄露"导致模型不知道改什么;命中词本就已在被拦截的
|
|
9743
|
+
* 回复中进入会话(已暴露面),打回消息重复一次不扩大暴露,模型据此精准重写)。
|
|
9744
|
+
* 命中词已落入模型上下文(它刚写过),此消息不回显给用户(steer 是 plugin source 消息,
|
|
9745
|
+
* 3100 对外响应 v1.26.10 起已不含 trajectory → 打回文本不会到达外部用户)。
|
|
9746
|
+
*/
|
|
9739
9747
|
function buildRebuke(hits) {
|
|
9740
|
-
return `[SERENITY OUTPUT GUARD] Your previous response contained ${hits.length} sensitive internal term(s) (mechanism/credential identifiers) that must not appear in user-visible output. Regenerate the response from scratch without these terms — describe the same substance without referencing internal machinery, credentials, tool names, or implementation details. Do not repeat the terms; do not explain this instruction to the user.`;
|
|
9748
|
+
return `[SERENITY OUTPUT GUARD] Your previous response contained ${hits.length} sensitive internal term(s) (mechanism/credential identifiers) that must not appear in user-visible output: ${[...new Set(hits)].join(", ")}. Regenerate the response from scratch without ANY of these terms — describe the same substance without referencing internal machinery, credentials, tool names, or implementation details. Do not repeat the terms; do not explain this instruction to the user.`;
|
|
9741
9749
|
}
|
|
9742
9750
|
/** 打回状态(按 agent 会话跟踪连续命中轮数) */
|
|
9743
9751
|
const rebukeStates = /* @__PURE__ */ new Map();
|
|
@@ -11479,6 +11487,7 @@ x.lex;
|
|
|
11479
11487
|
*/
|
|
11480
11488
|
var skiff_debug_exports = /* @__PURE__ */ __exportAll({
|
|
11481
11489
|
discoverCccs: () => discoverCccs,
|
|
11490
|
+
jscSafeJsonText: () => jscSafeJsonText,
|
|
11482
11491
|
renderSkiffMarkdown: () => renderSkiffMarkdown,
|
|
11483
11492
|
skiffDebugPage: () => skiffDebugPage,
|
|
11484
11493
|
startSkiffDebugServer: () => startSkiffDebugServer,
|
|
@@ -11546,7 +11555,7 @@ async function discoverCccs(ctx, defaultRoot) {
|
|
|
11546
11555
|
}
|
|
11547
11556
|
/** 问答页 HTML:CCC 切换器 + 角色下拉 + 输入 + 答案区 + 轨迹区(JS 渲染)+ WebUI 链接 */
|
|
11548
11557
|
function skiffDebugPage(cccs, defaultRoot, webPort) {
|
|
11549
|
-
const data = JSON.stringify(cccs).replace(/</g, "\\u003c");
|
|
11558
|
+
const data = jscSafeJsonText(JSON.stringify(cccs).replace(/</g, "\\u003c"));
|
|
11550
11559
|
return `<!DOCTYPE html>
|
|
11551
11560
|
<html lang="zh">
|
|
11552
11561
|
<head>
|
|
@@ -11724,6 +11733,25 @@ function escapeHtml(s) {
|
|
|
11724
11733
|
})[c] ?? c);
|
|
11725
11734
|
}
|
|
11726
11735
|
/**
|
|
11736
|
+
* JSC (Safari/iOS) JSON.parse 快速路径正则兼容化(v1.26.9,S142 调研定稿)。
|
|
11737
|
+
*
|
|
11738
|
+
* 背景:WebKit bug 200190「JavaScriptCore's Regex can't match the content」——JSC 的
|
|
11739
|
+
* JSON.parse 用**内部正则**预校验字符串;内容含**原始** `\u2028`(行分隔符)/`\u2029`
|
|
11740
|
+
* (段分隔符)时正则无法匹配 → 对**合法 JSON** 也抛
|
|
11741
|
+
* `SyntaxError: The string did not match the expected pattern`(sentry-javascript #2487 同源)。
|
|
11742
|
+
* JSON.stringify **不转义** `\u2028`/`\u2029`/`\uFEFF`(它们都是合法 JSON 字符串字符)→
|
|
11743
|
+
* 在 JSON **文本层**把它们替换为 `\uXXXX` 转义序列:JSON.parse 后语义完全一致(还原原字符),
|
|
11744
|
+
* 且 JSC 正则看到的是常规 ASCII 转义(与 JSON.stringify 对控制字符的输出同形态,安全)。
|
|
11745
|
+
*
|
|
11746
|
+
* 3100 问答页客户端 `await res.json()`(acp-http.ts)与页面内嵌 JSON(skiff-debug/acp-http)
|
|
11747
|
+
* 均需此兼容层——iOS Safari 用户实测"复杂回答"触发。
|
|
11748
|
+
*
|
|
11749
|
+
* @param jsonText JSON.stringify 的输出文本;原地等价替换,返回 JSC 安全文本
|
|
11750
|
+
*/
|
|
11751
|
+
function jscSafeJsonText(jsonText) {
|
|
11752
|
+
return jsonText.replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029").replace(/\uFEFF/g, "\\uFEFF");
|
|
11753
|
+
}
|
|
11754
|
+
/**
|
|
11727
11755
|
* 提取 `<think>…</think>` 块(v1.26.8:**状态机扫描,弃正则**——用户批评"老用正则不是个办法")。
|
|
11728
11756
|
*
|
|
11729
11757
|
* 逐字符扫描识别开/闭标签(大小写不敏感;`<think ...>` 允许属性变体;`</think >` 允许尾随空格),
|
|
@@ -12010,7 +12038,10 @@ var AcpServer = class {
|
|
|
12010
12038
|
});
|
|
12011
12039
|
return { sessions };
|
|
12012
12040
|
}
|
|
12013
|
-
/**
|
|
12041
|
+
/**
|
|
12042
|
+
* session/prompt:{ sessionId, question } → 答案(**v1.26.10:不返回 trajectory**——
|
|
12043
|
+
* 3100 对外只提供问答,轨迹含工具结果等内部信息;3099 调试页另走 /ask 保留)
|
|
12044
|
+
*/
|
|
12014
12045
|
async prompt(params) {
|
|
12015
12046
|
const sessionId = typeof params?.sessionId === "string" ? params.sessionId : void 0;
|
|
12016
12047
|
const question = typeof params?.question === "string" ? params.question : void 0;
|
|
@@ -12018,11 +12049,10 @@ var AcpServer = class {
|
|
|
12018
12049
|
if (!question?.trim()) throw new RpcInvalidParams("session/prompt requires question");
|
|
12019
12050
|
const agent = getSkiffAgent(sessionId);
|
|
12020
12051
|
if (!agent) throw new RpcInvalidParams(`unknown session: ${sessionId} (not recoverable — process restarted?)`);
|
|
12021
|
-
const result = await askSkiff(this.ctx, agent, question, 0);
|
|
12052
|
+
const result = await askSkiff(this.ctx, agent, question, void 0, { includeTrajectory: false });
|
|
12022
12053
|
return {
|
|
12023
12054
|
answer: result.answer,
|
|
12024
|
-
sessionId: result.sessionId
|
|
12025
|
-
trajectory: result.trajectory
|
|
12055
|
+
sessionId: result.sessionId
|
|
12026
12056
|
};
|
|
12027
12057
|
}
|
|
12028
12058
|
/** session/cancel:{ sessionId } → 中断当前 prompt(DSH interrupt) */
|
|
@@ -12131,7 +12161,7 @@ function readBody(req) {
|
|
|
12131
12161
|
});
|
|
12132
12162
|
}
|
|
12133
12163
|
function sendJson(res, status, payload) {
|
|
12134
|
-
const body = JSON.stringify(payload);
|
|
12164
|
+
const body = jscSafeJsonText(JSON.stringify(payload));
|
|
12135
12165
|
res.writeHead(status, {
|
|
12136
12166
|
"Content-Type": "application/json; charset=utf-8",
|
|
12137
12167
|
"Cache-Control": "no-store"
|
|
@@ -12338,13 +12368,12 @@ async function handleAskParsed(ctx, ccc, body, res, ip) {
|
|
|
12338
12368
|
}
|
|
12339
12369
|
}
|
|
12340
12370
|
if (!agent) agent = (await createSkiffAgent(ctx, root, effectiveRole, effectiveCfg, readHandymanConfig(root)?.defaultModel)).agent;
|
|
12341
|
-
const result = await askSkiff(ctx, agent, question, 0);
|
|
12371
|
+
const result = await askSkiff(ctx, agent, question, void 0, { includeTrajectory: false });
|
|
12342
12372
|
sendJson(res, 200, {
|
|
12343
12373
|
answer: result.answer,
|
|
12344
12374
|
answer_html: renderSkiffMarkdown(result.answer, true),
|
|
12345
12375
|
sessionId: result.sessionId,
|
|
12346
|
-
continued
|
|
12347
|
-
trajectory: result.trajectory
|
|
12376
|
+
continued
|
|
12348
12377
|
});
|
|
12349
12378
|
}
|
|
12350
12379
|
/** 问答页未启用提示页 */
|
|
@@ -12530,11 +12559,11 @@ gateKey.focus()
|
|
|
12530
12559
|
}
|
|
12531
12560
|
/** 单容器问答页(v1.26.2→v1.26.6):URL 锁定容器;聊天 UI——消息流 + 连续对话 + key 从列表页记忆(v1.26.6 用户拍板:对话页不再填 key) */
|
|
12532
12561
|
function publicAskContainerPage(ccc) {
|
|
12533
|
-
const data = JSON.stringify({
|
|
12562
|
+
const data = jscSafeJsonText(JSON.stringify({
|
|
12534
12563
|
name: ccc.name,
|
|
12535
12564
|
root: ccc.root,
|
|
12536
12565
|
roles: ccc.roles
|
|
12537
|
-
}).replace(/</g, "\\u003c");
|
|
12566
|
+
}).replace(/</g, "\\u003c"));
|
|
12538
12567
|
return `<!DOCTYPE html>
|
|
12539
12568
|
<html lang="zh">
|
|
12540
12569
|
<head>
|
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.10",
|
|
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": {
|