@wrongstack/acp 0.257.2 → 0.264.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/dist/agent.d.ts +60 -88
- package/dist/agent.js +402 -133
- package/dist/agent.js.map +1 -1
- package/dist/client.d.ts +2 -2
- package/dist/client.js +890 -114
- package/dist/client.js.map +1 -1
- package/dist/{index-DPMuJGqv.d.ts → index-BvPqJHhm.d.ts} +46 -14
- package/dist/index.d.ts +497 -3
- package/dist/index.js +1733 -326
- package/dist/index.js.map +1 -1
- package/dist/{stdio-transport-DoKRVjHz.d.ts → stdio-transport-CsFr8JzC.d.ts} +8 -1
- package/dist/tools-registry-BCf8evEG.d.ts +36 -0
- package/dist/wrongstack-acp-agent-Dv-A0bEm.d.ts +310 -0
- package/dist/wrongstack-acp-agent.d.ts +3 -0
- package/dist/wrongstack-acp-agent.js +492 -0
- package/dist/wrongstack-acp-agent.js.map +1 -0
- package/package.json +4 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,499 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
|
|
1
|
+
export { c as ACPCancelParams, d as ACPCapabilities, e as ACPChildProcess, f as ACPError, g as ACPImageContent, h as ACPInitializeParams, i as ACPInputSchema, j as ACPMessage, k as ACPNotification, l as ACPPlanContent, m as ACPPlanStep, n as ACPProgressContent, o as ACPRequest, p as ACPResourceContent, q as ACPResponse, r as ACPSessionInfo, s as ACPSessionMode, t as ACPTextContent, u as ACPToolCallRequest, v as ACPToolCallResponse, w as ACPToolDefinition, a as ACPToolList, b as ACPToolResult, A as AgentServerTransport, C as ClientTransport, x as ClientTransportOptions, y as ContentBlock, S as StdioTransport } from './stdio-transport-CsFr8JzC.js';
|
|
2
|
+
export { A as ACPToolsRegistry } from './tools-registry-BCf8evEG.js';
|
|
3
|
+
import { T as ToolCallUpdateNotification, P as PermissionOption, b as RequestPermissionOutcome, S as StopReason, U as UsageCost, c as PlanEntry } from './wrongstack-acp-agent-Dv-A0bEm.js';
|
|
4
|
+
export { A as ACPProtocolHandler, W as WrongStackACPServer, a as WrongStackACPServerOptions } from './wrongstack-acp-agent-Dv-A0bEm.js';
|
|
5
|
+
import { A as ACPSubagentRunnerOptions } from './index-BvPqJHhm.js';
|
|
6
|
+
export { a as ACP_AGENT_COMMANDS, T as ToolTranslator, b as ToolTranslatorOptions, m as makeACPSubagentRunner, c as makeACPSubagentRunnerWithStop } from './index-BvPqJHhm.js';
|
|
4
7
|
import 'node:events';
|
|
5
8
|
import '@wrongstack/core';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Permission policy for ACP v1 client sessions.
|
|
12
|
+
*
|
|
13
|
+
* ACP agents can call `session/request_permission` to ask the user
|
|
14
|
+
* before executing a tool call. The client is expected to surface
|
|
15
|
+
* the question, get a decision, and respond. This module is the seam
|
|
16
|
+
* where WrongStack-specific permission UI can plug in; for v1 we ship
|
|
17
|
+
* a minimal default that auto-approves the first `allow_once` option
|
|
18
|
+
* (or `allow_always` if present) and rejects on abort.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/** A single permission decision request. */
|
|
22
|
+
interface PermissionRequest {
|
|
23
|
+
toolCall: ToolCallUpdateNotification;
|
|
24
|
+
options: readonly PermissionOption[];
|
|
25
|
+
signal: AbortSignal;
|
|
26
|
+
}
|
|
27
|
+
/** A permission policy decides how to respond to a request. */
|
|
28
|
+
type PermissionPolicy = (req: PermissionRequest) => Promise<RequestPermissionOutcome>;
|
|
29
|
+
/**
|
|
30
|
+
* Default policy: pick the safest-looking allow option if the signal
|
|
31
|
+
* is not aborted, otherwise report cancelled. Order of preference:
|
|
32
|
+
*
|
|
33
|
+
* 1. `allow_always`
|
|
34
|
+
* 2. `allow_once`
|
|
35
|
+
* 3. anything else with `optionId` (last resort)
|
|
36
|
+
*
|
|
37
|
+
* Real WrongStack permission UIs replace this; the contract is the
|
|
38
|
+
* `PermissionPolicy` function type, not the implementation.
|
|
39
|
+
*/
|
|
40
|
+
declare const defaultPermissionPolicy: PermissionPolicy;
|
|
41
|
+
|
|
42
|
+
interface ACPSessionOptions {
|
|
43
|
+
command: string;
|
|
44
|
+
args?: readonly string[] | undefined;
|
|
45
|
+
env?: Record<string, string> | undefined;
|
|
46
|
+
cwd?: string | undefined;
|
|
47
|
+
role?: string | undefined;
|
|
48
|
+
/** Sandbox root for fs/* and terminal/* methods. */
|
|
49
|
+
projectRoot: string;
|
|
50
|
+
/** Hard timeout for one prompt turn. Default 5 minutes. */
|
|
51
|
+
timeoutMs?: number | undefined;
|
|
52
|
+
/** Override the permission policy. */
|
|
53
|
+
permissionPolicy?: PermissionPolicy | undefined;
|
|
54
|
+
/** Per-fs-call timeout, default 30s. */
|
|
55
|
+
fsTimeoutMs?: number | undefined;
|
|
56
|
+
/** Per-terminal command timeout, default 5 minutes. */
|
|
57
|
+
terminalTimeoutMs?: number | undefined;
|
|
58
|
+
/** Per-terminal output byte cap, default 1 MiB. */
|
|
59
|
+
terminalOutputByteLimit?: number | undefined;
|
|
60
|
+
}
|
|
61
|
+
interface ACPSessionRunResult {
|
|
62
|
+
text: string;
|
|
63
|
+
stopReason: StopReason;
|
|
64
|
+
hasText: boolean;
|
|
65
|
+
usage?: {
|
|
66
|
+
used: number;
|
|
67
|
+
size: number;
|
|
68
|
+
cost?: UsageCost | undefined;
|
|
69
|
+
} | undefined;
|
|
70
|
+
plan?: PlanEntry[] | undefined;
|
|
71
|
+
}
|
|
72
|
+
type ACPSessionErrorKind = 'spawn_failed' | 'init_failed' | 'protocol_error' | 'session_create_failed' | 'prompt_failed' | 'aborted' | 'closed' | 'agent_died' | 'unsupported_capability';
|
|
73
|
+
declare class ACPSessionError extends Error {
|
|
74
|
+
readonly kind: ACPSessionErrorKind;
|
|
75
|
+
readonly cause: unknown;
|
|
76
|
+
constructor(kind: ACPSessionErrorKind, message: string, cause?: unknown);
|
|
77
|
+
}
|
|
78
|
+
declare class ACPSession {
|
|
79
|
+
private readonly transport;
|
|
80
|
+
private readonly fileServer;
|
|
81
|
+
private readonly terminalServer;
|
|
82
|
+
private readonly permissionPolicy;
|
|
83
|
+
private readonly timeoutMs;
|
|
84
|
+
private readonly opts;
|
|
85
|
+
private state;
|
|
86
|
+
private sessionId;
|
|
87
|
+
/** Pending outbound requests (initialize, session/new, session/prompt, etc). */
|
|
88
|
+
private readonly pending;
|
|
89
|
+
private nextId;
|
|
90
|
+
/** True after close() has been called. */
|
|
91
|
+
private closed;
|
|
92
|
+
private constructor();
|
|
93
|
+
/**
|
|
94
|
+
* Spawn the child, run the initialize handshake, install the
|
|
95
|
+
* message dispatch, and return a ready session.
|
|
96
|
+
*/
|
|
97
|
+
static start(opts: ACPSessionOptions): Promise<ACPSession>;
|
|
98
|
+
private initialize;
|
|
99
|
+
/**
|
|
100
|
+
* Run one prompt turn. Creates a session if needed, sends the
|
|
101
|
+
* prompt, streams session/update notifications, and resolves with
|
|
102
|
+
* the agent's response.
|
|
103
|
+
*
|
|
104
|
+
* Cancellation: if `signal` aborts mid-prompt, we send
|
|
105
|
+
* `session/cancel` (a notification per spec) and keep accepting
|
|
106
|
+
* updates until the agent returns with `stopReason: 'cancelled'`.
|
|
107
|
+
* The result is the same shape as a normal turn, with
|
|
108
|
+
* `stopReason === 'cancelled'`.
|
|
109
|
+
*/
|
|
110
|
+
prompt(text: string, signal: AbortSignal): Promise<ACPSessionRunResult>;
|
|
111
|
+
private createSession;
|
|
112
|
+
/** Tear down the session and kill the child process. */
|
|
113
|
+
close(): Promise<void>;
|
|
114
|
+
private allocId;
|
|
115
|
+
private sendRequest;
|
|
116
|
+
private handleMessage;
|
|
117
|
+
private handleUpdate;
|
|
118
|
+
private scratch;
|
|
119
|
+
private accumulatedText;
|
|
120
|
+
private accumulatedPlan;
|
|
121
|
+
private accumulatedUsage;
|
|
122
|
+
private resetScratch;
|
|
123
|
+
private handlePermissionRequest;
|
|
124
|
+
private handleFsRequest;
|
|
125
|
+
private handleTerminalRequest;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Vendor classification — used to filter the catalog by family. */
|
|
129
|
+
type ACPAgentVendor = 'anthropic' | 'google' | 'openai' | 'github' | 'community';
|
|
130
|
+
/** How the agent is integrated into ACP. */
|
|
131
|
+
type ACPIntegration =
|
|
132
|
+
/** Agent ships with a documented ACP entry flag. */
|
|
133
|
+
'native'
|
|
134
|
+
/** Runs through Zed's SDK adapter or similar wrapper. */
|
|
135
|
+
| 'adapter'
|
|
136
|
+
/** Community-maintained wrapper (e.g. @agentify/cline, bub-acp-server). */
|
|
137
|
+
| 'community'
|
|
138
|
+
/** Listed by ACP but no public ACP entry yet; may not work. */
|
|
139
|
+
| 'experimental';
|
|
140
|
+
/** Static metadata for a known agent. */
|
|
141
|
+
interface ACPAgentDescriptor {
|
|
142
|
+
/** Stable identifier used as the spawn key. Lowercase, hyphenated. */
|
|
143
|
+
id: string;
|
|
144
|
+
/** Display name shown in the TUI / WebUI / CLI. */
|
|
145
|
+
displayName: string;
|
|
146
|
+
vendor: ACPAgentVendor;
|
|
147
|
+
/** argv to detect installation. Exits 0 with stdout on success. */
|
|
148
|
+
probe: {
|
|
149
|
+
command: string;
|
|
150
|
+
args?: readonly string[];
|
|
151
|
+
};
|
|
152
|
+
/** argv to start the agent in ACP mode. */
|
|
153
|
+
acp: {
|
|
154
|
+
command: string;
|
|
155
|
+
args?: readonly string[];
|
|
156
|
+
env?: Record<string, string>;
|
|
157
|
+
};
|
|
158
|
+
/** Capability hints — used to fail fast when the binary predates ACP. */
|
|
159
|
+
supports: {
|
|
160
|
+
loadSession: boolean;
|
|
161
|
+
promptImages: boolean;
|
|
162
|
+
terminal: boolean;
|
|
163
|
+
fs: boolean;
|
|
164
|
+
};
|
|
165
|
+
integration: ACPIntegration;
|
|
166
|
+
/** Documentation URL — shown in `wstack acp list` and the ensemble UI. */
|
|
167
|
+
docs: string;
|
|
168
|
+
}
|
|
169
|
+
/** A descriptor with its runtime detection result attached. */
|
|
170
|
+
interface DetectedAgent extends ACPAgentDescriptor {
|
|
171
|
+
installed: boolean;
|
|
172
|
+
/** Absolute path to the binary, if discovered. */
|
|
173
|
+
path?: string;
|
|
174
|
+
/** Captured version string, if `probe` produced one. */
|
|
175
|
+
version?: string;
|
|
176
|
+
/**
|
|
177
|
+
* When `installed: false`, a short reason — typically "binary not
|
|
178
|
+
* found", "binary predates ACP", or "probe timed out".
|
|
179
|
+
*/
|
|
180
|
+
reason?: string;
|
|
181
|
+
}
|
|
182
|
+
/** A single probe failure — never thrown, always returned. */
|
|
183
|
+
interface ProbeFailure {
|
|
184
|
+
ok: false;
|
|
185
|
+
reason: string;
|
|
186
|
+
/** Wall-clock duration of the failed probe in ms. */
|
|
187
|
+
durationMs: number;
|
|
188
|
+
}
|
|
189
|
+
interface ProbeSuccess {
|
|
190
|
+
ok: true;
|
|
191
|
+
version: string;
|
|
192
|
+
path?: string;
|
|
193
|
+
durationMs: number;
|
|
194
|
+
}
|
|
195
|
+
type ProbeResult = ProbeSuccess | ProbeFailure;
|
|
196
|
+
interface EnsembleRegistryOptions {
|
|
197
|
+
/** Override the catalog (mostly for tests). */
|
|
198
|
+
catalog?: readonly ACPAgentDescriptor[];
|
|
199
|
+
/** Override the probe timeout (ms). */
|
|
200
|
+
probeTimeoutMs?: number;
|
|
201
|
+
/** Inject a custom probe function (used by tests). */
|
|
202
|
+
probeFn?: (descriptor: ACPAgentDescriptor) => Promise<ProbeResult>;
|
|
203
|
+
}
|
|
204
|
+
declare class EnsembleRegistry {
|
|
205
|
+
private readonly catalog;
|
|
206
|
+
private readonly timeoutMs;
|
|
207
|
+
private readonly probe;
|
|
208
|
+
private cache;
|
|
209
|
+
constructor(options?: EnsembleRegistryOptions);
|
|
210
|
+
/** Return the full catalog (no probe), in catalog order. */
|
|
211
|
+
listAll(): readonly ACPAgentDescriptor[];
|
|
212
|
+
/**
|
|
213
|
+
* Probe every catalog entry in parallel and return the detection
|
|
214
|
+
* results. Results are cached for `PROBE_CACHE_MS`.
|
|
215
|
+
*/
|
|
216
|
+
list(): Promise<readonly DetectedAgent[]>;
|
|
217
|
+
/** Probe a single descriptor. Always returns a `DetectedAgent`. */
|
|
218
|
+
detect(desc: ACPAgentDescriptor): Promise<DetectedAgent>;
|
|
219
|
+
/** Invalidate the per-process cache. */
|
|
220
|
+
invalidate(): void;
|
|
221
|
+
/** Convenience: just the installed agents. */
|
|
222
|
+
listInstalled(): Promise<readonly DetectedAgent[]>;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Static catalog of ACP-supporting agents known to WrongStack.
|
|
227
|
+
*
|
|
228
|
+
* Scope: CLI-spawnable agents only (i.e. agents that can be run as a
|
|
229
|
+
* subprocess with stdio JSON-RPC, per the ACP v1 spec's local-transport
|
|
230
|
+
* model). IDE-only or SaaS-only entries from
|
|
231
|
+
* https://agentclientprotocol.com/get-started/agents are deliberately
|
|
232
|
+
* omitted — they can't be driven by a SubagentRunner.
|
|
233
|
+
*
|
|
234
|
+
* Maintenance
|
|
235
|
+
* ───────────
|
|
236
|
+
* This is a static catalog by design. ACP v1 is a moving target: agents
|
|
237
|
+
* ship ACP support, deprecate it, change invocation flags. Auto-fetching
|
|
238
|
+
* a live registry sounds appealing but adds a runtime dependency on
|
|
239
|
+
* network + on whatever schema the ACP team decides on for the Registry
|
|
240
|
+
* RFD. A typed static file the maintainer refreshes on a known schedule
|
|
241
|
+
* is more reliable, easier to diff in PRs, and keeps probe failures
|
|
242
|
+
* attributable to the local machine rather than to a transient registry
|
|
243
|
+
* outage.
|
|
244
|
+
*
|
|
245
|
+
* Each entry tags its `integration` mechanism:
|
|
246
|
+
* - `native` — the agent ships with a documented ACP entry flag.
|
|
247
|
+
* - `adapter` — runs through Zed's SDK adapter or similar wrapper.
|
|
248
|
+
* - `community` — community-maintained wrapper (e.g. `@agentify/cline`,
|
|
249
|
+
* `bub-acp-server`, `pi-acp`).
|
|
250
|
+
* - `experimental` — listed by ACP but no public ACP entry yet;
|
|
251
|
+
* entry may not work.
|
|
252
|
+
*
|
|
253
|
+
* When the maintainer verifies an entry works, flip `integration` from
|
|
254
|
+
* `experimental` to `native`/`adapter`/`community` and remove the warning.
|
|
255
|
+
*
|
|
256
|
+
* Detection
|
|
257
|
+
* ─────────
|
|
258
|
+
* The `EnsembleRegistry` (sibling module) probes each entry's `probe`
|
|
259
|
+
* argv in parallel via `Promise.allSettled`. A probe that exits 0 with
|
|
260
|
+
* a non-empty stdout line is considered installed. Probes that time out
|
|
261
|
+
* or print nothing are treated as not-installed.
|
|
262
|
+
*/
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* The catalog. Order is significant for the TUI render — most-requested
|
|
266
|
+
* agents go first. Edit by re-ordering, not by alphabetising.
|
|
267
|
+
*/
|
|
268
|
+
declare const AGENTS_CATALOG: readonly ACPAgentDescriptor[];
|
|
269
|
+
/** O(1) lookup by id. Returns `undefined` for unknown ids. */
|
|
270
|
+
declare function findAgentDescriptor(id: string): ACPAgentDescriptor | undefined;
|
|
271
|
+
|
|
272
|
+
interface FileServerOptions {
|
|
273
|
+
/** Absolute path; only files under this root are accessible. */
|
|
274
|
+
projectRoot: string;
|
|
275
|
+
/** Per-call timeout, default 30s. */
|
|
276
|
+
timeoutMs?: number;
|
|
277
|
+
}
|
|
278
|
+
interface ReadFileParams {
|
|
279
|
+
sessionId: string;
|
|
280
|
+
path: string;
|
|
281
|
+
}
|
|
282
|
+
interface WriteFileParams {
|
|
283
|
+
sessionId: string;
|
|
284
|
+
path: string;
|
|
285
|
+
content: string;
|
|
286
|
+
}
|
|
287
|
+
type FsErrorCode = 'ENOENT' | 'EACCES' | 'OUTSIDE_ROOT' | 'TIMEOUT' | 'INVALID_PATH';
|
|
288
|
+
/**
|
|
289
|
+
* Thrown for protocol-level rejections (path outside root, etc.).
|
|
290
|
+
* The session converts these into JSON-RPC error responses.
|
|
291
|
+
*/
|
|
292
|
+
declare class FsError extends Error {
|
|
293
|
+
readonly code: FsErrorCode;
|
|
294
|
+
readonly path: string;
|
|
295
|
+
constructor(code: FsErrorCode, path: string, message: string);
|
|
296
|
+
}
|
|
297
|
+
declare class FileServer {
|
|
298
|
+
private readonly root;
|
|
299
|
+
private readonly timeoutMs;
|
|
300
|
+
constructor(opts: FileServerOptions);
|
|
301
|
+
/** Read a text file. Returns the content as a string. */
|
|
302
|
+
readTextFile(params: ReadFileParams): Promise<{
|
|
303
|
+
content: string;
|
|
304
|
+
}>;
|
|
305
|
+
/** Write a text file. Atomic via write-then-rename. */
|
|
306
|
+
writeTextFile(params: WriteFileParams): Promise<void>;
|
|
307
|
+
/**
|
|
308
|
+
* Resolve a path; throw `FsError('OUTSIDE_ROOT')` if the result is
|
|
309
|
+
* not under the project root. Symlinks are not followed here — we
|
|
310
|
+
* operate on the textual path. A future hardening pass can
|
|
311
|
+
* `fs.realpath` each access to catch symlink escapes.
|
|
312
|
+
*/
|
|
313
|
+
private resolveInside;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
interface TerminalServerOptions {
|
|
317
|
+
projectRoot: string;
|
|
318
|
+
/** Hard cap on per-command wall-clock. Default 5 minutes. */
|
|
319
|
+
commandTimeoutMs?: number;
|
|
320
|
+
/** Bytes of output to retain per terminal. Default 1 MiB. */
|
|
321
|
+
outputByteLimit?: number;
|
|
322
|
+
/** Optional abort signal that kills ALL active terminals. */
|
|
323
|
+
signal?: AbortSignal;
|
|
324
|
+
}
|
|
325
|
+
declare class TerminalServer {
|
|
326
|
+
private readonly terminals;
|
|
327
|
+
private readonly projectRoot;
|
|
328
|
+
private readonly commandTimeoutMs;
|
|
329
|
+
private readonly outputByteLimit;
|
|
330
|
+
private nextId;
|
|
331
|
+
constructor(opts: TerminalServerOptions);
|
|
332
|
+
/** Spawn a new terminal. Returns the agent-facing id. */
|
|
333
|
+
create(params: {
|
|
334
|
+
sessionId: string;
|
|
335
|
+
command: string;
|
|
336
|
+
args?: string[];
|
|
337
|
+
env?: {
|
|
338
|
+
name: string;
|
|
339
|
+
value: string;
|
|
340
|
+
}[];
|
|
341
|
+
cwd?: string;
|
|
342
|
+
outputByteLimit?: number;
|
|
343
|
+
}): {
|
|
344
|
+
terminalId: string;
|
|
345
|
+
};
|
|
346
|
+
/** Return captured output and (if available) the exit status. */
|
|
347
|
+
output(terminalId: string): {
|
|
348
|
+
output: string;
|
|
349
|
+
truncated: boolean;
|
|
350
|
+
exitStatus?: {
|
|
351
|
+
exitCode: number | null;
|
|
352
|
+
signal: string | null;
|
|
353
|
+
};
|
|
354
|
+
};
|
|
355
|
+
/** Block until the process exits. Resolves with the exit status. */
|
|
356
|
+
waitForExit(terminalId: string): Promise<{
|
|
357
|
+
exitCode: number | null;
|
|
358
|
+
signal: string | null;
|
|
359
|
+
}>;
|
|
360
|
+
/** Kill the process but keep the terminal record (agent can still read output). */
|
|
361
|
+
kill(terminalId: string): void;
|
|
362
|
+
/** Kill the process if alive and remove the record. */
|
|
363
|
+
release(terminalId: string): void;
|
|
364
|
+
/** Kill all active terminals. Used on session close. */
|
|
365
|
+
releaseAll(): void;
|
|
366
|
+
private resolveCwd;
|
|
367
|
+
private buildEnv;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Ensemble runner — fan a single task out to multiple ACP agents in parallel.
|
|
372
|
+
*
|
|
373
|
+
* This is the engine behind both:
|
|
374
|
+
* - `wstack acp parallel <csv> <task>` (CLI subcommand)
|
|
375
|
+
* - `/ensemble <csv> <task>` (TUI slash command)
|
|
376
|
+
*
|
|
377
|
+
* The CLI wraps `runEnsemble` with a plain-text renderer. The TUI can
|
|
378
|
+
* call it directly and format the result however it likes (text dump,
|
|
379
|
+
* per-agent tabbed panels, etc.).
|
|
380
|
+
*
|
|
381
|
+
* Design notes
|
|
382
|
+
* ────────────
|
|
383
|
+
* - Skipping is up-front. We probe the registry once, then run only
|
|
384
|
+
* the installed agents. This keeps the "no installed agents" path
|
|
385
|
+
* cheap (no spawn attempts) and the error message clear.
|
|
386
|
+
* - All agents run concurrently via `Promise.allSettled`. A single
|
|
387
|
+
* failed agent doesn't kill the others; the call returns once every
|
|
388
|
+
* agent has either completed or crashed.
|
|
389
|
+
* - Per-agent errors are captured as structured `{kind, message}`
|
|
390
|
+
* objects, not thrown. The aggregated result is one `EnsembleResult`
|
|
391
|
+
* with per-agent outcomes. Callers can render it as they please.
|
|
392
|
+
* - The `signal` option propagates as the parent AbortSignal for each
|
|
393
|
+
* `SubagentRunner`. Aborting cancels all in-flight agents.
|
|
394
|
+
* - Idempotent cleanup: each agent's `stop()` is called in a
|
|
395
|
+
* `finally`, so a throw in the body still tears the child down.
|
|
396
|
+
*/
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Per-agent outcome from an ensemble run.
|
|
400
|
+
* `status === 'skipped'` carries a `reason`; the other statuses carry
|
|
401
|
+
* either a result or an error envelope.
|
|
402
|
+
*/
|
|
403
|
+
interface EnsembleAgentResult {
|
|
404
|
+
agentId: string;
|
|
405
|
+
status: 'success' | 'failed' | 'skipped' | 'cancelled';
|
|
406
|
+
/** The agent's text result. Present for `status === 'success'`. */
|
|
407
|
+
result?: string | undefined;
|
|
408
|
+
/** Structured error. Present for `status === 'failed' | 'cancelled'`. */
|
|
409
|
+
error?: {
|
|
410
|
+
kind: string;
|
|
411
|
+
message: string;
|
|
412
|
+
} | undefined;
|
|
413
|
+
/** Why the agent was skipped (not installed, unknown id, etc.). */
|
|
414
|
+
reason?: string | undefined;
|
|
415
|
+
/** Wall-clock time spent on this agent. 0 for skipped. */
|
|
416
|
+
durationMs: number;
|
|
417
|
+
/** Agent-reported iteration count (1 per ACP turn). */
|
|
418
|
+
iterations: number;
|
|
419
|
+
/** Agent-reported tool call count (currently 0 for ACP). */
|
|
420
|
+
toolCalls: number;
|
|
421
|
+
}
|
|
422
|
+
/** Aggregate result of one ensemble run. */
|
|
423
|
+
interface EnsembleResult {
|
|
424
|
+
/** The task that was dispatched. */
|
|
425
|
+
task: string;
|
|
426
|
+
/** Agent ids as the user provided them, after dedup. */
|
|
427
|
+
requested: string[];
|
|
428
|
+
/** Per-agent outcomes, in the order they were requested. */
|
|
429
|
+
results: EnsembleAgentResult[];
|
|
430
|
+
/** Roll-up of the per-agent statuses. */
|
|
431
|
+
summary: {
|
|
432
|
+
succeeded: number;
|
|
433
|
+
failed: number;
|
|
434
|
+
skipped: number;
|
|
435
|
+
cancelled: number;
|
|
436
|
+
};
|
|
437
|
+
/** Total wall-clock time of the run (longest agent). */
|
|
438
|
+
totalDurationMs: number;
|
|
439
|
+
}
|
|
440
|
+
/** Sync command resolver: id → command, or null if unknown. */
|
|
441
|
+
type EnsembleCmdResolver = (id: string) => ACPSubagentRunnerOptions | null;
|
|
442
|
+
interface EnsembleRunnerOptions {
|
|
443
|
+
/**
|
|
444
|
+
* Comma-separated agent ids. Whitespace, empty entries, and
|
|
445
|
+
* duplicates are filtered out. Order is preserved.
|
|
446
|
+
*/
|
|
447
|
+
agentIds: string;
|
|
448
|
+
/** The task description forwarded verbatim to each agent. */
|
|
449
|
+
task: string;
|
|
450
|
+
/**
|
|
451
|
+
* Per-agent hard timeout in ms. Defaults to 5 minutes; the
|
|
452
|
+
* `SubagentRunner` itself layers a turn-level timeout under this.
|
|
453
|
+
*/
|
|
454
|
+
timeoutMs?: number;
|
|
455
|
+
/**
|
|
456
|
+
* Override the registry used for the install probe. Defaults to
|
|
457
|
+
* `new EnsembleRegistry()`. Useful for tests.
|
|
458
|
+
*/
|
|
459
|
+
registry?: EnsembleRegistry;
|
|
460
|
+
/**
|
|
461
|
+
* Override the command resolver. Defaults to
|
|
462
|
+
* `defaultEnsembleCmdResolver` (legacy `ACP_AGENT_COMMANDS` map
|
|
463
|
+
* with catalog fallback via `findAgentDescriptor`). Useful for
|
|
464
|
+
* tests that don't want the real `makeACPSubagentRunnerWithStop`.
|
|
465
|
+
*/
|
|
466
|
+
resolveCmd?: EnsembleCmdResolver;
|
|
467
|
+
/**
|
|
468
|
+
* Cancellation signal. Aborting stops all in-flight agents via the
|
|
469
|
+
* `SubagentRunContext.signal` they receive.
|
|
470
|
+
*/
|
|
471
|
+
signal?: AbortSignal | undefined;
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Default command resolver. Checks the legacy `ACP_AGENT_COMMANDS` map
|
|
475
|
+
* first, then falls back to the 12-entry catalog. Returns `null` for
|
|
476
|
+
* ids that aren't in either source.
|
|
477
|
+
*/
|
|
478
|
+
declare const defaultEnsembleCmdResolver: EnsembleCmdResolver;
|
|
479
|
+
/**
|
|
480
|
+
* Fan a task out to multiple ACP agents concurrently.
|
|
481
|
+
*
|
|
482
|
+
* Returns once every requested agent has either completed, failed, or
|
|
483
|
+
* been cancelled. Skipped agents (not installed, unknown id) are
|
|
484
|
+
* reported with `status: 'skipped'` and don't block the result.
|
|
485
|
+
*
|
|
486
|
+
* The function is a pure orchestrator — it does NOT render output. The
|
|
487
|
+
* caller decides how to format the `EnsembleResult`.
|
|
488
|
+
*/
|
|
489
|
+
declare function runEnsemble(opts: EnsembleRunnerOptions): Promise<EnsembleResult>;
|
|
490
|
+
/**
|
|
491
|
+
* Render an `EnsembleResult` as a plain-text block. Useful as the
|
|
492
|
+
* default for the CLI; the TUI can call this or build a richer view.
|
|
493
|
+
*
|
|
494
|
+
* The format mirrors the output the `wstack acp parallel` subcommand
|
|
495
|
+
* emits, so existing scripts that parse the CLI's output keep working.
|
|
496
|
+
*/
|
|
497
|
+
declare function renderEnsembleText(result: EnsembleResult): string;
|
|
498
|
+
|
|
499
|
+
export { type ACPAgentDescriptor, type ACPAgentVendor, type ACPIntegration, ACPSession, ACPSessionError, type ACPSessionErrorKind, type ACPSessionOptions, type ACPSessionRunResult, ACPSubagentRunnerOptions, AGENTS_CATALOG, type DetectedAgent, type EnsembleAgentResult, type EnsembleCmdResolver, EnsembleRegistry, type EnsembleRegistryOptions, type EnsembleResult, type EnsembleRunnerOptions, FileServer, type FileServerOptions, FsError, type FsErrorCode, type PermissionPolicy, type PermissionRequest, type ReadFileParams, TerminalServer, type TerminalServerOptions, type WriteFileParams, defaultEnsembleCmdResolver, defaultPermissionPolicy, findAgentDescriptor, renderEnsembleText, runEnsemble };
|