@deepseek-ai/dsh-tool-subagent 0.0.1-rc.1 → 0.0.1-rc.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 +2 -2
- package/README.md +10 -10
- package/README.zh.md +10 -10
- package/lib/index.js +45 -11
- package/lib/types/index.d.ts +4 -3
- package/package.json +22 -21
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/subagent/tool-subagent/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: cc872f3decc4c85f26bd997293c8dc4140eb221c
|
|
6
|
+
README.zh.md: f7616dc677d10c141b1be606dae36d7dc7bb23ac
|
package/README.md
CHANGED
|
@@ -8,9 +8,9 @@ The model-facing delegation tool over one configured `ctx.subagents` provider. C
|
|
|
8
8
|
|
|
9
9
|
Each plugin instance binds one `provider` to one `toolName`; the model receives no provider selector. Load another distinctly named instance to expose another transport. The tool registers only while its provider exists, avoiding sibling load-order and provider-reload dependencies. Its description follows `provider.inheritsParentContext`: fresh children require standalone prompts, while forked children already see completed parent turns.
|
|
10
10
|
|
|
11
|
-
A foreground call passes the execution signal through startup and execution, awaits `run.result`, and always awaits `run.dispose()` before returning. Only `completed` returns the canonical `{ kind: 'foreground', runId, output: JsonValue[] }`, rendered as the same final text; abort, refusal, token limit, and other failures become errored tool results
|
|
11
|
+
A foreground call passes the execution signal through startup and execution, awaits `run.result`, and always awaits `run.dispose()` before returning. Only `completed` returns the canonical `{ kind: 'foreground', runId, output: JsonValue[] }`, rendered as the same final text; abort, refusal, token limit, and other failures become errored tool results whose message appends the child's preserved partial text (the `SubagentResult.output` selection) after the stop-reason headline, so a truncated answer is never reported as success yet never silently lost. If result collection and disposal both reject, the errored result preserves both diagnostics.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
`backgroundMode` selects both the background route and the omitted `run_in_background` default. `one-shot` waits in the foreground by default; an explicit `true` registers a plain parent-owned Task and returns canonical `{ kind: 'background', taskId }`, rendered as `started background subagent task <id>`, even when the provider supports continuable children. Generic task tools own its later status, collection, cancellation, and notices. `continuable` runs in the background when the argument is omitted or `true`; an explicit `false` waits for the result in the foreground. Its background route requires a provider with the `prepareContinuable` capability, calls `ctx.subagents.startContinuable()`, and returns `{ kind: 'continuable', subagentId }`, rendered as `started subagent <childId>`. The route resolves at inbox acceptance: the child owns its own turns from there, so this call neither waits for nor collects a result. The child's transcript by that id remains the source of its detailed output, and the optional global `send_message` tool sends it more work. The continuation service delivers one settlement notice whenever the child's Activation ends, containing its outcome and any final assistant message independently of `report`. Starting continuable work does not require `send_message` to be loaded. See the [background subagent Agent Note](../../../.agents/notes/implemented/feature/2026-07-08-background-subagent-tasks.md), the [continuable subagents Agent Note](../../../.agents/notes/implemented/feature/2026-07-28-continuable-subagent-conversations.md), and the [background-first delegation Agent Note](../../../.agents/notes/implemented/feature/2026-08-11-background-first-continuable-delegation.md).
|
|
14
14
|
|
|
15
15
|
`toolFilter` changes the child's global tool layer but is not a parent-derived authority ceiling. See the [agent-scope security non-goal](../../../.agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.md#security-and-authority-are-non-goals).
|
|
16
16
|
|
|
@@ -21,7 +21,7 @@ With `run_in_background: true`, `backgroundMode` selects the route. `one-shot` r
|
|
|
21
21
|
| `provider` (required) | Provider name (`spawn`, `fork`, `acp`, ...). |
|
|
22
22
|
| `toolName` | Model-facing name, default `subagent`; distinct for every loaded instance. |
|
|
23
23
|
| `enableRunInBackground` | Exposes background mode, default `true`; disabling also rejects forced background calls. |
|
|
24
|
-
| `backgroundMode` | Background lifecycle policy, default `one-shot`. `continuable` requires the provider's `prepareContinuable` capability and returns a durable child id
|
|
24
|
+
| `backgroundMode` | Background lifecycle policy, default `one-shot`. `one-shot` defaults calls to foreground; `continuable` defaults them to background, requires the provider's `prepareContinuable` capability, and returns a durable child id without requiring the follow-up tool. |
|
|
25
25
|
| `agentOptions` | Provider-specific child `provider`, `model`, and positive `maxTokens`; the in-process provider treats explicit values as overrides of inherited parent options. |
|
|
26
26
|
| `persona` | Per-child persona; requires provider `persona` capability. |
|
|
27
27
|
| `toolFilter` | Per-child global-tool restriction; requires `toolFilter` capability. |
|
|
@@ -29,7 +29,7 @@ With `run_in_background: true`, `backgroundMode` selects the route. `one-shot` r
|
|
|
29
29
|
|
|
30
30
|
## Concurrency
|
|
31
31
|
|
|
32
|
-
Foreground and background calls are
|
|
32
|
+
Foreground and background calls are concurrency-safe: sibling delegations in one assistant message overlap under the loop's rolling pool (`maxParallelToolCalls`), and results still commit in model order. Children work in their own sessions and a run never mutates the parent session; the one-shot background form's one parent-owned write — registering a Task — is a synchronous, commutative insertion that tolerates concurrent dispatch, so overlapping background calls acquire their task ids in dispatch-race order. Coordinating sibling workspace effects belongs to the model, exactly as it already does for background and continuable children. See the [parallel subagent Agent Note](../../../.agents/notes/implemented/feature/2026-08-09-parallel-subagent-delegations.md) and the [parallel tool-call Agent Note](../../../.agents/notes/implemented/feature/2026-07-10-parallel-tool-call-execution.md).
|
|
33
33
|
|
|
34
34
|
## Model Experience
|
|
35
35
|
|
|
@@ -37,11 +37,11 @@ Foreground and background calls are exclusive. Children may share the parent's w
|
|
|
37
37
|
|
|
38
38
|
#### What the model sees
|
|
39
39
|
|
|
40
|
-
The generated default [`subagent` schema](../../../docs/tool-catalog.md#deepseek-aidsh-tool-subagent) under this instance's configured name while its provider exists. Provider context inheritance changes the tool and prompt descriptions
|
|
40
|
+
The generated default [`subagent` schema](../../../docs/tool-catalog.md#deepseek-aidsh-tool-subagent) under this instance's configured name while its provider exists. Provider context inheritance changes the tool and prompt descriptions. Enabled background mode adds `run_in_background`: continuable mode documents its `true` default, runtime settlement notice, and explicit foreground override, while one-shot mode documents its `false` default and the task id collected with `task_output` or stopped with `task_kill`. While the tool is visible in an assembly's scope, a `tool:<toolName>` system-prompt section tells the model to start independent continuable delegations together, keep working while they run, and choose foreground only when its next action depends on the result; a tool restriction removes both its schema and this guidance.
|
|
41
41
|
|
|
42
42
|
#### Token effect
|
|
43
43
|
|
|
44
|
-
Fixed schema cost per parent request; each provider instance adds one schema.
|
|
44
|
+
Fixed schema cost per parent request; each provider instance adds one schema, and each continuable instance adds one short system-prompt section.
|
|
45
45
|
|
|
46
46
|
#### KV Cache effect
|
|
47
47
|
|
|
@@ -65,11 +65,11 @@ Append-only; newly visible content follows the reusable request prefix and does
|
|
|
65
65
|
|
|
66
66
|
#### What the model sees
|
|
67
67
|
|
|
68
|
-
Start returns exactly `started subagent <childId>` in configured continuable mode, or `started background subagent task <id>` in configured one-shot mode. In one-shot mode the generic task surface provides later status, final output, cancellation responses, and notices. In continuable mode the child
|
|
68
|
+
Start returns exactly `started subagent <childId>` in configured continuable mode, or `started background subagent task <id>` in configured one-shot mode. In one-shot mode the generic task surface provides later status, final output, cancellation responses, and notices. In continuable mode this tool returns no result of its own; the child's settlement reaches the parent as a [service-owned notice](../subagent/README.md#settlement-notice), an independently loaded `send_message` tool delivers follow-ups, and the child's transcript by its id is the source of its detailed output.
|
|
69
69
|
|
|
70
70
|
#### Token effect
|
|
71
71
|
|
|
72
|
-
The acknowledgement is retained; a one-shot final output enters parent history only when collected or injected, while a continuable child's output never returns through this tool.
|
|
72
|
+
The acknowledgement is retained; a one-shot final output enters parent history only when collected or injected, while a continuable child's output never returns through this tool — its settlement notice arrives independently of any tool result.
|
|
73
73
|
|
|
74
74
|
#### KV Cache effect
|
|
75
75
|
|
|
@@ -77,6 +77,6 @@ Append-only; newly visible content follows the reusable request prefix and does
|
|
|
77
77
|
|
|
78
78
|
## Known Limitations and Deferred Work
|
|
79
79
|
|
|
80
|
-
- **Background runs expose no result through this tool** — a one-shot task's final output is collected through the generic task surface, and a continuable child's output stays in its own session, read by its subagent id.
|
|
81
|
-
- **Duplicate names across waiting instances are detected late** (`TODO(subagent-dup-toolname)`) — preventing provider-registration rollback requires a registry of intended names.
|
|
80
|
+
- **Background runs expose no result through this tool** — a one-shot task's final output is collected through the generic task surface, and a continuable child's output stays in its own session, read by its subagent id. The settlement notice states how that child ended and carries any final assistant message, but it is not this call's return value and cannot be awaited here.
|
|
81
|
+
- **Duplicate names across waiting one-shot instances are detected late** (`TODO(subagent-dup-toolname)`) — continuable instances reserve their prompt-section name during plugin application, but preventing provider-registration rollback for waiting one-shot instances requires a registry of intended names.
|
|
82
82
|
- **Child policy is fixed per instance** — another model, persona, tool filter, or depth cap requires another distinctly named tool.
|
package/README.zh.md
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
每个插件实例把一个 `provider` 绑定到一个 `toolName`;模型不会收到提供方选择器。如需公开另一种传输,请加载另一个名称不同的实例。工具只在其提供方存在时注册,从而避免对同级加载顺序和提供方重新加载的依赖。工具描述遵循 `provider.inheritsParentContext`:新建子 agent(智能体)需要独立提示词,而 fork 子 agent 已能看到父级已完成轮次。
|
|
10
10
|
|
|
11
|
-
前台调用会让执行信号贯穿启动和执行,等待 `run.result`,并且在返回前总会等待 `run.dispose()`。只有 `completed` 会返回规范值 `{ kind: 'foreground', runId, output: JsonValue[] }`,并渲染为相同的最终文本;中止、拒绝、token
|
|
11
|
+
前台调用会让执行信号贯穿启动和执行,等待 `run.result`,并且在返回前总会等待 `run.dispose()`。只有 `completed` 会返回规范值 `{ kind: 'foreground', runId, output: JsonValue[] }`,并渲染为相同的最终文本;中止、拒绝、token 上限和其他失败都会变成出错的工具结果,其消息在终止原因标题之后附带子代理保留下来的部分文本(即 `SubagentResult.output` 的选取结果)——被截断的回答不会被报告为成功,也绝不会被悄悄丢弃。如果结果收集与 dispose(资源释放)都 reject,出错的结果会保留两项诊断信息。
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
`backgroundMode` 同时选择后台路由与省略 `run_in_background` 时的默认行为。`one-shot` 默认在前台等待;显式传入 `true` 时,它会注册一个归父级所有的普通 Task,并返回规范值 `{ kind: 'background', taskId }`,渲染为 `started background subagent task <id>`,即使提供方支持可继续子 agent 也不例外。通用 Task 工具负责其后续状态、收集、取消和通知。`continuable` 在参数省略或为 `true` 时于后台运行;显式传入 `false` 时则在前台等待结果。其后台路由要求提供方具备 `prepareContinuable` 能力,调用 `ctx.subagents.startContinuable()`,并返回 `{ kind: 'continuable', subagentId }`,渲染为 `started subagent <childId>`。该路由在 inbox 接受时结算:子 agent 自此拥有自己的轮次,因此该调用既不等待也不收集结果。通过该 id 查看其 transcript(文本记录)仍是其详细输出的来源,可选的全局 `send_message` 工具则向其发送更多工作。每当子 agent 的 Activation 结束,继续执行服务都会投递一条结算通知,其中包含结束结果及可能存在的最终 assistant 消息,且这项投递不依赖 `report`。启动可继续工作不要求加载 `send_message`。见[后台 subagent Agent Note](../../../.agents/notes/implemented/feature/2026-07-08-background-subagent-tasks.md)、[可继续的 subagent Agent Note](../../../.agents/notes/implemented/feature/2026-07-28-continuable-subagent-conversations.md)和[后台优先委派 Agent Note](../../../.agents/notes/implemented/feature/2026-08-11-background-first-continuable-delegation.md)。
|
|
14
14
|
|
|
15
15
|
`toolFilter` 会改变子 agent 的全局工具层,但不是从父级派生的权限上限。见 [agent 作用域的安全非目标](../../../.agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.md#security-and-authority-are-non-goals)。
|
|
16
16
|
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
| `provider`(必填) | 提供方名称(`spawn`、`fork`、`acp` 等)。 |
|
|
22
22
|
| `toolName` | 面向模型的名称,默认 `subagent`;每个已加载实例必须不同。 |
|
|
23
23
|
| `enableRunInBackground` | 公开后台模式,默认 `true`;禁用时也会拒绝强制后台调用。 |
|
|
24
|
-
| `backgroundMode` | 后台生命周期策略,默认 `one-shot`。`continuable`
|
|
24
|
+
| `backgroundMode` | 后台生命周期策略,默认 `one-shot`。`one-shot` 默认前台调用;`continuable` 默认后台调用,要求提供方具备 `prepareContinuable` 能力,并返回持久化子 agent ID,且不要求加载后续消息工具。 |
|
|
25
25
|
| `agentOptions` | 传给具体提供方的子 agent `provider`、`model` 和正整数 `maxTokens`;进程内提供方会用显式值覆盖继承的父级选项。 |
|
|
26
26
|
| `persona` | 每个子 agent 独立的 persona;要求提供方具备 `persona` 能力。 |
|
|
27
27
|
| `toolFilter` | 每个子 agent 独立的全局工具限制;要求提供方具备 `toolFilter` 能力。 |
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
## 并发
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
前台调用和后台调用均并发安全:同一条 assistant 消息中的同级委派会在循环的滚动池(`maxParallelToolCalls`)下重叠执行,结果仍按模型顺序提交。子 agent 在各自的会话中工作,一次运行绝不变更父会话;一次性后台形态对父级拥有状态的唯一写入是注册一个 Task——这是一次同步、可交换、能容忍并发分发的插入,因此重叠的后台调用按分发竞态顺序获得各自的 task id。协调同级工作区效果由模型负责,正如模型已经对后台和可继续子 agent 所承担的那样。见 [并行 subagent Agent Note](../../../.agents/notes/implemented/feature/2026-08-09-parallel-subagent-delegations.md) 和 [并行工具调用 Agent Note](../../../.agents/notes/implemented/feature/2026-07-10-parallel-tool-call-execution.md)。
|
|
33
33
|
|
|
34
34
|
## 模型体验
|
|
35
35
|
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
|
|
38
38
|
#### 模型看到的内容
|
|
39
39
|
|
|
40
|
-
当提供方存在时,以当前实例配置的名称公开已生成的默认 [`subagent` schema](../../../docs/tool-catalog.md#deepseek-aidsh-tool-subagent)
|
|
40
|
+
当提供方存在时,以当前实例配置的名称公开已生成的默认 [`subagent` schema](../../../docs/tool-catalog.md#deepseek-aidsh-tool-subagent)。提供方是否继承上下文会改变工具描述和提示词描述。启用后台模式会添加 `run_in_background`:可继续模式会记录其默认值为 `true`、运行时结算通知与显式前台覆盖;一次性模式会记录其默认值为 `false`,以及用 `task_output` 收集或用 `task_kill` 停止的 task id。当工具在本次组装的作用域中可见时,一个 `tool:<toolName>` 系统提示词 section 会指示模型同时启动相互独立的可继续委派、在它们运行时继续工作,并且仅当下一步动作依赖结果时选择前台;工具限制会同时移除其 schema 和这段指引。
|
|
41
41
|
|
|
42
42
|
#### Token 影响
|
|
43
43
|
|
|
44
|
-
每个父级请求都会产生固定的 schema token 开销;每个提供方实例增加一个 schema。
|
|
44
|
+
每个父级请求都会产生固定的 schema token 开销;每个提供方实例增加一个 schema,每个可继续实例还会增加一个简短的系统提示词 section。
|
|
45
45
|
|
|
46
46
|
#### KV Cache 影响
|
|
47
47
|
|
|
@@ -65,11 +65,11 @@
|
|
|
65
65
|
|
|
66
66
|
#### 模型看到的内容
|
|
67
67
|
|
|
68
|
-
在配置的可继续模式下,启动时返回内容恰为 `started subagent <childId>`;在配置的一次性模式下,则返回 `started background subagent task <id>`。一次性模式下,通用 Task
|
|
68
|
+
在配置的可继续模式下,启动时返回内容恰为 `started subagent <childId>`;在配置的一次性模式下,则返回 `started background subagent task <id>`。一次性模式下,通用 Task 接口提供后续状态、最终输出、取消响应和通知。可继续模式下,本工具不返回自己的结果;子 agent 的结算会以[服务负责的通知](../subagent/README.md#settlement-notice)到达父级,独立加载的 `send_message` 工具会投递后续消息,而通过其 id 查看子 agent 的 transcript 即是其详细输出来源。
|
|
69
69
|
|
|
70
70
|
#### Token 影响
|
|
71
71
|
|
|
72
|
-
确认消息会被保留;一次性最终输出只在收集或注入时进入父级历史,而可继续子 agent
|
|
72
|
+
确认消息会被保留;一次性最终输出只在收集或注入时进入父级历史,而可继续子 agent 的输出绝不会通过本工具返回——其结算通知独立于任何工具结果到达。
|
|
73
73
|
|
|
74
74
|
#### KV Cache 影响
|
|
75
75
|
|
|
@@ -77,6 +77,6 @@
|
|
|
77
77
|
|
|
78
78
|
## 已知限制与暂缓事项
|
|
79
79
|
|
|
80
|
-
- **后台运行不通过本工具公开结果**:一次性任务的最终输出通过通用 Task 接口收集,可继续子 agent 的输出留在其自身会话中,按其 subagent id
|
|
81
|
-
-
|
|
80
|
+
- **后台运行不通过本工具公开结果**:一次性任务的最终输出通过通用 Task 接口收集,可继续子 agent 的输出留在其自身会话中,按其 subagent id 读取。结算通知会说明该子 agent 如何结束,并携带可能存在的最终 assistant 消息,但它不是本次调用的返回值,也无法在此等待。
|
|
81
|
+
- **等待中的一次性实例较晚才发现重复名称**(`TODO(subagent-dup-toolname)`):可继续实例会在插件应用期间预留提示词 section 名称,但若要阻止等待中的一次性实例回滚提供方注册,仍需要一份预期名称注册表。
|
|
82
82
|
- **每个实例的子 agent 策略固定**:其他模型、persona、工具过滤器或深度上限都需要另一个名称不同的工具。
|
package/lib/index.js
CHANGED
|
@@ -12,7 +12,13 @@ import { assertSubagentMaxDepth, settleRun } from "@deepseek-ai/dsh-subagent";
|
|
|
12
12
|
* @module @deepseek-ai/dsh-tool-subagent
|
|
13
13
|
*/
|
|
14
14
|
const name = "tool-subagent";
|
|
15
|
-
const inject = [
|
|
15
|
+
const inject = [
|
|
16
|
+
"tools",
|
|
17
|
+
"subagents",
|
|
18
|
+
"systemPrompt"
|
|
19
|
+
];
|
|
20
|
+
/** Prompt order after bounded delegation policy and before child reporting. */
|
|
21
|
+
const SUBAGENT_SECTION_ORDER = 116.5;
|
|
16
22
|
const Config = z.object({
|
|
17
23
|
provider: z.string().required(),
|
|
18
24
|
toolName: z.string().default("subagent"),
|
|
@@ -57,13 +63,24 @@ function stopReasonError(result) {
|
|
|
57
63
|
}
|
|
58
64
|
}
|
|
59
65
|
/**
|
|
66
|
+
* Append the child's preserved partial answer to a stop-reason error so a
|
|
67
|
+
* truncated or cancelled child's real text still reaches the parent model.
|
|
68
|
+
* @param error - the stop-reason headline.
|
|
69
|
+
* @param output - the child's selected output (`SubagentResult.output`).
|
|
70
|
+
* @returns the headline, extended with the partial text when any exists.
|
|
71
|
+
*/
|
|
72
|
+
function withPartialText(error, output) {
|
|
73
|
+
const text = output.filter((block) => block.type === "text").map((block) => block.text).join("");
|
|
74
|
+
return text.length === 0 ? error : `${error}\nPartial output before the run ended:\n${text}`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
60
77
|
* Collect and release one foreground run without letting disposal replace an
|
|
61
78
|
* independent result failure.
|
|
62
79
|
*/
|
|
63
80
|
async function settleForegroundRun(run) {
|
|
64
81
|
const [execution] = await Promise.allSettled([run.result.then((result) => {
|
|
65
82
|
const error = stopReasonError(result);
|
|
66
|
-
if (error !== void 0) throw new Error(error);
|
|
83
|
+
if (error !== void 0) throw new Error(withPartialText(error, result.output));
|
|
67
84
|
return {
|
|
68
85
|
kind: "foreground",
|
|
69
86
|
runId: run.id,
|
|
@@ -92,27 +109,36 @@ async function settleForegroundRun(run) {
|
|
|
92
109
|
*/
|
|
93
110
|
function providerWording(inheritsConversation) {
|
|
94
111
|
if (inheritsConversation) return {
|
|
95
|
-
description: "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn)
|
|
112
|
+
description: "Delegate a task to a subagent that inherits this conversation: a child agent seeded with all completed turns so far (it does not see the current in-flight turn). Use this when the subtask builds on this conversation's context — a follow-up analysis, a review, a continuation — without consuming this conversation's context for the work itself. You receive its result, not its intermediate steps.",
|
|
96
113
|
promptDescription: "The task for the subagent. It already sees this conversation's completed turns, so build on them freely and state only what is new."
|
|
97
114
|
};
|
|
98
115
|
return {
|
|
99
|
-
description: "Delegate a self-contained task to a subagent (a separate agent that works in its own context)
|
|
116
|
+
description: "Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. Give it a complete, standalone prompt: it does not see this conversation.",
|
|
100
117
|
promptDescription: "The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs."
|
|
101
118
|
};
|
|
102
119
|
}
|
|
120
|
+
/** Resolve the model's optional scheduling request into one execution route. */
|
|
121
|
+
function resolveDelegationRun(request, options) {
|
|
122
|
+
if (!options.backgroundEnabled) {
|
|
123
|
+
if (request.run_in_background === true) throw new Error("run_in_background is disabled for this tool instance (enableRunInBackground: false)");
|
|
124
|
+
return { runInBackground: false };
|
|
125
|
+
}
|
|
126
|
+
return { runInBackground: request.run_in_background ?? options.continuable };
|
|
127
|
+
}
|
|
103
128
|
function apply(ctx, config) {
|
|
104
129
|
if (config.maxDepth !== "provider-managed") assertSubagentMaxDepth(config.maxDepth);
|
|
105
130
|
if (config.toolFilter !== void 0 && config.toolFilter.allow === void 0 && config.toolFilter.deny === void 0) throw new Error("tool-subagent: `toolFilter` is configured but names neither `allow` nor `deny` — remove the key or fill the filter");
|
|
131
|
+
const backgroundEnabled = config.enableRunInBackground !== false;
|
|
132
|
+
const continuable = (config.backgroundMode ?? "one-shot") === "continuable";
|
|
133
|
+
const toolName = config.toolName ?? "subagent";
|
|
106
134
|
let disposeTool;
|
|
107
135
|
const mount = (provider) => {
|
|
108
136
|
if (typeof config.maxDepth === "number" && !provider.capabilities.depthLimit) throw new Error(`tool-subagent: provider "${provider.name}" cannot enforce maxDepth (no depthLimit capability) — set maxDepth: 'provider-managed' to leave the recursion budget to the provider`);
|
|
109
137
|
const wording = providerWording(provider.inheritsParentContext);
|
|
110
|
-
const backgroundEnabled = config.enableRunInBackground !== false;
|
|
111
|
-
const continuable = (config.backgroundMode ?? "one-shot") === "continuable";
|
|
112
138
|
if (continuable && provider.prepareContinuable === void 0) throw new Error(`tool-subagent: provider "${provider.name}" does not support \`backgroundMode: continuable\``);
|
|
113
139
|
disposeTool = ctx.tools.register(defineTool({
|
|
114
|
-
name:
|
|
115
|
-
description: wording.description + (backgroundEnabled ? continuable ? "
|
|
140
|
+
name: toolName,
|
|
141
|
+
description: wording.description + (backgroundEnabled ? continuable ? " This tool runs in the background by default, immediately returns a durable subagent id, and keeps the child conversation available for later turns. When that run settles, the runtime sends the parent a notice containing its outcome and any final assistant message; `send_message` starts a later turn in the same child conversation. Set `run_in_background: false` only when your next action depends on receiving the result." : " This call waits for the result by default. Set `run_in_background: true` to return a task id; collect with `task_output` and stop with `task_kill`." : " This call waits for the subagent and returns its result."),
|
|
116
142
|
parameters: {
|
|
117
143
|
description: {
|
|
118
144
|
type: "string",
|
|
@@ -126,7 +152,7 @@ function apply(ctx, config) {
|
|
|
126
152
|
},
|
|
127
153
|
...backgroundEnabled ? { run_in_background: {
|
|
128
154
|
type: "boolean",
|
|
129
|
-
description: continuable ? "
|
|
155
|
+
description: continuable ? "Whether to run in the background and return a durable subagent id immediately. Defaults to true. Set false to wait for the result when your next action depends on it." : "Whether to run as a background task and return its id. Defaults to false; collect with task_output or stop with task_kill."
|
|
130
156
|
} } : {}
|
|
131
157
|
},
|
|
132
158
|
output: {
|
|
@@ -187,6 +213,7 @@ function apply(ctx, config) {
|
|
|
187
213
|
text: value.kind === "background" ? `started background subagent task ${value.taskId}` : value.kind === "continuable" ? `started subagent ${value.subagentId}` : outputValueText(value.output)
|
|
188
214
|
}]
|
|
189
215
|
},
|
|
216
|
+
isConcurrencySafe: () => true,
|
|
190
217
|
async execute(args, exec) {
|
|
191
218
|
const parent = exec.agent;
|
|
192
219
|
if (!parent) throw new Error("subagent tool requires a calling agent (exec.agent was undefined)");
|
|
@@ -203,8 +230,10 @@ function apply(ctx, config) {
|
|
|
203
230
|
...config.toolFilter !== void 0 ? { toolFilter: config.toolFilter } : {},
|
|
204
231
|
...maxDepth !== void 0 ? { maxDepth } : {}
|
|
205
232
|
};
|
|
206
|
-
if (args
|
|
207
|
-
|
|
233
|
+
if (resolveDelegationRun(args, {
|
|
234
|
+
backgroundEnabled,
|
|
235
|
+
continuable
|
|
236
|
+
}).runInBackground) {
|
|
208
237
|
if (continuable) return {
|
|
209
238
|
kind: "continuable",
|
|
210
239
|
subagentId: (await ctx.subagents.startContinuable({
|
|
@@ -255,6 +284,11 @@ function apply(ctx, config) {
|
|
|
255
284
|
const present = ctx.subagents.getProvider(config.provider);
|
|
256
285
|
if (present !== void 0) mount(present);
|
|
257
286
|
else ctx.logger.info(`subagent provider "${config.provider}" not registered yet; the "${config.toolName ?? "subagent"}" tool will register when it appears`);
|
|
287
|
+
if (backgroundEnabled && continuable) ctx.systemPrompt.section({
|
|
288
|
+
name: `tool:${toolName}`,
|
|
289
|
+
order: SUBAGENT_SECTION_ORDER,
|
|
290
|
+
text: (context) => disposeTool === void 0 || ctx.tools.get(toolName, context.scope) === void 0 ? "" : `Use ${toolName} in the background by default. Start independent delegations together in one assistant message and continue useful work while they run. Set \`run_in_background: false\` only when your next action depends on that subagent's result. When a background run settles, the runtime sends you a notice containing its outcome and any final assistant message.`
|
|
291
|
+
});
|
|
258
292
|
}
|
|
259
293
|
//#endregion
|
|
260
294
|
export { Config, apply, inject, name };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -27,9 +27,10 @@ export interface Config {
|
|
|
27
27
|
*/
|
|
28
28
|
enableRunInBackground?: boolean;
|
|
29
29
|
/**
|
|
30
|
-
* Background execution policy (default `one-shot`). `
|
|
31
|
-
*
|
|
32
|
-
*
|
|
30
|
+
* Background execution policy (default `one-shot`). `one-shot` defaults calls
|
|
31
|
+
* to foreground; `continuable` defaults them to background, requires a provider
|
|
32
|
+
* with the `prepareContinuable` capability, and returns the durable child id.
|
|
33
|
+
* Follow-up adapters remain independently optional.
|
|
33
34
|
*/
|
|
34
35
|
backgroundMode?: 'one-shot' | 'continuable';
|
|
35
36
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-tool-subagent",
|
|
3
3
|
"description": "Model-facing subagent delegation tool over the ctx.subagents seam",
|
|
4
|
-
"version": "0.0.1-rc.
|
|
4
|
+
"version": "0.0.1-rc.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "restricted"
|
|
7
7
|
},
|
|
@@ -32,32 +32,33 @@
|
|
|
32
32
|
],
|
|
33
33
|
"license": "BSD-3-Clause",
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@deepseek-ai/dsh-agent": "^0.0.1-rc.
|
|
36
|
-
"@deepseek-ai/dsh-
|
|
37
|
-
"@deepseek-ai/dsh-
|
|
38
|
-
"@deepseek-ai/dsh-subagent": "^0.0.1-rc.
|
|
39
|
-
"@deepseek-ai/dsh-
|
|
40
|
-
"@deepseek-ai/dsh-
|
|
35
|
+
"@deepseek-ai/dsh-agent": "^0.0.1-rc.2",
|
|
36
|
+
"@deepseek-ai/dsh-llm": "^0.0.1-rc.2",
|
|
37
|
+
"@deepseek-ai/dsh-invariants": "^0.0.1-rc.2",
|
|
38
|
+
"@deepseek-ai/dsh-subagent": "^0.0.1-rc.2",
|
|
39
|
+
"@deepseek-ai/dsh-system-prompt": "^0.0.1-rc.2",
|
|
40
|
+
"@deepseek-ai/dsh-tasks": "^0.0.1-rc.2",
|
|
41
|
+
"@deepseek-ai/dsh-tools": "^0.0.1-rc.2",
|
|
41
42
|
"@deepseek-ai/cordis": "^4.0.1-rc.1"
|
|
42
43
|
},
|
|
43
44
|
"dependencies": {
|
|
44
45
|
"@deepseek-ai/schemastery": "^3.18.1-rc.1"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
|
-
"@deepseek-ai/dsh-agent": "^0.0.1-rc.
|
|
48
|
-
"@deepseek-ai/dsh-invariants": "^0.0.1-rc.
|
|
49
|
-
"@deepseek-ai/dsh-llm": "^0.0.1-rc.
|
|
48
|
+
"@deepseek-ai/dsh-agent": "^0.0.1-rc.2",
|
|
49
|
+
"@deepseek-ai/dsh-invariants": "^0.0.1-rc.2",
|
|
50
|
+
"@deepseek-ai/dsh-llm": "^0.0.1-rc.2",
|
|
51
|
+
"@deepseek-ai/dsh-session": "^0.0.1-rc.2",
|
|
50
52
|
"@deepseek-ai/cordis-plugin-loader": "^1.0.1-rc.1",
|
|
51
|
-
"@deepseek-ai/dsh-session": "^0.0.1-rc.
|
|
52
|
-
"@deepseek-ai/dsh-session-persistence": "^0.0.1-rc.
|
|
53
|
-
"@deepseek-ai/dsh-
|
|
54
|
-
"@deepseek-ai/dsh-subagent": "^0.0.1-rc.
|
|
55
|
-
"@deepseek-ai/dsh-
|
|
56
|
-
"@deepseek-ai/dsh-tasks-local": "^0.0.1-rc.
|
|
57
|
-
"@deepseek-ai/dsh-
|
|
58
|
-
"@deepseek-ai/
|
|
59
|
-
"@deepseek-ai/dsh-
|
|
60
|
-
"@deepseek-ai/dsh-tools": "^0.0.1-rc.
|
|
61
|
-
"@deepseek-ai/cordis": "^4.0.1-rc.1"
|
|
53
|
+
"@deepseek-ai/dsh-session-persistence": "^0.0.1-rc.2",
|
|
54
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": "^0.0.1-rc.2",
|
|
55
|
+
"@deepseek-ai/dsh-subagent": "^0.0.1-rc.2",
|
|
56
|
+
"@deepseek-ai/dsh-subagent-spawn": "^0.0.1-rc.2",
|
|
57
|
+
"@deepseek-ai/dsh-system-prompt": "^0.0.1-rc.2",
|
|
58
|
+
"@deepseek-ai/dsh-tasks-local": "^0.0.1-rc.2",
|
|
59
|
+
"@deepseek-ai/dsh-tool-tasks": "^0.0.1-rc.2",
|
|
60
|
+
"@deepseek-ai/cordis": "^4.0.1-rc.1",
|
|
61
|
+
"@deepseek-ai/dsh-tasks": "^0.0.1-rc.2",
|
|
62
|
+
"@deepseek-ai/dsh-tools": "^0.0.1-rc.2"
|
|
62
63
|
}
|
|
63
64
|
}
|