@shgroup/dsh-serenity-hooks 1.99.0 → 1.100.0
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 +53 -15
- package/lib/seams/tool-visibility.d.ts +18 -4
- 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.
|
|
3
|
+
"version": "1.100.0",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——14 个工具(container_fs/cognitive_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/cheap-worker/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 认知轨迹日志与原地重建 + 网页登录入口/IM 桥/认知轨迹唤醒注册表。轨迹声明 = 轨迹目录下的 trajectory.json(约束面 + 旧标识 uid + CRO 机器绑定 cro.host;旧名 trajectory-constraint.json / skiff.json 仍在读取族里);轨迹提示词 = 轨迹目录下的 PROMPT.md(一条轨迹「是谁、按什么章程工作」,所有轨迹通用,追加在容器层与质量层之后,不替换它们)。适配 DSH 0.1.7-rc.1 / 0.2.0-rc.1 / 0.2.1-rc.1(三档,deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
package/lib/index.js
CHANGED
|
@@ -12635,8 +12635,6 @@ function createContainerAdminTool(ctx) {
|
|
|
12635
12635
|
}
|
|
12636
12636
|
//#endregion
|
|
12637
12637
|
//#region src/seams/tool-visibility.ts
|
|
12638
|
-
/** ACC 自己注册的工具名集合(退化档只发这些 —— 它们一定在册) */
|
|
12639
|
-
const REGISTERED_TOOLS_SET = new Set(REGISTERED_TOOLS);
|
|
12640
12638
|
/** 收集器:把各来源的 deny 合并成一个判决(**纯函数、无副作用**) */
|
|
12641
12639
|
function collectVisibilityDecision(sources) {
|
|
12642
12640
|
const deny = /* @__PURE__ */ new Set();
|
|
@@ -12668,12 +12666,13 @@ const applied = /* @__PURE__ */ new Map();
|
|
|
12668
12666
|
* (旧集合是新集合的子集时叠不叠都看不出来,但**不是子集时**会残留 —— 必须撤。)
|
|
12669
12667
|
* ③ 🔴 **未注册的名字不许炸掉整次发射**:宿主契约"unknown names … fail"。
|
|
12670
12668
|
* 合并后集合里只要有一个不在册的名字,整次 restrict 就失败 ⇒ 六个机制**全都不生效**。
|
|
12671
|
-
* ⇒ 策略 = **直接发 →
|
|
12672
|
-
*
|
|
12669
|
+
* ⇒ 策略 = **直接发 → 被拒时从宿主的错误文案里解析出它点名的未知名字 → 只剔那几个、其余重发一次**。
|
|
12670
|
+
* 被剔掉的名字进 `dropped`(调用方决定要不要告警)。
|
|
12673
12671
|
* ⚠️ **不做 `tools.get` 预探活** —— 那个视图查不出 agent-plane 贡献的工具
|
|
12674
12672
|
* (`bash` / `schedule_*`),会把**在册的名字误判成未注册**(见下方发射段的实测记录)。
|
|
12675
|
-
*
|
|
12676
|
-
*
|
|
12673
|
+
* 🔴 **也不按"谁注册的"降级** —— `REGISTERED_TOOLS` 只含 ACC 自己的 14 个,
|
|
12674
|
+
* 用它当"在册面"会**整类丢掉宿主工具**(2026-10-24 真机缺陷,见发射段)。
|
|
12675
|
+
* ⇒ 唯一合法的在册判据是**宿主自己的回答**:要么发一次成功,要么它说出哪些名字不认识。
|
|
12677
12676
|
*
|
|
12678
12677
|
* @returns `'unchanged'` / `'applied'` / `'failed'`(`failed` 时 `deny` 保持原样)
|
|
12679
12678
|
*/
|
|
@@ -12716,33 +12715,72 @@ function applyVisibilityDecision(agent, sessionId, decision) {
|
|
|
12716
12715
|
dropped
|
|
12717
12716
|
};
|
|
12718
12717
|
} catch (firstError) {
|
|
12719
|
-
const
|
|
12720
|
-
|
|
12718
|
+
const message = errorText(firstError);
|
|
12719
|
+
const unknown = parseUnknownToolNames(message);
|
|
12720
|
+
if (unknown.length === 0) return {
|
|
12721
12721
|
status: "failed",
|
|
12722
12722
|
dropped,
|
|
12723
|
-
error:
|
|
12723
|
+
error: message
|
|
12724
|
+
};
|
|
12725
|
+
const unknownSet = new Set(unknown);
|
|
12726
|
+
const remaining = names.filter((n) => !unknownSet.has(n));
|
|
12727
|
+
dropped.push(...names.filter((n) => unknownSet.has(n)));
|
|
12728
|
+
if (remaining.length === 0) return {
|
|
12729
|
+
status: "failed",
|
|
12730
|
+
dropped,
|
|
12731
|
+
error: message
|
|
12724
12732
|
};
|
|
12725
|
-
const abandoned = names.filter((n) => !REGISTERED_TOOLS_SET.has(n));
|
|
12726
12733
|
try {
|
|
12727
|
-
const dispose = tools.restrict({ deny:
|
|
12734
|
+
const dispose = tools.restrict({ deny: remaining });
|
|
12728
12735
|
applied.set(sessionId, {
|
|
12729
|
-
signature
|
|
12730
|
-
|
|
12736
|
+
signature: decisionSignature({
|
|
12737
|
+
...decision,
|
|
12738
|
+
deny: remaining
|
|
12739
|
+
}),
|
|
12740
|
+
deny: remaining,
|
|
12731
12741
|
dispose
|
|
12732
12742
|
});
|
|
12733
12743
|
return {
|
|
12734
12744
|
status: "applied",
|
|
12735
|
-
dropped
|
|
12745
|
+
dropped
|
|
12736
12746
|
};
|
|
12737
12747
|
} catch (secondError) {
|
|
12738
12748
|
return {
|
|
12739
12749
|
status: "failed",
|
|
12740
12750
|
dropped,
|
|
12741
|
-
error: secondError
|
|
12751
|
+
error: errorText(secondError)
|
|
12742
12752
|
};
|
|
12743
12753
|
}
|
|
12744
12754
|
}
|
|
12745
12755
|
}
|
|
12756
|
+
/** 取异常的可读文案(非 Error 也能取到 message;都没有则 String()) */
|
|
12757
|
+
function errorText(e) {
|
|
12758
|
+
if (e instanceof Error) return e.message;
|
|
12759
|
+
if (typeof e === "object" && e !== null && "message" in e && typeof e.message === "string") return e.message;
|
|
12760
|
+
return String(e);
|
|
12761
|
+
}
|
|
12762
|
+
/**
|
|
12763
|
+
* 从宿主的 `tools.restrict()` 错误文案里解析出**被点名的未知工具名**。
|
|
12764
|
+
*
|
|
12765
|
+
* 宿主逐字形态(`dsh-tools/lib/types/index.js` 的 `restrict()`):
|
|
12766
|
+
* ```
|
|
12767
|
+
* tools.restrict() names unknown global tool(s) "a", "b"; known global tools: x, y, z
|
|
12768
|
+
* ```
|
|
12769
|
+
* 单数时是 `tool`,复数时是 `tool(s)`——两种都匹配。
|
|
12770
|
+
*
|
|
12771
|
+
* 🔴 **只取分号之前那一段**:分号后是 `known global tools:` 清单,**不能**误当成未知名字。
|
|
12772
|
+
* 🔴 解析不出来就返回 `[]`(调用方据此走"如实失败、不记账"),**绝不猜**。
|
|
12773
|
+
*/
|
|
12774
|
+
function parseUnknownToolNames(message) {
|
|
12775
|
+
const head = message.split(";")[0] ?? "";
|
|
12776
|
+
if (!/names unknown global tool/.test(head)) return [];
|
|
12777
|
+
const out = [];
|
|
12778
|
+
for (const m of head.matchAll(/"([^"]+)"/g)) {
|
|
12779
|
+
const name = m[1];
|
|
12780
|
+
if (name !== void 0 && name !== "") out.push(name);
|
|
12781
|
+
}
|
|
12782
|
+
return [...new Set(out)];
|
|
12783
|
+
}
|
|
12746
12784
|
/** 会话销毁清理(防 per-会话 Map 无界增长;lifecycle 调用) */
|
|
12747
12785
|
function forgetToolVisibility(sessionId) {
|
|
12748
12786
|
const existing = applied.get(sessionId);
|
|
@@ -51,12 +51,13 @@ export declare function getToolVisibilityDiagnostics(): {
|
|
|
51
51
|
* (旧集合是新集合的子集时叠不叠都看不出来,但**不是子集时**会残留 —— 必须撤。)
|
|
52
52
|
* ③ 🔴 **未注册的名字不许炸掉整次发射**:宿主契约"unknown names … fail"。
|
|
53
53
|
* 合并后集合里只要有一个不在册的名字,整次 restrict 就失败 ⇒ 六个机制**全都不生效**。
|
|
54
|
-
* ⇒ 策略 = **直接发 →
|
|
55
|
-
*
|
|
54
|
+
* ⇒ 策略 = **直接发 → 被拒时从宿主的错误文案里解析出它点名的未知名字 → 只剔那几个、其余重发一次**。
|
|
55
|
+
* 被剔掉的名字进 `dropped`(调用方决定要不要告警)。
|
|
56
56
|
* ⚠️ **不做 `tools.get` 预探活** —— 那个视图查不出 agent-plane 贡献的工具
|
|
57
57
|
* (`bash` / `schedule_*`),会把**在册的名字误判成未注册**(见下方发射段的实测记录)。
|
|
58
|
-
*
|
|
59
|
-
*
|
|
58
|
+
* 🔴 **也不按"谁注册的"降级** —— `REGISTERED_TOOLS` 只含 ACC 自己的 14 个,
|
|
59
|
+
* 用它当"在册面"会**整类丢掉宿主工具**(2026-10-24 真机缺陷,见发射段)。
|
|
60
|
+
* ⇒ 唯一合法的在册判据是**宿主自己的回答**:要么发一次成功,要么它说出哪些名字不认识。
|
|
60
61
|
*
|
|
61
62
|
* @returns `'unchanged'` / `'applied'` / `'failed'`(`failed` 时 `deny` 保持原样)
|
|
62
63
|
*/
|
|
@@ -73,5 +74,18 @@ export declare function applyVisibilityDecision(agent: {
|
|
|
73
74
|
dropped: string[];
|
|
74
75
|
error?: string;
|
|
75
76
|
};
|
|
77
|
+
/**
|
|
78
|
+
* 从宿主的 `tools.restrict()` 错误文案里解析出**被点名的未知工具名**。
|
|
79
|
+
*
|
|
80
|
+
* 宿主逐字形态(`dsh-tools/lib/types/index.js` 的 `restrict()`):
|
|
81
|
+
* ```
|
|
82
|
+
* tools.restrict() names unknown global tool(s) "a", "b"; known global tools: x, y, z
|
|
83
|
+
* ```
|
|
84
|
+
* 单数时是 `tool`,复数时是 `tool(s)`——两种都匹配。
|
|
85
|
+
*
|
|
86
|
+
* 🔴 **只取分号之前那一段**:分号后是 `known global tools:` 清单,**不能**误当成未知名字。
|
|
87
|
+
* 🔴 解析不出来就返回 `[]`(调用方据此走"如实失败、不记账"),**绝不猜**。
|
|
88
|
+
*/
|
|
89
|
+
export declare function parseUnknownToolNames(message: string): string[];
|
|
76
90
|
/** 会话销毁清理(防 per-会话 Map 无界增长;lifecycle 调用) */
|
|
77
91
|
export declare function forgetToolVisibility(sessionId: string): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shgroup/dsh-serenity-hooks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.100.0",
|
|
4
4
|
"description": "宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:14 个工具(container_fs/cognitive_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/cheap-worker/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫/对外输出守卫)+ 认知轨迹日志与原地重建 + 网页登录入口/IM 桥/认知轨迹唤醒注册表。轨迹声明 = 轨迹目录下的 trajectory.json(约束面 + 旧标识 uid + CRO 机器绑定 cro.host;旧名 trajectory-constraint.json / skiff.json 仍在读取族里);轨迹提示词 = 轨迹目录下的 PROMPT.md(一条轨迹「是谁、按什么章程工作」,所有轨迹通用,追加在容器层与质量层之后,不替换它们)。适配 DSH 0.1.7-rc.1 / 0.2.0-rc.1 / 0.2.1-rc.1(三档)。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|