@shgroup/dsh-serenity-hooks 1.59.2 → 1.59.3

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-serenity-hooks",
3
- "version": "1.59.2",
3
+ "version": "1.59.3",
4
4
  "main": "lib/index.js",
5
5
  "description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——14 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/cheap-worker/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 轨迹日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/trajectory 唤醒注册表。适配 DSH 0.1.7-rc.1 与 0.2.0-rc.1(双档,deepseek-ai/deepseek-harness)。",
6
6
  "engines": {
@@ -86,14 +86,27 @@ export declare function hostWeb(ctx: unknown): HostWeb | undefined;
86
86
  /**
87
87
  * `ctx.subagents`(lazy;v1.31.3:cheap-worker foreground 模式的委派正门)。
88
88
  *
89
- * 形状对照宿主 rc.1:`SubagentRuntime.start(name, request)` → `SubagentRun`
90
- * (`result` / `dispose` / `id`)。本模块只做形状收口;语义与错误处理归调用方。
89
+ * 🔴 **形状对照宿主 `0.2.1-rc.1`(v1.59.3 适配)**:旧成员 `start(name, request)` **已消失**,
90
+ * 改由 `startActivation(spec)` 承担(实名由 `spec.provider` 指定,我们仍传 `'spawn'`)。
91
+ * - 旧:`start(name: string, request: SubagentStartRequest): Promise<SubagentRun>`
92
+ * - 新:`startActivation(spec: SubagentActivationSpec): Promise<SubagentActivation>`(两个重载)
93
+ * 实测依据(**类型面与运行时都核过**,不是只看一边):
94
+ * `_tmp/host-0.2.1-rc.1/…/dsh-subagent/lib/types/index.d.ts:135,145` +
95
+ * 同包 `lib/index.js` 里**只有** `async startActivation(spec)`。
96
+ * ⚠️ **两个方法都保留为可选**:本仓仍声明支持 `0.1.7-rc.1` 双档(`VERIFIED_HOST_BANDS`),
97
+ * 而 0.1.7 那代同样只有 `start` —— **删掉 `start` 会让旧档在类型面说谎**。
98
+ * 调用方按"先新后旧"选用,见 `cheap-worker.ts` 的 `resolveSubagentStarter()`。
99
+ *
100
+ * 本模块只做形状收口;语义与错误处理归调用方。
91
101
  *
92
102
  * 注(v1.31.4):本服务**不在** dsp 的 `inject` 列表内,因此走 `hostInjected` 的
93
103
  * 回落分支(`ctx.get`)——见 `hostInjected` 的 v1.31.4 说明与真实 cordis 用例。
94
104
  */
95
105
  interface HostSubagents {
106
+ /** 宿主 `0.1.7-rc.*` / `0.2.0-rc.*`(旧形态;0.2.1-rc.1 起已移除) */
96
107
  start?: (name: string, request: unknown) => Promise<unknown>;
108
+ /** 宿主 `0.2.1-rc.1+`(新形态;`spec.provider` 即旧 `name`) */
109
+ startActivation?: (spec: unknown) => Promise<unknown>;
97
110
  }
98
111
  export declare function hostSubagents(ctx: unknown): HostSubagents | undefined;
99
112
  /**
@@ -82,6 +82,14 @@ export declare const HOST_EVENTS: readonly HostEventContract[];
82
82
  * - ⇒ 双档是**唯一不把本机宿主堵死的写法**(两档在真 semver 下均 PASS)。
83
83
  * 档上界取 `<0.2.0` / `<0.3.0`(即 `^0.2.0-rc.1` 的 caret 上界):第二档同时覆盖
84
84
  * `0.2.0` 正式版与后续 `0.2.0-rc.N`。
85
+ *
86
+ * 🆕 **第三档 `^0.2.1-rc.1`(v1.59.3 适配,2026-10-17)** —— 为什么非加不可:
87
+ * - npm 的 `^0.2.0-rc.1` 对**预发布**只放行**同一 `major.minor.patch`** 的 prerelease
88
+ * ⇒ **`0.2.1-rc.1` 不满足它**(patch 位不同)⇒ 宿主门会**整包拒绝安装**(D98 同族)。
89
+ * - 而第二档的 `ceiling: '0.3.0'` 本来就"包含" 0.2.1 —— 那是**我们自己的手写比较器**的语义;
90
+ * 两个判据(真 semver 门 vs 手写区间)在这里**给出相反答案**,故必须把第三档显式写出来,
91
+ * 让**派生串**({@link REQUIRED_HOST_RANGE})里真的出现 `^0.2.1-rc.1`。
92
+ * ⚠️ **加档不是收窄**:前两档原样保留(0.1.7 / 0.2.0 两代仍被声明支持)。
85
93
  */
86
94
  export declare const VERIFIED_HOST_BANDS: readonly {
87
95
  floor: string;
package/lib/index.js CHANGED
@@ -9178,12 +9178,68 @@ function parseForegroundJobs(raw) {
9178
9178
  }
9179
9179
  return jobs;
9180
9180
  }
9181
+ /**
9182
+ * 选出一个可用的"启动子 agent"函数(**先新后旧**)。
9183
+ *
9184
+ * 🔴 **为什么需要这一层**(v1.59.3 适配,2026-10-17):
9185
+ * 宿主 `0.2.1-rc.1` **移除了** `SubagentRuntime.start(name, request)`,改由
9186
+ * `startActivation(spec)` 承担;而 `0.1.7-rc.*` / `0.2.0-rc.*` **只有** `start`。
9187
+ * 本仓仍声明支持双档(`VERIFIED_HOST_BANDS`)⇒ **不能只留一边**。
9188
+ *
9189
+ * 形状差异(逐字取自两端 `.d.ts`):
9190
+ * · 旧:`start('spawn', {label?, prompt, parent, signal, agentOptions, toolFilter})`
9191
+ * · 新:`startActivation({provider:'spawn', label, request:{prompt, parent, agentOptions}, signal, delivery})`
9192
+ * —— 注意 `label` 在新 spec 里是**必填**(`readonly label: string`),故这里补默认值。
9193
+ *
9194
+ * @returns 一个统一签名的启动器;两者都不存在 ⇒ `undefined`(由调用方报**可诊断**的错)
9195
+ */
9196
+ function resolveSubagentStarter(subagents) {
9197
+ if (typeof subagents.startActivation === "function") {
9198
+ const fn = subagents.startActivation;
9199
+ return (req) => fn({
9200
+ provider: "spawn",
9201
+ label: req.label,
9202
+ request: {
9203
+ prompt: req.prompt,
9204
+ parent: req.parent,
9205
+ agentOptions: req.agentOptions,
9206
+ ...req.cwd === void 0 ? {} : { cwd: req.cwd }
9207
+ },
9208
+ signal: req.signal,
9209
+ delivery: "caller"
9210
+ });
9211
+ }
9212
+ if (typeof subagents.start === "function") {
9213
+ const fn = subagents.start;
9214
+ return (req) => fn("spawn", {
9215
+ label: req.label,
9216
+ prompt: req.prompt,
9217
+ parent: req.parent,
9218
+ signal: req.signal,
9219
+ agentOptions: req.agentOptions,
9220
+ toolFilter: { deny: ["cheap-worker"] },
9221
+ ...req.cwd === void 0 ? {} : { cwd: req.cwd }
9222
+ });
9223
+ }
9224
+ }
9181
9225
  /** 拼接 SubagentResult.output(ContentBlock[])中的文本块 */
9182
9226
  function subagentOutputText(output) {
9183
9227
  if (!Array.isArray(output)) return "";
9184
9228
  return output.filter((b) => typeof b === "object" && b !== null).filter((b) => b.type === "text" && typeof b.text === "string").map((b) => b.text).join("");
9185
9229
  }
9186
9230
  /**
9231
+ * 任务首行 → 子会话 label(截断)。
9232
+ *
9233
+ * 🔴 为什么必须有一个:新宿主 `SubagentActivationSpec.label` 是**必填**(`readonly label: string`),
9234
+ * 而我们对外把 `label` 当可选参数 ⇒ 缺省时必须自己造一个,否则 spec 不合法。
9235
+ * 取任务首行而不是空串:子会话在列表里要能被人认出来(空串等于没有标识)。
9236
+ */
9237
+ function firstLineLabel(task) {
9238
+ const line = task.split(/\r?\n/)[0]?.trim() ?? "";
9239
+ const clipped = line.length > 60 ? `${line.slice(0, 60)}…` : line;
9240
+ return clipped === "" ? "task" : clipped;
9241
+ }
9242
+ /**
9187
9243
  * providerPreflight — 在**创建任何 worker 之前**判定「本机有没有该 provider 的 adapter」。
9188
9244
  *
9189
9245
  * 返回**可执行**的错误文本;`null` = 可用,**或无法取证**(服务缺失 / 形状不符 / 读取抛错
@@ -9231,7 +9287,8 @@ async function runForegroundJob(ctx, opts) {
9231
9287
  const { task, label, model, models, parent, signal } = opts;
9232
9288
  requireWhitelistedModel(model, models);
9233
9289
  const subagents = hostSubagents(ctx);
9234
- if (!subagents?.start) throw new Error("cheap-worker: host subagents service unavailable — neither ctx.subagents nor ctx.get(\"subagents\") yielded a start() function. Check `dashboard health` (host-contract section, service \"subagents\").");
9290
+ const starter = subagents === void 0 ? void 0 : resolveSubagentStarter(subagents);
9291
+ if (starter === void 0) throw new Error("cheap-worker: host subagents service unavailable — neither ctx.subagents.startActivation (0.2.1-rc.1+) nor ctx.subagents.start (0.1.7-rc.* / 0.2.0-rc.*) yielded a starter function. Check `dashboard health` (host-contract section, service \"subagents\").");
9235
9292
  const preflight = providerPreflight(ctx, model);
9236
9293
  if (preflight !== null) return {
9237
9294
  mode: "foreground",
@@ -9242,8 +9299,8 @@ async function runForegroundJob(ctx, opts) {
9242
9299
  diagnostic: preflight
9243
9300
  };
9244
9301
  const { provider, model: modelName } = splitModel(model);
9245
- const run = await subagents.start("spawn", {
9246
- ...label === void 0 ? {} : { label },
9302
+ const run = await starter({
9303
+ label: label ?? firstLineLabel(task),
9247
9304
  prompt: [{
9248
9305
  type: "text",
9249
9306
  text: task
@@ -9253,8 +9310,7 @@ async function runForegroundJob(ctx, opts) {
9253
9310
  agentOptions: {
9254
9311
  ...provider === void 0 ? {} : { provider },
9255
9312
  model: modelName
9256
- },
9257
- toolFilter: { deny: ["cheap-worker"] }
9313
+ }
9258
9314
  });
9259
9315
  try {
9260
9316
  const result = run.result === void 0 ? {} : await run.result;
@@ -9265,7 +9321,7 @@ async function runForegroundJob(ctx, opts) {
9265
9321
  model,
9266
9322
  stopReason,
9267
9323
  output: subagentOutputText(result.output),
9268
- ...typeof run.id === "string" ? { childId: run.id } : {},
9324
+ ...typeof (run.childId ?? run.id) === "string" ? { childId: run.childId ?? run.id } : {},
9269
9325
  ...typeof result.diagnostic === "string" && result.diagnostic !== "" ? { diagnostic: result.diagnostic } : {}
9270
9326
  };
9271
9327
  } finally {
@@ -16124,14 +16180,29 @@ const HOST_SERVICES = [
16124
16180
  * - ⇒ 双档是**唯一不把本机宿主堵死的写法**(两档在真 semver 下均 PASS)。
16125
16181
  * 档上界取 `<0.2.0` / `<0.3.0`(即 `^0.2.0-rc.1` 的 caret 上界):第二档同时覆盖
16126
16182
  * `0.2.0` 正式版与后续 `0.2.0-rc.N`。
16183
+ *
16184
+ * 🆕 **第三档 `^0.2.1-rc.1`(v1.59.3 适配,2026-10-17)** —— 为什么非加不可:
16185
+ * - npm 的 `^0.2.0-rc.1` 对**预发布**只放行**同一 `major.minor.patch`** 的 prerelease
16186
+ * ⇒ **`0.2.1-rc.1` 不满足它**(patch 位不同)⇒ 宿主门会**整包拒绝安装**(D98 同族)。
16187
+ * - 而第二档的 `ceiling: '0.3.0'` 本来就"包含" 0.2.1 —— 那是**我们自己的手写比较器**的语义;
16188
+ * 两个判据(真 semver 门 vs 手写区间)在这里**给出相反答案**,故必须把第三档显式写出来,
16189
+ * 让**派生串**({@link REQUIRED_HOST_RANGE})里真的出现 `^0.2.1-rc.1`。
16190
+ * ⚠️ **加档不是收窄**:前两档原样保留(0.1.7 / 0.2.0 两代仍被声明支持)。
16127
16191
  */
16128
- const VERIFIED_HOST_BANDS = [{
16129
- floor: "0.1.7-rc.1",
16130
- ceiling: "0.2.0"
16131
- }, {
16132
- floor: "0.2.0-rc.1",
16133
- ceiling: "0.3.0"
16134
- }];
16192
+ const VERIFIED_HOST_BANDS = [
16193
+ {
16194
+ floor: "0.1.7-rc.1",
16195
+ ceiling: "0.2.0"
16196
+ },
16197
+ {
16198
+ floor: "0.2.0-rc.1",
16199
+ ceiling: "0.3.0"
16200
+ },
16201
+ {
16202
+ floor: "0.2.1-rc.1",
16203
+ ceiling: "0.3.0"
16204
+ }
16205
+ ];
16135
16206
  /**
16136
16207
  * 与 `package.json` 的 `peerDependencies` **逐字同串**的宿主版本范围(由 {@link VERIFIED_HOST_BANDS} 派生)。
16137
16208
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shgroup/dsh-serenity-hooks",
3
- "version": "1.59.2",
3
+ "version": "1.59.3",
4
4
  "description": "宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:14 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/cheap-worker/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫/对外输出守卫)+ 工作日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/trajectory 唤醒注册表。适配 DSH 0.1.7-rc.1 与 0.2.0-rc.1(双档)。",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -67,22 +67,22 @@
67
67
  },
68
68
  "peerDependencies": {
69
69
  "@deepseek-ai/cordis": "^4.0.4",
70
- "@deepseek-ai/dsh-acp": "^0.1.7-rc.1 || ^0.2.0-rc.1",
71
- "@deepseek-ai/dsh-agent": "^0.1.7-rc.1 || ^0.2.0-rc.1",
72
- "@deepseek-ai/dsh-agent-loop": "^0.1.7-rc.1 || ^0.2.0-rc.1",
73
- "@deepseek-ai/dsh-agent-preset-registry": "^0.1.7-rc.1 || ^0.2.0-rc.1",
74
- "@deepseek-ai/dsh-compaction": "^0.1.7-rc.1 || ^0.2.0-rc.1",
75
- "@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.1 || ^0.2.0-rc.1",
76
- "@deepseek-ai/dsh-llm": "^0.1.7-rc.1 || ^0.2.0-rc.1",
77
- "@deepseek-ai/dsh-session": "^0.1.7-rc.1 || ^0.2.0-rc.1",
78
- "@deepseek-ai/dsh-session-title": "^0.1.7-rc.1 || ^0.2.0-rc.1",
79
- "@deepseek-ai/dsh-shell": "^0.1.7-rc.1 || ^0.2.0-rc.1",
80
- "@deepseek-ai/dsh-shell-env": "^0.1.7-rc.1 || ^0.2.0-rc.1",
81
- "@deepseek-ai/dsh-skill": "^0.1.7-rc.1 || ^0.2.0-rc.1",
82
- "@deepseek-ai/dsh-system-prompt": "^0.1.7-rc.1 || ^0.2.0-rc.1",
83
- "@deepseek-ai/dsh-tools": "^0.1.7-rc.1 || ^0.2.0-rc.1",
84
- "@deepseek-ai/dsh-web": "^0.1.7-rc.1 || ^0.2.0-rc.1",
85
- "@deepseek-ai/dsh-web-fetch-http": "^0.1.7-rc.1 || ^0.2.0-rc.1",
70
+ "@deepseek-ai/dsh-acp": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
71
+ "@deepseek-ai/dsh-agent": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
72
+ "@deepseek-ai/dsh-agent-loop": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
73
+ "@deepseek-ai/dsh-agent-preset-registry": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
74
+ "@deepseek-ai/dsh-compaction": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
75
+ "@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
76
+ "@deepseek-ai/dsh-llm": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
77
+ "@deepseek-ai/dsh-session": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
78
+ "@deepseek-ai/dsh-session-title": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
79
+ "@deepseek-ai/dsh-shell": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
80
+ "@deepseek-ai/dsh-shell-env": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
81
+ "@deepseek-ai/dsh-skill": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
82
+ "@deepseek-ai/dsh-system-prompt": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
83
+ "@deepseek-ai/dsh-tools": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
84
+ "@deepseek-ai/dsh-web": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
85
+ "@deepseek-ai/dsh-web-fetch-http": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
86
86
  "@deepseek-ai/schemastery": "^3.18.4",
87
87
  "cordis": "^4.0.0-rc.7"
88
88
  },