@argszero/cordis-plugin-subagent-wait 0.1.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.
- package/LICENSE +21 -0
- package/README.md +106 -0
- package/lib/index.d.ts +62 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +175 -0
- package/lib/index.js.map +1 -0
- package/package.json +70 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 argszero
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# cordis-plugin-subagent-wait
|
|
2
|
+
|
|
3
|
+
`wait_for_agent` for the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (`dsh`).
|
|
4
|
+
|
|
5
|
+
A thin orchestration helper for **continuable background subagents**: it blocks — under a bounded timeout —
|
|
6
|
+
until a specific continuable child is **terminal**, instead of forcing the parent to re-derive completion by
|
|
7
|
+
polling `list_agents` (whose `idle` status collapses "between turns" and "waiting on its own children").
|
|
8
|
+
|
|
9
|
+
## Why
|
|
10
|
+
|
|
11
|
+
`list_agents` reports a child's status as `running | idle | ready`. But `idle` is ambiguous:
|
|
12
|
+
|
|
13
|
+
- an `idle` child may simply be between turns;
|
|
14
|
+
- **an `idle` child may be blocked-waiting on its own grandchildren** — and is *not* terminal.
|
|
15
|
+
|
|
16
|
+
So a parent that polls `list_agents` and treats `status !== 'running'` as "done" can hang on a child that is
|
|
17
|
+
actually waiting on its own descendants. `status === 'ready'` (only in storage) is also **not** a terminal
|
|
18
|
+
result to collect — it means "resumable, not finished."
|
|
19
|
+
|
|
20
|
+
`wait_for_agent` solves this by keying on the **settlement signal**, not a status read: the harness's
|
|
21
|
+
continuation manager publishes a `subagent-settled` notice (a typed message source, `form: notice`, carrying
|
|
22
|
+
the child's `senderSessionId`) into the **parent agent's inbox** exactly when the child settles and is
|
|
23
|
+
disposed. This plugin binds to that signal (via the `agent/inbox/inserted` event) and falls back to a bounded
|
|
24
|
+
registry/status read, so a blocked-waiting child is never mistaken for terminal.
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
npm install @argszero/cordis-plugin-subagent-wait
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Mount the plugin into your `dsh` profile (it registers the `wait_for_agent` tool):
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
# cordis.yml
|
|
36
|
+
plugins:
|
|
37
|
+
"@argszero/cordis-plugin-subagent-wait": {}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
> Requires the subagent continuation runtime (`@deepseek-ai/dsh-subagent` is a peer dependency). The tool
|
|
41
|
+
> is a thin model-facing adapter over `ctx.subagents` and the live Agent registry.
|
|
42
|
+
|
|
43
|
+
> **Version pin.** The `@deepseek-ai/dsh-*` `latest` dist-tag is frozen at an old `0.0.1-rc.1`; the current
|
|
44
|
+
> harness line is published under `next` (`0.1.2-rc.1`). This plugin's peer range (`>=0.1.0`) resolves to
|
|
45
|
+
> `next` and **excludes** the stale `latest`. If you install by tag, prefer:
|
|
46
|
+
>
|
|
47
|
+
> ```sh
|
|
48
|
+
> npm install @argszero/cordis-plugin-subagent-wait @deepseek-ai/dsh-tools@next @deepseek-ai/dsh-subagent@next
|
|
49
|
+
> ```
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
After starting a **continuable** background subagent, call `wait_for_agent` to block until it settles:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
wait_for_agent agent_id="<child session id>" timeout_ms=30000
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{ "settled": true, "status": "settled", "agent_id": "<child session id>" }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
When the timeout lapses (and the child is still alive), `settled` is `false` and `status` reflects the
|
|
66
|
+
observed runtime status (`running` / `idle` / `ready`). A `false` result means "the child may still be
|
|
67
|
+
running" — not "the child failed."
|
|
68
|
+
|
|
69
|
+
### Parameters
|
|
70
|
+
|
|
71
|
+
| param | type | default | description |
|
|
72
|
+
|-------|------|---------|-------------|
|
|
73
|
+
| `agent_id` | `string` | — (required) | The durable session id of your direct continuable child. |
|
|
74
|
+
| `timeout_ms` | `number` | `30000` | Max milliseconds to block. Capped at `300000`. |
|
|
75
|
+
|
|
76
|
+
## Exported helper
|
|
77
|
+
|
|
78
|
+
The same logic is available as a parent-side helper for other plugins:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { waitForAgent } from '@argszero/cordis-plugin-subagent-wait'
|
|
82
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
83
|
+
|
|
84
|
+
const { settled, status } = await waitForAgent(ctx, parentAgent, childId, {
|
|
85
|
+
signal, // caller cancellation
|
|
86
|
+
timeoutMs: 30_000, // bounded wait (default 30s)
|
|
87
|
+
})
|
|
88
|
+
// settled: true → the child disposed (terminal)
|
|
89
|
+
// status: 'idle' → timeout, child alive but between turns (NOT terminal)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Design notes
|
|
93
|
+
|
|
94
|
+
- **Keyed on settlement, not status.** The wait binds to the `subagent-settled` notice carrying the child id,
|
|
95
|
+
and re-checks registry terminality (disposal) as a fallback. An `idle` child waiting on its own
|
|
96
|
+
grandchildren never satisfies the wait.
|
|
97
|
+
- **Timeout is mandatory.** A model-facing tool must never be left awaiting a child that never settles, so
|
|
98
|
+
the wait is always bounded.
|
|
99
|
+
- **Cooperative cancellation.** The wait observes the tool's `signal` and resolves promptly on abort.
|
|
100
|
+
- **Composes public surface only.** It widens no core interface: it consumes `agent/inbox/inserted` (a
|
|
101
|
+
registered typed event), `ctx.subagents.listChildren()`, and the live Agent registry. The core
|
|
102
|
+
`wait_for_agent` primitive, if upstream adopts one, stays a separate harness concern.
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
MIT
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A thin orchestration helper for continuable background subagents: a
|
|
3
|
+
* `wait_for_agent` model-facing tool (and a parent-side `waitForAgent`
|
|
4
|
+
* helper) that blocks — under a bounded timeout — until a specific
|
|
5
|
+
* continuable child is terminal, instead of forcing the parent to re-derive
|
|
6
|
+
* completion by polling `list_agents` (whose `idle` status collapses
|
|
7
|
+
* "between turns" and "waiting on its own children").
|
|
8
|
+
*
|
|
9
|
+
* The wait is keyed on the *settlement signal*, not a status read: the
|
|
10
|
+
* continuation manager publishes a `subagent-settled` notice
|
|
11
|
+
* (`SubagentSettledMessageSource`, `form: notice`) carrying the child's
|
|
12
|
+
* `senderSessionId` into the parent agent's inbox exactly when the child
|
|
13
|
+
* settles. `wait_for_agent` binds to that typed source kind (and falls back to
|
|
14
|
+
* a bounded registry/status read), so an `idle` child that is merely
|
|
15
|
+
* blocked-waiting on its own grandchildren is never mistaken for terminal.
|
|
16
|
+
*
|
|
17
|
+
* This composes *existing public surface* — the `agent/inbox/inserted` event,
|
|
18
|
+
* `ctx.subagents.listChildren()`, and the live Agent registry — and widens no
|
|
19
|
+
* core interface. It is the orchestration-layer package the community invited
|
|
20
|
+
* (see the subagent continuation discussion); the core `wait_for_agent`
|
|
21
|
+
* primitive, if any, stays a separate harness concern.
|
|
22
|
+
*
|
|
23
|
+
* @module @argszero/cordis-plugin-subagent-wait
|
|
24
|
+
*/
|
|
25
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
26
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
27
|
+
import type { SessionId } from '@deepseek-ai/dsh-session';
|
|
28
|
+
export declare const name = "tool-subagent-wait";
|
|
29
|
+
export declare const inject: string[];
|
|
30
|
+
/** Default maximum milliseconds the wait may block before returning the current status. */
|
|
31
|
+
export declare const DEFAULT_TIMEOUT_MS = 30000;
|
|
32
|
+
/** Per-call cap so a single tool invocation cannot block a step indefinitely. */
|
|
33
|
+
export declare const MAX_TIMEOUT_MS = 300000;
|
|
34
|
+
/** Observed terminal/status shape returned by {@link waitForAgent}. */
|
|
35
|
+
export type WaitStatus = 'settled' | 'running' | 'idle' | 'ready';
|
|
36
|
+
/** One result: whether the child became terminal, plus its observed status. */
|
|
37
|
+
export interface WaitResult {
|
|
38
|
+
readonly settled: boolean;
|
|
39
|
+
readonly status: WaitStatus;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Block until `childId` reaches agent terminality, or `timeoutMs` elapses, or
|
|
43
|
+
* `signal` aborts. Returns the terminal/observed status so the caller can
|
|
44
|
+
* distinguish "settled" from "still running at timeout."
|
|
45
|
+
*
|
|
46
|
+
* @param ctx - context carrying the live Agent registry and the parent's
|
|
47
|
+
* scope for `agent/inbox/inserted` subscription.
|
|
48
|
+
* @param parent - the exact calling agent whose inbox carries the
|
|
49
|
+
* `subagent-settled` notice.
|
|
50
|
+
* @param childId - the durable child session id to wait on.
|
|
51
|
+
* @param options - `signal` for cancellation and `timeoutMs` bound.
|
|
52
|
+
*/
|
|
53
|
+
export declare function waitForAgent(ctx: Context, parent: Agent, childId: SessionId, options?: {
|
|
54
|
+
signal?: AbortSignal;
|
|
55
|
+
timeoutMs?: number;
|
|
56
|
+
}): Promise<WaitResult>;
|
|
57
|
+
/**
|
|
58
|
+
* Register the `wait_for_agent` tool.
|
|
59
|
+
* @param ctx - context carrying the tool registry, subagent service, and live Agent registry.
|
|
60
|
+
*/
|
|
61
|
+
export declare function apply(ctx: Context): void;
|
|
62
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,KAAK,EAAe,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAGtE,eAAO,MAAM,IAAI,uBAAuB,CAAA;AACxC,eAAO,MAAM,MAAM,UAAmC,CAAA;AAEtD,2FAA2F;AAC3F,eAAO,MAAM,kBAAkB,QAAS,CAAA;AAExC,iFAAiF;AACjF,eAAO,MAAM,cAAc,SAAU,CAAA;AAErC,uEAAuE;AACvE,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAA;AAEjE,+EAA+E;AAC/E,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;CAC5B;AAcD;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,KAAK,EACb,OAAO,EAAE,SAAS,EAClB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACzD,OAAO,CAAC,UAAU,CAAC,CA+DrB;AAED;;;GAGG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAqDxC"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A thin orchestration helper for continuable background subagents: a
|
|
3
|
+
* `wait_for_agent` model-facing tool (and a parent-side `waitForAgent`
|
|
4
|
+
* helper) that blocks — under a bounded timeout — until a specific
|
|
5
|
+
* continuable child is terminal, instead of forcing the parent to re-derive
|
|
6
|
+
* completion by polling `list_agents` (whose `idle` status collapses
|
|
7
|
+
* "between turns" and "waiting on its own children").
|
|
8
|
+
*
|
|
9
|
+
* The wait is keyed on the *settlement signal*, not a status read: the
|
|
10
|
+
* continuation manager publishes a `subagent-settled` notice
|
|
11
|
+
* (`SubagentSettledMessageSource`, `form: notice`) carrying the child's
|
|
12
|
+
* `senderSessionId` into the parent agent's inbox exactly when the child
|
|
13
|
+
* settles. `wait_for_agent` binds to that typed source kind (and falls back to
|
|
14
|
+
* a bounded registry/status read), so an `idle` child that is merely
|
|
15
|
+
* blocked-waiting on its own grandchildren is never mistaken for terminal.
|
|
16
|
+
*
|
|
17
|
+
* This composes *existing public surface* — the `agent/inbox/inserted` event,
|
|
18
|
+
* `ctx.subagents.listChildren()`, and the live Agent registry — and widens no
|
|
19
|
+
* core interface. It is the orchestration-layer package the community invited
|
|
20
|
+
* (see the subagent continuation discussion); the core `wait_for_agent`
|
|
21
|
+
* primitive, if any, stays a separate harness concern.
|
|
22
|
+
*
|
|
23
|
+
* @module @argszero/cordis-plugin-subagent-wait
|
|
24
|
+
*/
|
|
25
|
+
import { brandString } from '@deepseek-ai/dsh-brand';
|
|
26
|
+
import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
27
|
+
export const name = 'tool-subagent-wait';
|
|
28
|
+
export const inject = ['tools', 'subagents', 'agents'];
|
|
29
|
+
/** Default maximum milliseconds the wait may block before returning the current status. */
|
|
30
|
+
export const DEFAULT_TIMEOUT_MS = 30_000;
|
|
31
|
+
/** Per-call cap so a single tool invocation cannot block a step indefinitely. */
|
|
32
|
+
export const MAX_TIMEOUT_MS = 300_000;
|
|
33
|
+
/** Whether one child is terminal according to the live Agent registry. */
|
|
34
|
+
function isAgentTerminal(agents, id) {
|
|
35
|
+
return agents.get(id) === undefined;
|
|
36
|
+
}
|
|
37
|
+
/** Whether an inserted inbox message is the settlement notice for `childId`. */
|
|
38
|
+
function isSettlementFor(message, childId) {
|
|
39
|
+
const source = message.source;
|
|
40
|
+
return source.kind === 'subagent-settled'
|
|
41
|
+
&& source.senderSessionId === childId;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Block until `childId` reaches agent terminality, or `timeoutMs` elapses, or
|
|
45
|
+
* `signal` aborts. Returns the terminal/observed status so the caller can
|
|
46
|
+
* distinguish "settled" from "still running at timeout."
|
|
47
|
+
*
|
|
48
|
+
* @param ctx - context carrying the live Agent registry and the parent's
|
|
49
|
+
* scope for `agent/inbox/inserted` subscription.
|
|
50
|
+
* @param parent - the exact calling agent whose inbox carries the
|
|
51
|
+
* `subagent-settled` notice.
|
|
52
|
+
* @param childId - the durable child session id to wait on.
|
|
53
|
+
* @param options - `signal` for cancellation and `timeoutMs` bound.
|
|
54
|
+
*/
|
|
55
|
+
export async function waitForAgent(ctx, parent, childId, options = {}) {
|
|
56
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
57
|
+
// A terminal child is one the registry no longer holds. This is the
|
|
58
|
+
// settlement-by-disposal path: the continuation manager disposes the
|
|
59
|
+
// AgentHandle when a continuable child settles, so its absence IS terminal.
|
|
60
|
+
if (isAgentTerminal(ctx.agents, childId)) {
|
|
61
|
+
return { settled: true, status: 'settled' };
|
|
62
|
+
}
|
|
63
|
+
const signal = options.signal;
|
|
64
|
+
return new Promise((resolve) => {
|
|
65
|
+
let done = false;
|
|
66
|
+
let disposeInbox;
|
|
67
|
+
let removeAbort;
|
|
68
|
+
let timer;
|
|
69
|
+
const finish = (settled, status) => {
|
|
70
|
+
if (done)
|
|
71
|
+
return;
|
|
72
|
+
done = true;
|
|
73
|
+
if (timer !== undefined)
|
|
74
|
+
clearTimeout(timer);
|
|
75
|
+
if (disposeInbox !== undefined)
|
|
76
|
+
disposeInbox();
|
|
77
|
+
if (removeAbort !== undefined) {
|
|
78
|
+
signal?.removeEventListener('abort', onAbort);
|
|
79
|
+
removeAbort = undefined;
|
|
80
|
+
}
|
|
81
|
+
resolve({ settled, status });
|
|
82
|
+
};
|
|
83
|
+
const onInserted = (payload) => {
|
|
84
|
+
// Scope-filtered dispatch delivers only this agent's messages, but the
|
|
85
|
+
// listener is registered on the shared ctx — filter by the exact parent.
|
|
86
|
+
if (payload.agent !== parent)
|
|
87
|
+
return;
|
|
88
|
+
if (!isSettlementFor(payload.message, childId))
|
|
89
|
+
return;
|
|
90
|
+
finish(true, 'settled');
|
|
91
|
+
};
|
|
92
|
+
const onAbort = () => finish(false, 'running');
|
|
93
|
+
// A settlement notice establishes terminality, but the notice may have
|
|
94
|
+
// already been claimed from the inbox before we subscribed. Close that
|
|
95
|
+
// window by re-checking registry terminality after subscribing.
|
|
96
|
+
disposeInbox = ctx.on('agent/inbox/inserted', onInserted);
|
|
97
|
+
if (signal !== undefined) {
|
|
98
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
99
|
+
removeAbort = () => signal.removeEventListener('abort', onAbort);
|
|
100
|
+
}
|
|
101
|
+
timer = setTimeout(() => {
|
|
102
|
+
// Timeout: re-read the live registry. If the child disposed during the
|
|
103
|
+
// wait boundary, report settled; otherwise report the observed status.
|
|
104
|
+
const agent = ctx.agents.get(childId);
|
|
105
|
+
const observed = agent === undefined
|
|
106
|
+
? 'settled'
|
|
107
|
+
: agent.status === 'running' ? 'running' : 'idle';
|
|
108
|
+
finish(agent === undefined, observed);
|
|
109
|
+
}, timeoutMs);
|
|
110
|
+
// Unref so the timer does not keep the process alive on a long idle wait.
|
|
111
|
+
timer.unref();
|
|
112
|
+
// Post-subscription re-check: the child may have settled between the
|
|
113
|
+
// initial status read and our listener registration.
|
|
114
|
+
if (isAgentTerminal(ctx.agents, childId))
|
|
115
|
+
finish(true, 'settled');
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Register the `wait_for_agent` tool.
|
|
120
|
+
* @param ctx - context carrying the tool registry, subagent service, and live Agent registry.
|
|
121
|
+
*/
|
|
122
|
+
export function apply(ctx) {
|
|
123
|
+
ctx.tools.register(defineTool({
|
|
124
|
+
name: 'wait_for_agent',
|
|
125
|
+
description: 'Block until a direct continuable background subagent reaches terminality (settles and is disposed), '
|
|
126
|
+
+ 'or until a bounded timeout elapses. Use this instead of repeatedly calling `list_agents` and '
|
|
127
|
+
+ 'interpreting `idle`: an `idle` child may simply be waiting on its own children, and is NOT terminal. '
|
|
128
|
+
+ 'This call keys on the settlement signal (the `subagent-settled` notice the manager sends to your '
|
|
129
|
+
+ 'inbox when the child finishes), so it is correct even when the child is blocked-waiting on '
|
|
130
|
+
+ 'grandchildren. Returns `true` when the child settled, `false` when the timeout lapsed (the child may '
|
|
131
|
+
+ 'still be running). A timeout is mandatory so a model is never left awaiting a child that never settles.',
|
|
132
|
+
parameters: {
|
|
133
|
+
agent_id: {
|
|
134
|
+
type: 'string',
|
|
135
|
+
required: true,
|
|
136
|
+
description: 'The agent id of your direct continuable child to wait on.',
|
|
137
|
+
},
|
|
138
|
+
timeout_ms: {
|
|
139
|
+
type: 'number',
|
|
140
|
+
description: 'Maximum milliseconds to block before returning the current status. '
|
|
141
|
+
+ `Defaults to ${DEFAULT_TIMEOUT_MS} (${DEFAULT_TIMEOUT_MS / 1000}s), capped at ${MAX_TIMEOUT_MS / 1000}s.`,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
output: {
|
|
145
|
+
schema: {
|
|
146
|
+
type: 'object',
|
|
147
|
+
additionalProperties: false,
|
|
148
|
+
properties: {
|
|
149
|
+
settled: { type: 'boolean', required: true },
|
|
150
|
+
status: { type: 'string', required: true, enum: ['settled', 'running', 'idle', 'ready'] },
|
|
151
|
+
agent_id: { type: 'string', required: true },
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
render: (args, value) => [{
|
|
155
|
+
type: 'text',
|
|
156
|
+
text: value.settled
|
|
157
|
+
? `agent ${args.agent_id} settled`
|
|
158
|
+
: `agent ${args.agent_id} is ${value.status} after waiting (timeout)`,
|
|
159
|
+
}],
|
|
160
|
+
},
|
|
161
|
+
async execute(args, exec) {
|
|
162
|
+
const parent = exec.agent;
|
|
163
|
+
if (!parent) {
|
|
164
|
+
throw new Error('wait_for_agent requires a calling agent (exec.agent was undefined)');
|
|
165
|
+
}
|
|
166
|
+
const timeoutMs = args.timeout_ms === undefined ? DEFAULT_TIMEOUT_MS : Math.min(args.timeout_ms, MAX_TIMEOUT_MS);
|
|
167
|
+
const result = await waitForAgent(ctx, parent, brandString(args.agent_id), {
|
|
168
|
+
signal: exec.signal,
|
|
169
|
+
timeoutMs,
|
|
170
|
+
});
|
|
171
|
+
return { settled: result.settled, status: result.status, agent_id: args.agent_id };
|
|
172
|
+
},
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@argszero/cordis-plugin-subagent-wait",
|
|
3
|
+
"description": "wait_for_agent for the dsh harness: block until a continuable background subagent settles (via the subagent-settled notice) instead of polling list_agents and misreading idle.",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"default": "./lib/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"lib",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"@deepseek-ai/cordis": ">=4.0.0 <5",
|
|
21
|
+
"@deepseek-ai/dsh-tools": ">=0.1.0",
|
|
22
|
+
"@deepseek-ai/dsh-subagent": ">=0.1.0",
|
|
23
|
+
"@deepseek-ai/dsh-agent": ">=0.1.0",
|
|
24
|
+
"@deepseek-ai/dsh-session": ">=0.1.0",
|
|
25
|
+
"@deepseek-ai/dsh-brand": ">=0.1.0"
|
|
26
|
+
},
|
|
27
|
+
"peerDependenciesMeta": {
|
|
28
|
+
"@deepseek-ai/dsh-agents": {
|
|
29
|
+
"optional": true
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsc -p .",
|
|
34
|
+
"prepack": "tsc -p .",
|
|
35
|
+
"test": "node test/logic.test.mjs"
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": "^22.19 || >=24"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"deepseek",
|
|
42
|
+
"dsh",
|
|
43
|
+
"cordis",
|
|
44
|
+
"plugin",
|
|
45
|
+
"subagent",
|
|
46
|
+
"wait",
|
|
47
|
+
"orchestration",
|
|
48
|
+
"continuable"
|
|
49
|
+
],
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public"
|
|
53
|
+
},
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "git+https://github.com/argszero/cordis-plugin-subagent-wait.git"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@deepseek-ai/cordis": ">=4.0.0 <5",
|
|
60
|
+
"@deepseek-ai/dsh-tools": ">=0.1.0",
|
|
61
|
+
"@deepseek-ai/dsh-subagent": ">=0.1.0",
|
|
62
|
+
"@deepseek-ai/dsh-agent": ">=0.1.0",
|
|
63
|
+
"@deepseek-ai/dsh-session": ">=0.1.0",
|
|
64
|
+
"@deepseek-ai/dsh-brand": ">=0.1.0",
|
|
65
|
+
"typescript": "^7.0.2"
|
|
66
|
+
},
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"@types/node": "^22.20.1"
|
|
69
|
+
}
|
|
70
|
+
}
|