@wrongstack/acp 0.260.0 → 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/index.d.ts CHANGED
@@ -1,5 +1,499 @@
1
- export { A as ACPCancelParams, a as ACPCapabilities, b as ACPChildProcess, c as ACPError, d as ACPImageContent, e as ACPInitializeParams, f as ACPInputSchema, g as ACPMessage, h as ACPNotification, i as ACPPlanContent, j as ACPPlanStep, k as ACPProgressContent, l as ACPRequest, m as ACPResourceContent, n as ACPResponse, o as ACPSessionInfo, p as ACPSessionMode, q as ACPTextContent, r as ACPToolCallRequest, s as ACPToolCallResponse, t as ACPToolDefinition, u as ACPToolList, v as ACPToolResult, w as AgentServerTransport, C as ClientTransport, x as ClientTransportOptions, y as ContentBlock, S as StdioTransport } from './stdio-transport-DoKRVjHz.js';
2
- export { ACPProtocolHandler, ACPToolsRegistry, WrongStackACPServer, WrongStackACPServerOptions } from './agent.js';
3
- export { A as ACPSubagentRunnerOptions, a as ACP_AGENT_COMMANDS, T as ToolTranslator, b as ToolTranslatorOptions, m as makeACPSubagentRunner, c as makeACPSubagentRunnerWithStop } from './index-DPMuJGqv.js';
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 };