@deepseek-ai/dsh-headless 0.2.1-alpha.1 → 0.2.1-alpha.2

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/README.i18n.yaml CHANGED
@@ -36,14 +36,14 @@
36
36
  en: be1b73a6d0ee3902
37
37
  zh: bdba099685d68b27
38
38
  /deepseek-ai-dsh-headless/understand-the-implementation/run-flow:
39
- en: 2f2adf0c346c6c1b
40
- zh: f1e988c7e597a852
39
+ en: 3729fbdc598637da
40
+ zh: 254c6961b65b9e2b
41
41
  /deepseek-ai-dsh-headless/understand-the-implementation/patch-surface-over-base:
42
42
  en: a22752c052878579
43
43
  zh: 1e42c946d8673eeb
44
44
  /deepseek-ai-dsh-headless/understand-the-implementation/exit-mapping:
45
- en: cc6c485a42d40d28
46
- zh: c57775d9319d8dfd
45
+ en: c2466d3d8a26177a
46
+ zh: b75743bfa2e7723a
47
47
  /deepseek-ai-dsh-headless/understand-the-implementation/source-map:
48
48
  en: d82278600e0efdbd
49
49
  zh: 0f546bdba164ef25
package/README.md CHANGED
@@ -77,7 +77,7 @@ The runner is a direct driver over the core API carrier: it resolves the Agent i
77
77
 
78
78
  ### Run flow
79
79
 
80
- The runner awaits the complete application (`ctx.get('loader')?.await()`) so the composed tools and adapters are not half-mounted, reads the shared [`agentDefaultModel`](../../core/agent-default-model/README.md) selection, resolves the task from config or stdin, then resolves the Agent identity: a fresh `session-<uuid>` by default, or the persisted Session `--session-id` names, which it adopts through [`sessionQuery`](../../session-query/session-query/README.md) and refuses when no log exists. It submits the task as an ordinary user message. Without `--json` it streams that Agent's non-empty reasoning deltas to stderr; with `--json` it projects the run instead. It waits for quiescence, then flushes the Session and folds the owned interval (`firstSeq` onward) into the last non-empty `assistant/message` text and final `turn/end` reason. It writes the final text to stdout (or the `final` event) and requests exit.
80
+ The runner awaits the complete application (`ctx.get('loader')?.await()`) so the composed tools and adapters are not half-mounted, reads the shared [`agentDefaultModel`](../../core/agent-default-model/README.md) selection, resolves the task from config or stdin, then resolves the Agent identity: a fresh `session-<uuid>` by default, or the persisted Session `--session-id` names, which it adopts through [`sessionQuery`](../../session-query/session-query/README.md) and refuses when no log exists. It submits the task as an ordinary user message. Without `--json` it streams that Agent's non-empty reasoning deltas to stderr; with `--json` it projects the run instead. It waits for child work and rechecks that the parent remains idle with an unchanged Session sequence before finishing, so settlement notices can drive a final parent answer. Idle children with parked inbox messages do not delay completion; process shutdown discards their unclaimed messages. It then flushes the Session and folds the owned interval (`firstSeq` onward) into the last non-empty `assistant/message` text and final `turn/end` reason. It writes the final text to stdout (or the `final` event) and requests exit.
81
81
 
82
82
  ### Patch surface over base
83
83
 
@@ -85,7 +85,7 @@ The patch rides over `dsh-base`: it inherits the projection cache and shared PTC
85
85
 
86
86
  ### Exit mapping
87
87
 
88
- A completed final `turn/end` exits 0; any other outcome — aborted, error, or no turn in the owned interval — exits 1. An `error` reason also writes `dsh: <code>: <message>` to stderr. A direct driver failure (for example, Agent creation or an unusable `--session-id`) writes `dsh: <message>` to stderr and exits 1, and in `--json` mode also emits an `error` event.
88
+ A completed final `turn/end` exits 0; any other outcome — aborted, error, or no turn in the owned interval — exits 1. An `error` reason also writes `dsh: <code>: <message>` to stderr. A live Agent failure without a later committed `turn/end` is a direct driver failure, including a summary whose start or end cannot be persisted; an earlier completed turn cannot make that run succeed. A direct driver failure (for example, Agent creation or an unusable `--session-id`) writes `dsh: <message>` to stderr and exits 1, and in `--json` mode also emits an `error` event without a `final` event.
89
89
 
90
90
  ### Source map
91
91
 
package/README.zh.md CHANGED
@@ -77,7 +77,7 @@ runner 是核心 API 载体之上的直接驱动器:它确定 Agent 标识—
77
77
 
78
78
  ### 运行流程
79
79
 
80
- runner 等待整个应用结算(`ctx.get('loader')?.await()`),确保已组合的工具与适配器不会半挂载,读取共享的 [`agentDefaultModel`](../../core/agent-default-model/README.zh.md) 选择,从配置或 stdin 解析任务,然后确定 Agent 标识:默认是全新的 `session-<uuid>`,或是 `--session-id` 指名的持久化 Session——通过 [`sessionQuery`](../../session-query/session-query/README.zh.md) 沿用,日志不存在时拒绝。它把任务作为普通用户消息提交。不带 `--json` 时,它把该 Agent 的非空推理增量流式写入 stderr;带 `--json` 时改为投影本次运行。它等待完全停稳,然后对会话执行 flush,并把所属区间(从 `firstSeq` 起)折叠为最后一条非空 `assistant/message` 文本与最终 `turn/end` 原因。最后,它把最终文本写入 stdout(或 `final` 事件)并请求退出。
80
+ runner 等待整个应用结算(`ctx.get('loader')?.await()`),确保已组合的工具与适配器不会半挂载,读取共享的 [`agentDefaultModel`](../../core/agent-default-model/README.zh.md) 选择,从配置或 stdin 解析任务,然后确定 Agent 标识:默认是全新的 `session-<uuid>`,或是 `--session-id` 指名的持久化 Session——通过 [`sessionQuery`](../../session-query/session-query/README.zh.md) 沿用,日志不存在时拒绝。它把任务作为普通用户消息提交。不带 `--json` 时,它把该 Agent 的非空推理增量流式写入 stderr;带 `--json` 时改为投影本次运行。它等待子级工作,并在结束前复核父级仍空闲且 Session 序号未变,让结算通知可以驱动父级生成最终答案。收件箱消息处于停放状态的空闲子级不会延迟完成;进程关闭时丢弃这些未领取消息。随后它对会话执行 flush,并把所属区间(从 `firstSeq` 起)折叠为最后一条非空 `assistant/message` 文本与最终 `turn/end` 原因。最后,它把最终文本写入 stdout(或 `final` 事件)并请求退出。
81
81
 
82
82
  ### 基于 base 的 patch 内容
83
83
 
@@ -85,7 +85,7 @@ patch 叠加在 `dsh-base` 之上:继承投影缓存与共享 PTC 运行时,
85
85
 
86
86
  ### 退出映射
87
87
 
88
- 最终 `turn/end` 完成时退出码为 0;任何其他结果——aborted、error,或所属区间内没有轮次——退出码为 1。结束原因为 `error` 时还会向 stderr 写入 `dsh: <code>: <message>`。直接驱动器失败(例如 Agent 创建失败或不可用的 `--session-id`)向 stderr 写入 `dsh: <message>` 并退出 1,且在 `--json` 模式下额外发出一个 `error` 事件。
88
+ 最终 `turn/end` 完成时退出码为 0;任何其他结果——aborted、error,或所属区间内没有轮次——退出码为 1。结束原因为 `error` 时还会向 stderr 写入 `dsh: <code>: <message>`。若实时 Agent 失败后没有提交更晚的 `turn/end`,则视为直接驱动器失败,包括汇总轮次的开始或结束无法持久化;更早的已完成轮次不能使该次运行成功。直接驱动器失败(例如 Agent 创建失败或不可用的 `--session-id`)向 stderr 写入 `dsh: <message>` 并退出 1,且在 `--json` 模式下额外发出一个 `error` 事件,不发出 `final` 事件。
89
89
 
90
90
  ### 源码地图
91
91
 
package/cordis.patch.yml CHANGED
@@ -8,7 +8,6 @@
8
8
 
9
9
  - id: system-prompt
10
10
  config:
11
- personaSuffix: Your working directory is {{cwd}}.
12
11
  personaPrefix: >-
13
12
  You are a coding agent powered by the {{model}} model.
14
13
 
package/lib/index.js CHANGED
@@ -286,6 +286,7 @@ function fail(io, error, json) {
286
286
  }
287
287
  /**
288
288
  * Run one task through one Agent and request process exit.
289
+ * Live Agent failures require a later durable terminal before a recovered run can succeed.
289
290
  * @param ctx - plugin context carrying the Agent, default model, Session, and launcher IO services.
290
291
  * @param config - task, optional exact Session identity, and output mode.
291
292
  * @param io - process-facing effects.
@@ -324,6 +325,16 @@ async function run(ctx, config, io) {
324
325
  const firstSeq = agent.session.seq;
325
326
  const projection = config.json === true ? projectJsonRun(ctx, agent, io.stdout, { cwd }) : void 0;
326
327
  const stopReasoning = projection === void 0 ? streamReasoning(ctx, agent, io.stderr) : void 0;
328
+ let failure;
329
+ const stopErrors = ctx.on("agent/error", ({ agent: subject, error }) => {
330
+ if (subject === agent) failure = {
331
+ error,
332
+ atOffset: agent.session.seq
333
+ };
334
+ });
335
+ const stopTerminals = ctx.on("session/event", (session, event) => {
336
+ if (session === agent.session && event.type === "turn/end" && failure !== void 0 && event.seq >= failure.atOffset) failure = void 0;
337
+ });
327
338
  try {
328
339
  try {
329
340
  agent.followup(createUserMessage({
@@ -333,17 +344,25 @@ async function run(ctx, config, io) {
333
344
  }],
334
345
  source: { kind: "user" }
335
346
  }));
336
- await agent.whenIdle();
347
+ const subagents = ctx.get("subagents");
348
+ while (true) {
349
+ await agent.whenIdle();
350
+ const idleSeq = agent.session.seq;
351
+ if (!await subagents?.waitForChildren(agent) && agent.status === "idle" && agent.session.seq === idleSeq) break;
352
+ }
337
353
  } finally {
338
354
  stopReasoning?.();
339
355
  }
340
356
  await sessions.flush(agent.session);
357
+ if (failure !== void 0) throw failure.error;
341
358
  const outcome = summarize(agent.session, firstSeq);
342
359
  if (projection === void 0) io.stdout.write(outcome.text + "\n");
343
360
  else projection.finish(outcome.text);
344
361
  if (outcome.reason?.kind === "error") io.stderr.write(`dsh: ${outcome.reason.error.code}: ${outcome.reason.error.message}\n`);
345
362
  io.exit(outcome.reason?.kind === "completed" ? 0 : 1);
346
363
  } finally {
364
+ stopErrors();
365
+ stopTerminals();
347
366
  projection?.dispose();
348
367
  }
349
368
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-headless",
3
3
  "description": "The dsh one-shot bundle: a direct core Agent/Session runner over dsh-base with no Host, HTTP, or browser layer",
4
- "version": "0.2.1-alpha.1",
4
+ "version": "0.2.1-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -40,32 +40,39 @@
40
40
  }
41
41
  },
42
42
  "dependencies": {
43
- "commander": "^15.0.0",
44
- "@deepseek-ai/dsh-cmdline": "0.2.1-alpha.1",
45
- "@deepseek-ai/dsh-brand": "0.2.1-alpha.1",
46
- "@deepseek-ai/dsh-util-values": "0.2.1-alpha.1",
47
- "@deepseek-ai/schemastery": "~3.18.5-alpha.1"
43
+ "@deepseek-ai/dsh-brand": "0.2.1-alpha.2",
44
+ "@deepseek-ai/dsh-cmdline": "0.2.1-alpha.2",
45
+ "@deepseek-ai/dsh-util-values": "0.2.1-alpha.2",
46
+ "@deepseek-ai/schemastery": "~3.18.5-alpha.1",
47
+ "commander": "^15.0.0"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "@deepseek-ai/cordis": "~4.0.5-alpha.1",
51
51
  "@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.1",
52
- "@deepseek-ai/dsh-agent": "0.2.1-alpha.1",
53
- "@deepseek-ai/dsh-agent-default-model": "0.2.1-alpha.1",
54
- "@deepseek-ai/dsh-llm": "0.2.1-alpha.1",
55
- "@deepseek-ai/dsh-session": "0.2.1-alpha.1",
56
- "@deepseek-ai/dsh-session-query": "0.2.1-alpha.1",
57
- "@deepseek-ai/dsh-fs": "0.2.1-alpha.1"
52
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.2",
53
+ "@deepseek-ai/dsh-agent-default-model": "0.2.1-alpha.2",
54
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
55
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.2",
56
+ "@deepseek-ai/dsh-session-query": "0.2.1-alpha.2",
57
+ "@deepseek-ai/dsh-fs": "0.2.1-alpha.2",
58
+ "@deepseek-ai/dsh-subagent": "0.2.1-alpha.2"
58
59
  },
59
60
  "devDependencies": {
60
- "@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.1",
61
61
  "@deepseek-ai/cordis": "~4.0.5-alpha.1",
62
- "@deepseek-ai/dsh-agent-default-model": "0.2.1-alpha.1",
63
- "@deepseek-ai/dsh-agent-loop": "0.2.1-alpha.1",
64
- "@deepseek-ai/dsh-agent": "0.2.1-alpha.1",
65
- "@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-alpha.1",
66
- "@deepseek-ai/dsh-llm": "0.2.1-alpha.1",
67
- "@deepseek-ai/dsh-session-query": "0.2.1-alpha.1",
68
- "@deepseek-ai/dsh-fs": "0.2.1-alpha.1",
69
- "@deepseek-ai/dsh-session": "0.2.1-alpha.1"
62
+ "@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.1",
63
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.2",
64
+ "@deepseek-ai/dsh-agent-default-model": "0.2.1-alpha.2",
65
+ "@deepseek-ai/dsh-agent-loop": "0.2.1-alpha.2",
66
+ "@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-alpha.2",
67
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
68
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.2",
69
+ "@deepseek-ai/dsh-session-query": "0.2.1-alpha.2",
70
+ "@deepseek-ai/dsh-fs": "0.2.1-alpha.2",
71
+ "@deepseek-ai/dsh-subagent": "0.2.1-alpha.2"
72
+ },
73
+ "peerDependenciesMeta": {
74
+ "@deepseek-ai/dsh-subagent": {
75
+ "optional": true
76
+ }
70
77
  }
71
78
  }