@shgroup/dsh-serenity-hooks 1.46.0 → 1.47.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.
@@ -0,0 +1,49 @@
1
+ /**
2
+ * unattended-seam.ts — 无人值守代理回复的**拦截缝**(S142 **D77**,owner 2026-09-23 令「我需要的是一个机制」)
3
+ *
4
+ * ## 停在哪、怎么接(设计 §4 的裁决:**A 的通道 + B 的措辞**)
5
+ *
6
+ * 复用的是**已验证过的**通道——`agent/turn-stopping`(serial)里 `agent.steer()`:
7
+ * 宿主语义 = "**listener 反对就打回**,机器重读 inbox:有新 steer ⇒ 再跑一步,没有 ⇒ 关轮"
8
+ * (`host/contract.ts` 的 `HOST_EVENTS` 原文)。因此:
9
+ * · **轮不结束**(语义正是"有人打回")⇒ **零新机械**;
10
+ * · 文本**写成代理用户的话**(B 的措辞)+ **首句自报身份**(owner 已裁)。
11
+ *
12
+ * 模板 = `output-guard-seam.ts`(同一缝位、同一 `createUserMessage + PLUGIN_SOURCE` 形态)。
13
+ *
14
+ * ## 🔴「这轮是不是真实用户发起的」怎么判(本机制**唯一**的新机械;2026-09-23 取证)
15
+ *
16
+ * 交接块把它列为"动手前必须先查清的一件事",取证结论(读宿主类型面,非猜测):
17
+ *
18
+ * | 事实 | 出处 |
19
+ * |---|---|
20
+ * | 每条进入 inbox 的消息都发 `agent/inbox/inserted { agent, message }`;**在轮内离开 inbox 时**发 `agent/inbox/claimed { agent, message, turn }` | `@deepseek-ai/dsh-agent` README(Inbox 段)+ `runtime-types.d.ts` |
21
+ * | `claimed.turn` = **拥有该消息的那一轮**;`turn-stopping.turn` = **即将关闭的那一轮** ⇒ 两者同编号可直接比对 | `runtime-types.d.ts` 同一文件两处 `turn` 声明 |
22
+ * | 消息来源可辨:`MessageSourceMap` 里**真实用户** = `kind: 'user'`(`user` / `user-rpc` 两种形态**同 kind**);**ACC 自己注入**的一律 `kind: 'plugin:dsh-serenity-hooks'`(v1.47.0 改;旧值 = `'plugin'`) | `@deepseek-ai/dsh-llm` `src/message.ts` 的 `MessageSourceMap`(合并和类型)+ 本仓 `message-source.ts`(**唯一**声明处与常量处) |
23
+ *
24
+ * ⇒ **判据 = 「这一轮 claim 到的消息里,有没有 `source.kind === 'user'`」**。
25
+ * 没有现成信号时本可退化为"记账法"(我们知道自己投过什么),**但不必**:宿主已给出一手信号。
26
+ *
27
+ * ## 🔴 为什么"用户发起的轮"要跳过(这是设计 §3-③ 的本意,别当成漏洞)
28
+ *
29
+ * 用户**刚说完话**⇒ 人就在跟前,代理插话既是冒充也是浪费。**"用户说完走开"那种情形**
30
+ * 由**绳(长周期保险丝)/其它非用户发起的唤醒**覆盖:那条轮**不是**用户发起的 ⇒ 代理接手,
31
+ * 一路推进到**合法收束**。⇒ 两个机制合起来才等于"用户走开后会话还能自己跑完"。
32
+ *
33
+ * ## 🔴 铁律(与 `unattended-ops.ts` 同族)
34
+ *
35
+ * **本模块的任何失败都不得影响 turn 收尾**:所有 handler 包 try/catch,异常只记一行 console。
36
+ */
37
+ import type { Context } from 'cordis';
38
+ import type { Agent } from '@deepseek-ai/dsh-agent';
39
+ /**
40
+ * 装配无人值守代理缝(`index.ts` apply 调用)。
41
+ *
42
+ * 订阅三个事件(**都已在 `host/contract.ts` 白名单里**,新增的 `agent/inbox/claimed` 同批登记):
43
+ * · `agent/inbox/claimed` —— 记「真实用户发起的轮次」;用户回来时**让位**(清代理段 + 记流水);
44
+ * · `agent/turn-stopping` —— 判定 + 注入(本机制主体);
45
+ * · `agent/disposed` / `session/disposed` —— 载体销毁清表(**本容器栽过 5 次"只增不清"**)。
46
+ */
47
+ export declare function registerUnattendedSeam(ctx: Context): void;
48
+ /** 类型再导出(调用方少一处 import) */
49
+ export type { Agent as UnattendedAgent };
@@ -1,8 +1,8 @@
1
1
  import { r as hostService, t as hostAgents } from "./access-fiehjxV6.js";
2
2
  import { g as resolveInside } from "./ccc-DG4Oc7I1.js";
3
3
  import { o as listCccs } from "./ccc-roots-FxWXuZPw.js";
4
- import { D as localIdStamp, E as localHuman, f as findSession, n as listBoundSessionIds, w as isoLocal, y as sessionsRoot } from "./trajectory-bound-BPWKkzJC.js";
5
- import { t as readSimpleSettings } from "./settings-section-CIuyoSOX.js";
4
+ import { E as isoLocal, O as localHuman, i as listBoundSessionIds, k as localIdStamp, m as findSession, n as PLUGIN_SOURCE, x as sessionsRoot } from "./message-source-Boc-AbHs.js";
5
+ import { t as readSimpleSettings } from "./settings-section-DTJW4smh.js";
6
6
  import { basename, dirname, join } from "node:path";
7
7
  import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from "node:fs";
8
8
  import { spawn } from "node:child_process";
@@ -857,7 +857,7 @@ const TURN_TTL_MS = 18e5;
857
857
  * 进程内的「正在跑」表(键 = 载体 dsh 会话 id)。
858
858
  *
859
859
  * ⚠️ **仅内存**:进程重启即空 —— 这是**可接受的**,因为重启后宿主会重发
860
- * `session-start`(或至少下一次 `turn-stopping` 会清掉残留),且空表 = "没有在跑",
860
+ * `agent/created`(或至少下一次 `turn-stopping` 会清掉残留),且空表 = "没有在跑",
861
861
  * 落到上面那条**便宜**的误判方向。
862
862
  */
863
863
  const runningBySession = /* @__PURE__ */ new Map();
@@ -866,7 +866,7 @@ function sessionIdOf(agent) {
866
866
  const id = agent?.session?.id;
867
867
  return typeof id === "string" && id !== "" ? id : null;
868
868
  }
869
- /** 标记「在跑」(`agent/session-start` + `agent/status=running` 调用) */
869
+ /** 标记「在跑」(`agent/created` + `agent/status=running` 调用) */
870
870
  function markTurnRunning(sessionId, nowMs, turn = null) {
871
871
  if (!sessionId) return;
872
872
  runningBySession.set(sessionId, {
@@ -914,7 +914,7 @@ function runningCarriersOf(boundSessionIds, nowMs, ttlMs = TURN_TTL_MS) {
914
914
  * 装配追踪(`index.ts` apply 调用):订阅四个既有事件 + 拆卸。
915
915
  *
916
916
  * **为什么订阅四个而不是两个**(R↓):
917
- * · 前两个(`session-start` / `turn-stopping`)负责**语义**——"在不在跑";
917
+ * · 前两个(`agent/created` / `turn-stopping`)负责**语义**——"在不在跑";
918
918
  * · 后两个(`agent/disposed` / `session/disposed`)负责**生命周期**——
919
919
  * 载体没了必须清项,否则表按载体只增(本模块的头号风险)。
920
920
  *
@@ -930,7 +930,7 @@ function registerCroTurnTracking(ctx) {
930
930
  console.log(`[serenity-hooks] ✗ CRO turn 追踪未装配(${event} 不可用): ${String(err?.message ?? err)}`);
931
931
  }
932
932
  };
933
- on("agent/session-start", (payload) => {
933
+ on("agent/created", (payload) => {
934
934
  const id = sessionIdOf(payload?.agent);
935
935
  if (id) markTurnRunning(id, Date.now());
936
936
  });
@@ -1370,10 +1370,6 @@ function createClock(opts) {
1370
1370
  }
1371
1371
  //#endregion
1372
1372
  //#region src/wake-scheduler.ts
1373
- const PLUGIN_SOURCE = {
1374
- kind: "plugin",
1375
- plugin: "dsh-serenity-hooks"
1376
- };
1377
1373
  /**
1378
1374
  * 解析条目的 target(`S###` 或完整目录名)→ 目录名 + SESSION.md 路径。
1379
1375
  * @param root CCC 根
@@ -1393,7 +1389,9 @@ function resolveWakeTarget(root, target) {
1393
1389
  /**
1394
1390
  * 🔴 **本钟的全局闸已于 2026-09-21 砍掉**(所有者令逐字:「**send-later 的开关不再重要了,砍掉**」)。
1395
1391
  *
1396
- * **为什么砍**(R↓):唤醒已从"可选实验能力"长成**全容器的续接绳**——S142/S151/S185 的链、
1392
+ * **为什么砍**(R↓):唤醒已从"可选实验能力"长成**全容器的续接绳**(🔵 **术语说明,2026-09-23 补**:
1393
+ * **"绳" = 我们对自己用 `send-later` 给自己排的"定时叫醒"条目的俗称** —— 一条链每轮给自己排下一根,
1394
+ * 链才不断。本仓注释与 SESSION.md 沿用此说法,**它不是产品名、也不是宿主概念**)——S142/S151/S185 的链、
1397
1395
  * 跨轨迹投递、`send-now`/`send-later` 都走它。留一个"能被误关的开关"的**代价**是
1398
1396
  * "整条链静默停摆且无人告警"(本仓已实测过同族事故:闸关 6.6h 零 tick、断链 1 天 14 小时);
1399
1397
  * 而**收益**只剩"关掉一个 5min unref 空检查"。⇒ **收益 < 代价,故删闸**(不是改为缺省开——是**没有这个键了**)。
@@ -1887,4 +1885,4 @@ function registerWakeScheduler(ctx) {
1887
1885
  registerDisposer(ctx, "trajectory 唤醒调度器", () => clock.dispose());
1888
1886
  }
1889
1887
  //#endregion
1890
- export { registerDisposer as a, addWake as c, registerCroTurnTracking as i, listWakes as l, sendToTrajectory as n, buildCroSnapshot as o, wakeSchedulerState as r, WAKE_CATCH_UP_MS as s, registerWakeScheduler as t };
1888
+ export { registerDisposer as a, WAKE_CATCH_UP_MS as c, registerCroTurnTracking as i, addWake as l, sendToTrajectory as n, CRO_FILENAME as o, wakeSchedulerState as r, buildCroSnapshot as s, registerWakeScheduler as t, listWakes as u };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shgroup/dsh-serenity-hooks",
3
- "version": "1.46.0",
4
- "description": "宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:11 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/im-bridge/acc-diag)+ 机械约束(安全模式/工作区围墙/密钥守卫/对外输出守卫)+ 工作日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/trajectory 唤醒注册表。适配 DSH 0.1.5-rc.2。",
3
+ "version": "1.47.0",
4
+ "description": "宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:11 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/im-bridge/acc-diag)+ 机械约束(安全模式/工作区围墙/密钥守卫/对外输出守卫)+ 工作日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/trajectory 唤醒注册表。适配 DSH 0.1.7-rc.1。",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -53,23 +53,23 @@
53
53
  }
54
54
  },
55
55
  "peerDependencies": {
56
- "@deepseek-ai/cordis": "^4.0.2",
57
- "@deepseek-ai/dsh-agent": "^0.1.5-rc.2",
58
- "@deepseek-ai/dsh-agent-loop": "^0.1.5-rc.2",
59
- "@deepseek-ai/dsh-agent-presets": "^0.1.5-rc.2",
60
- "@deepseek-ai/dsh-compaction": "^0.1.5-rc.2",
61
- "@deepseek-ai/dsh-host-webserver": "^0.1.5-rc.2",
62
- "@deepseek-ai/dsh-llm": "^0.1.5-rc.2",
63
- "@deepseek-ai/dsh-session": "^0.1.5-rc.2",
64
- "@deepseek-ai/dsh-session-title": "^0.1.5-rc.2",
65
- "@deepseek-ai/dsh-shell": "^0.1.5-rc.2",
66
- "@deepseek-ai/dsh-shell-env": "^0.1.5-rc.2",
67
- "@deepseek-ai/dsh-skill": "^0.1.5-rc.2",
68
- "@deepseek-ai/dsh-system-prompt": "^0.1.5-rc.2",
69
- "@deepseek-ai/dsh-tools": "^0.1.5-rc.2",
70
- "@deepseek-ai/dsh-web": "^0.1.5-rc.2",
71
- "@deepseek-ai/dsh-web-fetch-http": "^0.1.5-rc.2",
72
- "@deepseek-ai/schemastery": "^3.18.2",
56
+ "@deepseek-ai/cordis": "^4.0.4",
57
+ "@deepseek-ai/dsh-agent": "^0.1.7-rc.1",
58
+ "@deepseek-ai/dsh-agent-loop": "^0.1.7-rc.1",
59
+ "@deepseek-ai/dsh-agent-preset-registry": "^0.1.7-rc.1",
60
+ "@deepseek-ai/dsh-compaction": "^0.1.7-rc.1",
61
+ "@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.1",
62
+ "@deepseek-ai/dsh-llm": "^0.1.7-rc.1",
63
+ "@deepseek-ai/dsh-session": "^0.1.7-rc.1",
64
+ "@deepseek-ai/dsh-session-title": "^0.1.7-rc.1",
65
+ "@deepseek-ai/dsh-shell": "^0.1.7-rc.1",
66
+ "@deepseek-ai/dsh-shell-env": "^0.1.7-rc.1",
67
+ "@deepseek-ai/dsh-skill": "^0.1.7-rc.1",
68
+ "@deepseek-ai/dsh-system-prompt": "^0.1.7-rc.1",
69
+ "@deepseek-ai/dsh-tools": "^0.1.7-rc.1",
70
+ "@deepseek-ai/dsh-web": "^0.1.7-rc.1",
71
+ "@deepseek-ai/dsh-web-fetch-http": "^0.1.7-rc.1",
72
+ "@deepseek-ai/schemastery": "^3.18.4",
73
73
  "cordis": "^4.0.0-rc.7"
74
74
  },
75
75
  "peerDependenciesMeta": {
@@ -85,7 +85,7 @@
85
85
  "@deepseek-ai/dsh-agent-loop": {
86
86
  "optional": true
87
87
  },
88
- "@deepseek-ai/dsh-agent-presets": {
88
+ "@deepseek-ai/dsh-agent-preset-registry": {
89
89
  "optional": true
90
90
  },
91
91
  "@deepseek-ai/dsh-compaction": {
@@ -96,38 +96,38 @@
96
96
  }
97
97
  },
98
98
  "devDependencies": {
99
- "@deepseek-ai/cordis": "^4.0.2",
100
- "@deepseek-ai/dsh-agent": "0.1.5-rc.2",
101
- "@deepseek-ai/dsh-agent-loop": "0.1.5-rc.2",
102
- "@deepseek-ai/dsh-agent-presets": "0.1.5-rc.2",
103
- "@deepseek-ai/dsh-api-session-controller": "0.1.5-rc.2",
104
- "@deepseek-ai/dsh-client-connection": "0.1.5-rc.2",
105
- "@deepseek-ai/dsh-client-locale": "0.1.5-rc.2",
106
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.5-rc.2",
107
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.5-rc.2",
108
- "@deepseek-ai/dsh-client-ui-renderer": "0.1.5-rc.2",
109
- "@deepseek-ai/dsh-client-ui-session": "0.1.5-rc.2",
110
- "@deepseek-ai/dsh-client-ui-settings": "0.1.5-rc.2",
111
- "@deepseek-ai/dsh-client-ui-slots": "0.1.5-rc.2",
112
- "@deepseek-ai/dsh-compaction": "0.1.5-rc.2",
113
- "@deepseek-ai/dsh-host-webserver": "0.1.5-rc.2",
114
- "@deepseek-ai/dsh-llm": "0.1.5-rc.2",
115
- "@deepseek-ai/dsh-session": "0.1.5-rc.2",
116
- "@deepseek-ai/dsh-session-persistence": "0.1.5-rc.2",
117
- "@deepseek-ai/dsh-session-projection": "0.1.5-rc.2",
118
- "@deepseek-ai/dsh-session-title": "0.1.5-rc.2",
119
- "@deepseek-ai/dsh-settings": "0.1.5-rc.2",
120
- "@deepseek-ai/dsh-shell": "0.1.5-rc.2",
121
- "@deepseek-ai/dsh-shell-env": "0.1.5-rc.2",
122
- "@deepseek-ai/dsh-skill": "0.1.5-rc.2",
123
- "@deepseek-ai/dsh-subagent": "0.1.5-rc.2",
124
- "@deepseek-ai/dsh-system-prompt": "0.1.5-rc.2",
125
- "@deepseek-ai/dsh-token-meter": "0.1.5-rc.2",
126
- "@deepseek-ai/dsh-tools": "0.1.5-rc.2",
127
- "@deepseek-ai/dsh-web": "0.1.5-rc.2",
128
- "@deepseek-ai/dsh-web-fetch-http": "0.1.5-rc.2",
129
- "@deepseek-ai/dsh-workspace": "0.1.5-rc.2",
130
- "@deepseek-ai/schemastery": "^3.18.2",
99
+ "@deepseek-ai/cordis": "^4.0.4",
100
+ "@deepseek-ai/dsh-agent": "0.1.7-rc.1",
101
+ "@deepseek-ai/dsh-agent-loop": "0.1.7-rc.1",
102
+ "@deepseek-ai/dsh-agent-preset-registry": "0.1.7-rc.1",
103
+ "@deepseek-ai/dsh-api-session-controller": "0.1.7-rc.1",
104
+ "@deepseek-ai/dsh-client-connection": "0.1.7-rc.1",
105
+ "@deepseek-ai/dsh-client-locale": "0.1.7-rc.1",
106
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.1",
107
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.1",
108
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.1",
109
+ "@deepseek-ai/dsh-client-ui-session": "0.1.7-rc.1",
110
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.7-rc.1",
111
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.1",
112
+ "@deepseek-ai/dsh-compaction": "0.1.7-rc.1",
113
+ "@deepseek-ai/dsh-host-webserver": "0.1.7-rc.1",
114
+ "@deepseek-ai/dsh-llm": "0.1.7-rc.1",
115
+ "@deepseek-ai/dsh-session": "0.1.7-rc.1",
116
+ "@deepseek-ai/dsh-session-persistence": "0.1.7-rc.1",
117
+ "@deepseek-ai/dsh-session-projection": "0.1.7-rc.1",
118
+ "@deepseek-ai/dsh-session-title": "0.1.7-rc.1",
119
+ "@deepseek-ai/dsh-settings": "0.1.7-rc.1",
120
+ "@deepseek-ai/dsh-shell": "0.1.7-rc.1",
121
+ "@deepseek-ai/dsh-shell-env": "0.1.7-rc.1",
122
+ "@deepseek-ai/dsh-skill": "0.1.7-rc.1",
123
+ "@deepseek-ai/dsh-subagent": "0.1.7-rc.1",
124
+ "@deepseek-ai/dsh-system-prompt": "0.1.7-rc.1",
125
+ "@deepseek-ai/dsh-token-meter": "0.1.7-rc.1",
126
+ "@deepseek-ai/dsh-tools": "0.1.7-rc.1",
127
+ "@deepseek-ai/dsh-web": "0.1.7-rc.1",
128
+ "@deepseek-ai/dsh-web-fetch-http": "0.1.7-rc.1",
129
+ "@deepseek-ai/dsh-workspace": "0.1.7-rc.1",
130
+ "@deepseek-ai/schemastery": "^3.18.4",
131
131
  "@types/node": "^20.0.0",
132
132
  "@types/qrcode-generator": "^1.0.6",
133
133
  "@types/react": "^18.2.0",