@deepseek-ai/dsh-subagent-dsh-sdk 0.2.0-rc.2 → 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 +16 -16
- package/README.md +6 -9
- package/README.zh.md +6 -9
- package/lib/index.js +33 -19
- package/lib/types/index.d.ts +2 -11
- package/lib/types/run.d.ts +3 -5
- package/package.json +30 -30
package/README.i18n.yaml
CHANGED
|
@@ -18,17 +18,17 @@
|
|
|
18
18
|
en: d6eb16d8fc690671
|
|
19
19
|
zh: 5865ee3bed0b36ca
|
|
20
20
|
/deepseek-ai-dsh-subagent-dsh-sdk/use-this-package/when-to-choose-it:
|
|
21
|
-
en:
|
|
22
|
-
zh:
|
|
21
|
+
en: 83a84f1d42a071da
|
|
22
|
+
zh: 0dce8e7ea861f8c2
|
|
23
23
|
/deepseek-ai-dsh-subagent-dsh-sdk/use-this-package/configuration:
|
|
24
|
-
en:
|
|
25
|
-
zh:
|
|
24
|
+
en: 67cf17bbc985cad7
|
|
25
|
+
zh: ea432ae524f4ade9
|
|
26
26
|
/deepseek-ai-dsh-subagent-dsh-sdk/use-this-package/what-you-get:
|
|
27
27
|
en: b9ccfa85b40b07eb
|
|
28
28
|
zh: 4f84e7327b4ff188
|
|
29
29
|
/deepseek-ai-dsh-subagent-dsh-sdk/use-this-package/failure-and-recovery:
|
|
30
|
-
en:
|
|
31
|
-
zh:
|
|
30
|
+
en: 9e3838df9eba09bb
|
|
31
|
+
zh: fbd00b9d72e41adc
|
|
32
32
|
/deepseek-ai-dsh-subagent-dsh-sdk/understand-the-implementation:
|
|
33
33
|
en: 00d076edd7fee716
|
|
34
34
|
zh: 7aea818c13fe3cc1
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
en: 1bed6c1577997df6
|
|
40
40
|
zh: 8c99f132377f6ca2
|
|
41
41
|
/deepseek-ai-dsh-subagent-dsh-sdk/understand-the-implementation/run-flow:
|
|
42
|
-
en:
|
|
43
|
-
zh:
|
|
42
|
+
en: 6c50e4e8dc5e0698
|
|
43
|
+
zh: 9d0011e28341bbde
|
|
44
44
|
/deepseek-ai-dsh-subagent-dsh-sdk/understand-the-implementation/stop-reason-mapping:
|
|
45
45
|
en: e040a57202916f91
|
|
46
46
|
zh: 196bf38f0f0db310
|
|
@@ -69,17 +69,17 @@
|
|
|
69
69
|
en: 75d061c2151624a7
|
|
70
70
|
zh: 71e58e020b60ff90
|
|
71
71
|
/deepseek-ai-dsh-subagent-dsh-sdk/model-experience/parent-tool-result-indirectly/what-the-model-sees:
|
|
72
|
-
en:
|
|
73
|
-
zh:
|
|
72
|
+
en: 5e4e3efe7517f782
|
|
73
|
+
zh: 0465e164583f6bc3
|
|
74
74
|
/deepseek-ai-dsh-subagent-dsh-sdk/model-experience/parent-tool-result-indirectly/token-effect:
|
|
75
|
-
en:
|
|
76
|
-
zh:
|
|
75
|
+
en: 4fae54e2ff0c4874
|
|
76
|
+
zh: 1574bfe874f66a1f
|
|
77
77
|
/deepseek-ai-dsh-subagent-dsh-sdk/model-experience/parent-tool-result-indirectly/kv-cache-effect:
|
|
78
78
|
en: f5d5f97a153f7c70
|
|
79
79
|
zh: 3d6bc05b9eadfbc2
|
|
80
80
|
/deepseek-ai-dsh-subagent-dsh-sdk/known-limitations-and-deferred-work:
|
|
81
|
-
en:
|
|
82
|
-
zh:
|
|
81
|
+
en: 9158e90d1a521c05
|
|
82
|
+
zh: 246ed0c694ead7ac
|
|
83
83
|
/deepseek-ai-dsh-subagent-dsh-sdk/known-limitations-and-deferred-work/dev-note:
|
|
84
|
-
en:
|
|
85
|
-
zh:
|
|
84
|
+
en: 04a404ccea615ef3
|
|
85
|
+
zh: df2d9d901d75f024
|
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ Mount this provider when a delegation should run as a complete Harness runtime i
|
|
|
31
31
|
|
|
32
32
|
Choose this backend when the child must be a full harness peer — its own composition, session persistence, model route, and tools — rather than an agent that shares the parent's process. Choose an in-process backend when the child must share the parent's composition or honor parent-enforced non-route capabilities: this provider accepts agent route options but rejects structured output, depth caps, tool filters, and personas rather than silently omitting them.
|
|
33
33
|
|
|
34
|
-
The provider advertises `agentOptions: true`, with `outputSchema`/`depthLimit`/`toolFilter`/`persona` false, and `inheritsParentContext: false`. Its immutable `agentRouteDefaults` publish the configured provider/model baseline to `dsh-tool-subagent` before model overrides and exact-route preflight;
|
|
34
|
+
The provider advertises `agentOptions: true`, with `outputSchema`/`depthLimit`/`toolFilter`/`persona` false, and `inheritsParentContext: false`. Its immutable `agentRouteDefaults` publish the configured provider/model baseline to `dsh-tool-subagent` before model overrides and exact-route preflight; the backend applies the same configuration defaults during activation startup, including `maxTokens`. Agent route values cross the SDK wire as an explicit whitelist; the child remains a fresh runtime in another process, and the child process uses the selected effective directory while its Session retains the parent origin directory. `dsh-tool-subagent` deployments over this provider set `maxDepth: 'provider-managed'` — the child harness owns its own recursion budget.
|
|
35
35
|
|
|
36
36
|
### Configuration
|
|
37
37
|
|
|
@@ -42,7 +42,6 @@ The provider advertises `agentOptions: true`, with `outputSchema`/`depthLimit`/`
|
|
|
42
42
|
| `profile` | `sdk` | Named child profile |
|
|
43
43
|
| `patches` | `[]` | Ordered per-launch profile patch files, resolved and checked at plugin load |
|
|
44
44
|
| `dshHome` | required | Absolute isolated Harness home for every nested child process |
|
|
45
|
-
| `cwd` | parent session cwd | Working-directory override for the child process and its SDK session |
|
|
46
45
|
| `provider` | `deepseek-official` | Provider route sent in the child's `initialize` |
|
|
47
46
|
| `model` | `deepseek-v4-flash` | Model sent in the child's `initialize` |
|
|
48
47
|
| `maxTokens` | adapter/provider route default | Per-request output-token cap sent in the child's `initialize` |
|
|
@@ -77,7 +76,7 @@ A successful run returns the child's final assistant text (or accumulated partia
|
|
|
77
76
|
|
|
78
77
|
### Failure and recovery
|
|
79
78
|
|
|
80
|
-
An already-aborted request fails before path resolution or spawn. A route, spawn, handshake, or pre-publication cancellation failure ordinarily rejects only after the subprocess is reaped. If initialization and cleanup both fail, the ordered safe facts preserve both failures without claiming quiescence. A child runtime that fails after publication settles through the run rather than rejecting it; partial output stays separate from the safe diagnostic. Diagnostics expose only the provider plus `initialize`, `session-run`, or `shutdown` stage and a fixed category. They never copy SDK messages, stderr, paths, task content, environment values, credentials, or protocol payloads.
|
|
79
|
+
The configured SDK runtime must implement `session/wait`; a runtime without it reports an execution failure. Update the provider and a separately configured `dshBin` runtime together. An already-aborted request fails before path resolution or spawn. A route, spawn, handshake, or pre-publication cancellation failure ordinarily rejects only after the subprocess is reaped. If initialization and cleanup both fail, the ordered safe facts preserve both failures without claiming quiescence. A child runtime that fails after publication settles through the run rather than rejecting it; partial output stays separate from the safe diagnostic. Diagnostics expose only the provider plus `initialize`, `session-run`, or `shutdown` stage and a fixed category. They never copy SDK messages, stderr, paths, task content, environment values, credentials, or protocol payloads.
|
|
81
80
|
|
|
82
81
|
-----
|
|
83
82
|
|
|
@@ -104,7 +103,7 @@ This section explains how the backend drives a child Harness runtime and where t
|
|
|
104
103
|
|
|
105
104
|
### Run flow
|
|
106
105
|
|
|
107
|
-
A start resolves the child's working directory and one process-wide SDK route before spawning. Each declared `request.agentOptions` field (`provider`, `model`, `reasoningEffort`, or `maxTokens`) overrides the matching provider-instance default; omission preserves the configured provider/model and optional cap, while reasoning effort remains absent unless the request supplies it. The provider spawns the runtime through the SDK client and completes the `initialize` handshake, including exact-model and effort validation, before it fulfills. A route, spawn, handshake, or pre-publication cancellation failure rejects only after the subprocess is reaped; a working-directory resolution failure rejects before spawning. After publication the provider
|
|
106
|
+
A start resolves the child's working directory and one process-wide SDK route before spawning. Each declared `request.agentOptions` field (`provider`, `model`, `reasoningEffort`, or `maxTokens`) overrides the matching provider-instance default; omission preserves the configured provider/model and optional cap, while reasoning effort remains absent unless the request supplies it. The provider spawns the runtime through the SDK client and completes the `initialize` handshake, including exact-model and effort validation, before it fulfills. A route, spawn, handshake, or pre-publication cancellation failure rejects only after the subprocess is reaped; a working-directory resolution failure rejects before spawning. After publication the provider subscribes to the child Session, queues its prompt, and waits through `session/wait` for managed descendants and subsequent root turns. It reads the child's answer from the ordered session events: the last complete non-empty `assistant/message` (an empty-content message that records usage is skipped), or the accumulated `text-delta` stream when no such message exists. Disposal is idempotent: it settles the result locally as `aborted`, sends a bounded protocol `shutdown` request, then escalates through stdin EOF → SIGTERM → SIGKILL to actual exit. The activation manager owns that run after acceptance; the caller's startup signal no longer cancels the child. Each activation executes once, and its receipt cancels execution and awaits cleanup.
|
|
108
107
|
|
|
109
108
|
### Stop-reason mapping
|
|
110
109
|
|
|
@@ -152,11 +151,11 @@ Independent of the parent request cache. Each SDK child can reuse only prefixes
|
|
|
152
151
|
|
|
153
152
|
#### What the model sees
|
|
154
153
|
|
|
155
|
-
Through `dsh-tool-subagent`, the parent receives
|
|
154
|
+
Through `dsh-tool-subagent`, the parent model first receives a child id, then a completion notice containing final or partial assistant text, the stop reason, and safe diagnostic. The parent Session independently retains the external task identity and complete terminal result. Intermediate messages and tool traffic do not enter the parent Session.
|
|
156
155
|
|
|
157
156
|
#### Token effect
|
|
158
157
|
|
|
159
|
-
Parent input grows
|
|
158
|
+
Parent input grows by the start acknowledgement and completion notice, whose size depends on the result data and persists until compaction. This provider adds no parent schema by itself.
|
|
160
159
|
|
|
161
160
|
#### KV Cache effect
|
|
162
161
|
|
|
@@ -171,7 +170,7 @@ These limits define when this backend is a poor fit or needs special operational
|
|
|
171
170
|
|
|
172
171
|
- **A fresh runtime process per run** — no pooling; a harness runtime boots a full plugin tree, so per-run spawn cost is higher than the ACP backend's typical child.
|
|
173
172
|
- **No non-route start-time capabilities** — the parent can select the child agent route but cannot enforce `outputSchema`, depth, tool filters, or persona inside the child process; configure the selected child profile and its ordered patches instead.
|
|
174
|
-
- **The child's transcript stays in the child's own session root** — the parent log
|
|
173
|
+
- **The child's transcript stays in the child's own session root** — the parent log retains the external task identity and full result, while the streamed `session.event` channel is consumed for output extraction rather than transcript replication.
|
|
175
174
|
- **Local child processes only** — the resolved working directory is a local path; a remote runtime would need its own backend.
|
|
176
175
|
|
|
177
176
|
<a id="dev-note"></a>
|
|
@@ -186,5 +185,3 @@ This Dev Note is working context for maintainers: open questions and undecided d
|
|
|
186
185
|
- **Remote runtimes** — a remote runtime would need its own backend and workspace mapping.
|
|
187
186
|
|
|
188
187
|
</details>
|
|
189
|
-
|
|
190
|
-
**Runtime invariant:** No companion is published. Run lifecycle pairing is owned and checked by the subagent seam's invariant; this backend's own state lives in the child process beyond this context's event streams.
|
package/README.zh.md
CHANGED
|
@@ -31,7 +31,7 @@ kind: "package-reference"
|
|
|
31
31
|
|
|
32
32
|
当子进程必须是完整的 harness 对等体——拥有自己的组合、会话持久化、模型路由与工具——而不是共享父进程的 agent 时,选择此后端。当子进程必须共享父级组合或遵守父级强制的非路由能力时,请选择进程内后端:本提供方接受 agent 路由选项,但会拒绝结构化输出、深度上限、工具过滤或 persona,而不是静默省略。
|
|
33
33
|
|
|
34
|
-
提供方声明 `agentOptions: true`,同时保持 `outputSchema`/`depthLimit`/`toolFilter`/`persona` 为 false,并且 `inheritsParentContext: false`。不可变的 `agentRouteDefaults` 会在模型覆盖与确切路由预检前,把配置的 provider/model 基线公开给 `dsh-tool-subagent
|
|
34
|
+
提供方声明 `agentOptions: true`,同时保持 `outputSchema`/`depthLimit`/`toolFilter`/`persona` 为 false,并且 `inheritsParentContext: false`。不可变的 `agentRouteDefaults` 会在模型覆盖与确切路由预检前,把配置的 provider/model 基线公开给 `dsh-tool-subagent`;后端在 activation 启动时应用同一份配置默认值,包括 `maxTokens`。agent 路由值通过显式白名单跨越 SDK 协议;子进程仍是另一进程里的全新运行时,子进程使用所选有效目录,而其 Session 保留父级起始目录。基于本提供方的 `dsh-tool-subagent` 部署应设置 `maxDepth: 'provider-managed'`——子 harness 拥有自己的递归预算。
|
|
35
35
|
|
|
36
36
|
### 配置
|
|
37
37
|
|
|
@@ -42,7 +42,6 @@ kind: "package-reference"
|
|
|
42
42
|
| `profile` | `sdk` | 具名子 profile |
|
|
43
43
|
| `patches` | `[]` | 每次启动的有序 profile patch 文件,在插件加载时解析并校验 |
|
|
44
44
|
| `dshHome` | 必填 | 每个嵌套子进程的绝对隔离 Harness home |
|
|
45
|
-
| `cwd` | 父会话 cwd | 子进程及其 SDK 会话的工作目录覆盖值 |
|
|
46
45
|
| `provider` | `deepseek-official` | 写入子进程 `initialize` 的提供方路由 |
|
|
47
46
|
| `model` | `deepseek-v4-flash` | 写入子进程 `initialize` 的模型 |
|
|
48
47
|
| `maxTokens` | 适配器/提供方路由默认值 | 写入子进程 `initialize` 的单次请求输出 token 上限 |
|
|
@@ -77,7 +76,7 @@ kind: "package-reference"
|
|
|
77
76
|
|
|
78
77
|
### 失败与恢复
|
|
79
78
|
|
|
80
|
-
|
|
79
|
+
配置的 SDK 运行时必须实现 `session/wait`;不支持该请求的运行时会报告执行失败。请一并更新提供方与单独配置的 `dshBin` 运行时。已取消的请求会在路径解析或 spawn 之前失败。路由、spawn、握手或发布前取消失败通常只在子进程被回收后拒绝;如果初始化与清理均失败,有序安全事实会保留两项失败,而不会宣称已完全停稳。子运行时在发布后失败时会通过运行本身结算,而不是拒绝;部分输出与安全诊断保持分离。诊断只公开提供方、`initialize`、`session-run` 或 `shutdown` 阶段,以及固定类别。SDK 消息、stderr、路径、任务内容、环境值、凭据和协议载荷绝不会复制到诊断中。
|
|
81
80
|
|
|
82
81
|
-----
|
|
83
82
|
|
|
@@ -104,7 +103,7 @@ kind: "package-reference"
|
|
|
104
103
|
|
|
105
104
|
### 运行流程
|
|
106
105
|
|
|
107
|
-
一次启动会在 spawn 前解析子进程工作目录与一条进程级 SDK 路由。`request.agentOptions` 中每个已声明字段(`provider`、`model`、`reasoningEffort` 或 `maxTokens`)都会覆盖对应的提供方实例默认值;省略时保留已配置的提供方/模型与可选上限,而推理强度只有在请求提供时才会出现。随后,提供方通过 SDK 客户端 spawn 运行时,并在履行前完成 `initialize` 握手,其中包括确切模型与推理强度校验。路由、spawn、握手或发布前取消失败时,只会在子进程被回收后拒绝;工作目录解析失败则会在尚未 spawn
|
|
106
|
+
一次启动会在 spawn 前解析子进程工作目录与一条进程级 SDK 路由。`request.agentOptions` 中每个已声明字段(`provider`、`model`、`reasoningEffort` 或 `maxTokens`)都会覆盖对应的提供方实例默认值;省略时保留已配置的提供方/模型与可选上限,而推理强度只有在请求提供时才会出现。随后,提供方通过 SDK 客户端 spawn 运行时,并在履行前完成 `initialize` 握手,其中包括确切模型与推理强度校验。路由、spawn、握手或发布前取消失败时,只会在子进程被回收后拒绝;工作目录解析失败则会在尚未 spawn 任何内容时拒绝。发布后,提供方先订阅子会话,再排入提示词,并通过 `session/wait` 等待受管理后代与根 Agent 后续轮次。它从有序会话事件中读取答案:最后一条完整且非空的 `assistant/message`(记录 usage 的空内容消息会被跳过);若没有这类消息,则取累积的 `text-delta` 流。dispose 是幂等的:先在本地把结果确定为 `aborted`,发出有界的协议 `shutdown` 请求,再经 stdin EOF → SIGTERM → SIGKILL 升级到实际退出。任务接受后由 activation 管理器拥有该运行;此后调用方的启动信号不再取消子任务。每个 activation 只执行一次,其凭据用于取消执行并等待清理。
|
|
108
107
|
|
|
109
108
|
### 停止原因映射
|
|
110
109
|
|
|
@@ -152,11 +151,11 @@ kind: "package-reference"
|
|
|
152
151
|
|
|
153
152
|
#### 模型看到什么
|
|
154
153
|
|
|
155
|
-
|
|
154
|
+
通过 `dsh-tool-subagent`,父模型先收到 child id,随后收到含最终或部分 assistant 文本、停止原因与安全诊断的完成通知。父会话独立保存外部任务身份和完整终态结果。中间消息与工具通信不进入父会话。
|
|
156
155
|
|
|
157
156
|
#### Token 影响
|
|
158
157
|
|
|
159
|
-
|
|
158
|
+
父级输入增加启动确认与完成通知,内容大小取决于数据,并保留到压缩(compaction)为止。本提供方自身不会向父级添加任何 schema。
|
|
160
159
|
|
|
161
160
|
#### KV Cache 影响
|
|
162
161
|
|
|
@@ -171,7 +170,7 @@ kind: "package-reference"
|
|
|
171
170
|
|
|
172
171
|
- **每次运行都使用全新的运行时进程**——不使用进程池;harness 运行时需要启动完整的插件树,因此每次运行的 spawn 成本高于 ACP 后端通常使用的子进程。
|
|
173
172
|
- **不支持路由之外的启动时能力**——父级可以选择子 agent 路由,但无法在子进程内强制执行 `outputSchema`、深度限制、工具过滤或 persona;应改为配置所选子 profile 及其有序 patch。
|
|
174
|
-
-
|
|
173
|
+
- **子任务转录保留在子进程自己的会话根目录中**——父日志保留外部任务身份与完整结果;流式 `session.event` 通道用于提取输出,不用于复制子任务转录。
|
|
175
174
|
- **仅支持本地子进程**——解析出的工作目录是本地路径;远程运行时需要独立的后端。
|
|
176
175
|
|
|
177
176
|
<a id="dev-note"></a>
|
|
@@ -186,5 +185,3 @@ kind: "package-reference"
|
|
|
186
185
|
- **远程运行时**——远程运行时需要独立的后端与工作区映射。
|
|
187
186
|
|
|
188
187
|
</details>
|
|
189
|
-
|
|
190
|
-
**运行时不变式:** 不发布伴生入口。run 生命周期配对由 subagent seam 的不变式检查;本后端自身的状态位于子进程中,不在当前上下文的事件流内。
|
package/lib/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { statSync } from "node:fs";
|
|
2
2
|
import { isAbsolute, resolve } from "node:path";
|
|
3
3
|
import z from "@deepseek-ai/schemastery";
|
|
4
|
-
import { AssistantOutputFold, NO_START_CAPABILITIES, assertPositiveFinite,
|
|
4
|
+
import { AssistantOutputFold, NO_START_CAPABILITIES, assertPositiveFinite, assertUsableCwd, settleRunResult, subprocessRunHandle } from "@deepseek-ai/dsh-subagent";
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
6
6
|
import { brandString } from "@deepseek-ai/dsh-brand";
|
|
7
|
-
import { DeepSeekHarness, JsonRpcResponseError, SdkProtocolError, TransportClosedError } from "@deepseek-ai/dsh-sdk-client";
|
|
7
|
+
import { DeepSeekHarness, JsonRpcResponseError, SdkProtocolError, TransportClosedError, validatedSessionEvent } from "@deepseek-ai/dsh-sdk-client";
|
|
8
8
|
import { scrubbedParentEnv } from "@deepseek-ai/dsh-subprocess";
|
|
9
9
|
//#region lib/types/run.js
|
|
10
10
|
/**
|
|
@@ -165,7 +165,7 @@ async function startSdkRun(request, spec) {
|
|
|
165
165
|
shutdownTimeoutMs: spec.shutdownTimeoutMs,
|
|
166
166
|
disposeEofGraceMs: spec.disposeEofGraceMs,
|
|
167
167
|
disposeGraceMs: spec.disposeGraceMs,
|
|
168
|
-
cwd: spec.cwd,
|
|
168
|
+
cwd: spec.originCwd ?? spec.cwd,
|
|
169
169
|
provider: spec.provider,
|
|
170
170
|
model: spec.model,
|
|
171
171
|
...spec.reasoningEffort === void 0 ? {} : { reasoningEffort: spec.reasoningEffort },
|
|
@@ -209,9 +209,15 @@ async function startSdkRun(request, spec) {
|
|
|
209
209
|
}
|
|
210
210
|
const childSessionId = `session-${randomUUID().replaceAll("-", "")}`;
|
|
211
211
|
const fold = new AssistantOutputFold();
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
212
|
+
const subscription = harness.client.subscribe((notification) => notification.method === "session.event" && notification.params.sessionId === childSessionId);
|
|
213
|
+
let lastEnd;
|
|
214
|
+
const drainNotifications = () => {
|
|
215
|
+
let notification;
|
|
216
|
+
while ((notification = subscription.tryNext()) !== void 0) {
|
|
217
|
+
const event = validatedSessionEvent(notification.params.event);
|
|
218
|
+
fold.push(event);
|
|
219
|
+
if (event.type === "turn/end") lastEnd = event.data.reason;
|
|
220
|
+
}
|
|
215
221
|
};
|
|
216
222
|
const collectOutput = () => fold.collect() ?? [];
|
|
217
223
|
const teardown = async () => {
|
|
@@ -226,17 +232,28 @@ async function startSdkRun(request, spec) {
|
|
|
226
232
|
}
|
|
227
233
|
};
|
|
228
234
|
let diagnostic;
|
|
235
|
+
let accepted = false;
|
|
229
236
|
return subprocessRunHandle({
|
|
230
237
|
id,
|
|
231
238
|
result: settleRunResult({
|
|
232
239
|
attempt: async () => {
|
|
233
240
|
try {
|
|
234
|
-
|
|
235
|
-
|
|
241
|
+
try {
|
|
242
|
+
await Promise.race([(async () => {
|
|
243
|
+
await harness.session(childSessionId).setWorkingDirectory(spec.cwd);
|
|
244
|
+
if (flags.cancelled) return;
|
|
245
|
+
await harness.client.prompt(childSessionId, request.prompt);
|
|
246
|
+
accepted = true;
|
|
247
|
+
await harness.client.request("session/wait", { sessionId: childSessionId });
|
|
248
|
+
})(), cancelSettled]);
|
|
249
|
+
} finally {
|
|
250
|
+
if (accepted) drainNotifications();
|
|
251
|
+
}
|
|
252
|
+
if (flags.cancelled) return {
|
|
236
253
|
output: collectOutput(),
|
|
237
254
|
stopReason: "aborted"
|
|
238
255
|
};
|
|
239
|
-
const outcome = sdkChildOutcome(
|
|
256
|
+
const outcome = sdkChildOutcome(lastEnd);
|
|
240
257
|
diagnostic = outcome.diagnostic;
|
|
241
258
|
return {
|
|
242
259
|
output: collectOutput(),
|
|
@@ -245,6 +262,8 @@ async function startSdkRun(request, spec) {
|
|
|
245
262
|
} catch (error) {
|
|
246
263
|
diagnostic = failureDiagnostic(sdkFailure(error, "session-run").facts);
|
|
247
264
|
throw error;
|
|
265
|
+
} finally {
|
|
266
|
+
subscription.close();
|
|
248
267
|
}
|
|
249
268
|
},
|
|
250
269
|
collectOutput,
|
|
@@ -268,8 +287,8 @@ async function startSdkRun(request, spec) {
|
|
|
268
287
|
* session, model route, and tools — driven over stdio JSON-RPC through the
|
|
269
288
|
* TypeScript SDK client, so it shares no Cordis context. It accepts the
|
|
270
289
|
* provider/model/reasoning/maxTokens subset of `agentOptions`; other start
|
|
271
|
-
* features remain unsupported. The
|
|
272
|
-
*
|
|
290
|
+
* features remain unsupported. The child retains its parent's origin directory
|
|
291
|
+
* while starting in the directory selected by the subagent service. This plugin uses named
|
|
273
292
|
* exports only; a default would hide its loader metadata (see
|
|
274
293
|
* `docs/postmortem/0001-acp-default-export-drops-inject.md`).
|
|
275
294
|
* @module @deepseek-ai/dsh-subagent-dsh-sdk
|
|
@@ -282,7 +301,6 @@ const Config = z.object({
|
|
|
282
301
|
profile: z.string().default("sdk"),
|
|
283
302
|
patches: z.array(z.string()).default([]),
|
|
284
303
|
dshHome: z.string().required(),
|
|
285
|
-
cwd: z.string(),
|
|
286
304
|
provider: z.string().default("deepseek-official"),
|
|
287
305
|
model: z.string().default("deepseek-v4-flash"),
|
|
288
306
|
maxTokens: z.number().step(1).min(1).max(Number.MAX_SAFE_INTEGER),
|
|
@@ -339,7 +357,7 @@ var SdkSubagentProvider = class {
|
|
|
339
357
|
if (request.signal.aborted) throw new Error("subagent request was aborted before the SDK child started");
|
|
340
358
|
let cwd;
|
|
341
359
|
try {
|
|
342
|
-
cwd =
|
|
360
|
+
cwd = assertUsableCwd("subagent-dsh-sdk", "child cwd", request.cwd);
|
|
343
361
|
} catch (error) {
|
|
344
362
|
const failure = sdkConfigurationFailure(error);
|
|
345
363
|
this.ctx.logger.warn(`subagent-dsh-sdk "${this.name}": child start failed: %o`, error);
|
|
@@ -352,6 +370,7 @@ var SdkSubagentProvider = class {
|
|
|
352
370
|
patches: this.config.patches,
|
|
353
371
|
dshHome: this.config.dshHome,
|
|
354
372
|
cwd,
|
|
373
|
+
originCwd: request.parent.session.header.cwd,
|
|
355
374
|
...route,
|
|
356
375
|
env: this.config.env,
|
|
357
376
|
shutdownTimeoutMs: this.config.shutdownTimeoutMs,
|
|
@@ -375,12 +394,7 @@ function apply(ctx, config) {
|
|
|
375
394
|
patches: resolved.patches.map((path, index) => resolveConfiguredFile(`patches[${String(index)}]`, path)),
|
|
376
395
|
...resolved.dshBin === void 0 ? {} : { dshBin: resolveConfiguredFile("dshBin", resolved.dshBin) }
|
|
377
396
|
};
|
|
378
|
-
|
|
379
|
-
const validated = configuredCwd === void 0 ? launchPaths : {
|
|
380
|
-
...launchPaths,
|
|
381
|
-
cwd: configuredCwd
|
|
382
|
-
};
|
|
383
|
-
ctx.subagents.registerProvider(new SdkSubagentProvider(validated.providerName, ctx, validated));
|
|
397
|
+
ctx.subagents.registerProvider(new SdkSubagentProvider(launchPaths.providerName, ctx, launchPaths));
|
|
384
398
|
}
|
|
385
399
|
//#endregion
|
|
386
400
|
export { Config, apply, inject, name };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* session, model route, and tools — driven over stdio JSON-RPC through the
|
|
5
5
|
* TypeScript SDK client, so it shares no Cordis context. It accepts the
|
|
6
6
|
* provider/model/reasoning/maxTokens subset of `agentOptions`; other start
|
|
7
|
-
* features remain unsupported. The
|
|
8
|
-
*
|
|
7
|
+
* features remain unsupported. The child retains its parent's origin directory
|
|
8
|
+
* while starting in the directory selected by the subagent service. This plugin uses named
|
|
9
9
|
* exports only; a default would hide its loader metadata (see
|
|
10
10
|
* `docs/postmortem/0001-acp-default-export-drops-inject.md`).
|
|
11
11
|
* @module @deepseek-ai/dsh-subagent-dsh-sdk
|
|
@@ -26,15 +26,6 @@ export interface Config {
|
|
|
26
26
|
patches: string[];
|
|
27
27
|
/** Absolute isolated Harness home for every nested child process. */
|
|
28
28
|
dshHome: string;
|
|
29
|
-
/**
|
|
30
|
-
* Working directory override for the child process and its SDK session
|
|
31
|
-
* workspace. Must be non-empty; a relative path resolves against the
|
|
32
|
-
* harness launch directory at load, and the result must be an existing
|
|
33
|
-
* directory. When omitted, each child inherits its delegating parent
|
|
34
|
-
* session's cwd — and starting one from a parent session that has no cwd
|
|
35
|
-
* fails.
|
|
36
|
-
*/
|
|
37
|
-
cwd?: string;
|
|
38
29
|
/** Provider route the child runtime initializes with (default `deepseek-official`). */
|
|
39
30
|
provider: string;
|
|
40
31
|
/** Model the child runtime initializes with (default `deepseek-v4-flash`). */
|
package/lib/types/run.d.ts
CHANGED
|
@@ -23,12 +23,10 @@ export interface SdkRunSpec {
|
|
|
23
23
|
patches: string[];
|
|
24
24
|
/** Absolute isolated Harness home for the nested runtime. */
|
|
25
25
|
dshHome: string;
|
|
26
|
-
/**
|
|
27
|
-
* Absolute working directory for the child process AND the workspace cwd
|
|
28
|
-
* of its SDK session. The provider resolves it before this spec exists:
|
|
29
|
-
* config override, else the delegating parent session's workspace.
|
|
30
|
-
*/
|
|
26
|
+
/** Absolute initial working directory selected by the delegating runtime. */
|
|
31
27
|
cwd: string;
|
|
28
|
+
/** Parent origin directory recorded independently of the child's effective directory. */
|
|
29
|
+
originCwd?: string | undefined;
|
|
32
30
|
/** Provider route the child runtime initializes with. */
|
|
33
31
|
provider: string;
|
|
34
32
|
/** Model the child runtime initializes with. */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-subagent-dsh-sdk",
|
|
3
3
|
"description": "Out-of-process SDK subagent backend: drives a child DeepSeek Harness runtime subprocess over stdio JSON-RPC through the TypeScript SDK client",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.1-alpha.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -27,38 +27,38 @@
|
|
|
27
27
|
],
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@deepseek-ai/cordis": "~4.0.
|
|
31
|
-
"@deepseek-ai/dsh-
|
|
32
|
-
"@deepseek-ai/dsh-
|
|
33
|
-
"@deepseek-ai/dsh-
|
|
34
|
-
"@deepseek-ai/dsh-
|
|
35
|
-
"@deepseek-ai/dsh-subagent": "0.2.
|
|
36
|
-
"@deepseek-ai/dsh-
|
|
30
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.1",
|
|
31
|
+
"@deepseek-ai/dsh-agent": "0.2.1-alpha.2",
|
|
32
|
+
"@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
|
|
33
|
+
"@deepseek-ai/dsh-sdk-client": "0.2.1-alpha.2",
|
|
34
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.2",
|
|
35
|
+
"@deepseek-ai/dsh-subagent": "0.2.1-alpha.2",
|
|
36
|
+
"@deepseek-ai/dsh-subprocess": "0.2.1-alpha.2"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@deepseek-ai/dsh-brand": "0.2.
|
|
40
|
-
"@deepseek-ai/schemastery": "~3.18.
|
|
39
|
+
"@deepseek-ai/dsh-brand": "0.2.1-alpha.2",
|
|
40
|
+
"@deepseek-ai/schemastery": "~3.18.5-alpha.1"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@deepseek-ai/cordis": "~4.0.
|
|
44
|
-
"@deepseek-ai/cordis-plugin-loader": "~1.0.
|
|
45
|
-
"@deepseek-ai/dsh-agent": "0.2.
|
|
46
|
-
"@deepseek-ai/dsh-agent-instructions": "0.2.
|
|
47
|
-
"@deepseek-ai/dsh-app-boot": "0.2.
|
|
48
|
-
"@deepseek-ai/dsh-llm": "0.2.
|
|
49
|
-
"@deepseek-ai/dsh-llm-deepseek": "0.2.
|
|
50
|
-
"@deepseek-ai/dsh-llm-deepseek-api-key": "0.2.
|
|
51
|
-
"@deepseek-ai/dsh-
|
|
52
|
-
"@deepseek-ai/dsh-sdk-
|
|
53
|
-
"@deepseek-ai/dsh-
|
|
54
|
-
"@deepseek-ai/dsh-session
|
|
55
|
-
"@deepseek-ai/dsh-session-
|
|
56
|
-
"@deepseek-ai/dsh-session-
|
|
57
|
-
"@deepseek-ai/dsh-
|
|
58
|
-
"@deepseek-ai/dsh-
|
|
59
|
-
"@deepseek-ai/dsh-
|
|
60
|
-
"@deepseek-ai/dsh-
|
|
61
|
-
"@deepseek-ai/dsh-
|
|
62
|
-
"@deepseek-ai/dsh-
|
|
43
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.1",
|
|
44
|
+
"@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.1",
|
|
45
|
+
"@deepseek-ai/dsh-agent": "0.2.1-alpha.2",
|
|
46
|
+
"@deepseek-ai/dsh-agent-instructions": "0.2.1-alpha.2",
|
|
47
|
+
"@deepseek-ai/dsh-app-boot": "0.2.1-alpha.2",
|
|
48
|
+
"@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
|
|
49
|
+
"@deepseek-ai/dsh-llm-deepseek": "0.2.1-alpha.2",
|
|
50
|
+
"@deepseek-ai/dsh-llm-deepseek-api-key": "0.2.1-alpha.2",
|
|
51
|
+
"@deepseek-ai/dsh-loader-smoke": "0.2.1-alpha.2",
|
|
52
|
+
"@deepseek-ai/dsh-sdk-client": "0.2.1-alpha.2",
|
|
53
|
+
"@deepseek-ai/dsh-sdk-protocol": "0.2.1-alpha.2",
|
|
54
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.2",
|
|
55
|
+
"@deepseek-ai/dsh-session-checkpoint-policy": "0.2.1-alpha.2",
|
|
56
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": "0.2.1-alpha.2",
|
|
57
|
+
"@deepseek-ai/dsh-session-projection": "0.2.1-alpha.2",
|
|
58
|
+
"@deepseek-ai/dsh-skill-filesystem": "0.2.1-alpha.2",
|
|
59
|
+
"@deepseek-ai/dsh-subagent": "0.2.1-alpha.2",
|
|
60
|
+
"@deepseek-ai/dsh-subprocess": "0.2.1-alpha.2",
|
|
61
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.2",
|
|
62
|
+
"@deepseek-ai/dsh-tool-subagent": "0.2.1-alpha.2"
|
|
63
63
|
}
|
|
64
64
|
}
|