@tangle-network/agent-runtime 0.71.1 → 0.73.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.
Files changed (66) hide show
  1. package/README.md +8 -8
  2. package/dist/agent.d.ts +27 -17
  3. package/dist/agent.js +21 -9
  4. package/dist/agent.js.map +1 -1
  5. package/dist/analyst-loop.d.ts +1 -1
  6. package/dist/analyst-loop.js +3 -2
  7. package/dist/{chunk-4KGQHS7U.js → chunk-7ODB76J5.js} +2 -18
  8. package/dist/chunk-7ODB76J5.js.map +1 -0
  9. package/dist/chunk-HPYWEFVY.js +4039 -0
  10. package/dist/chunk-HPYWEFVY.js.map +1 -0
  11. package/dist/{chunk-P5OKDSLB.js → chunk-IODKUOBA.js} +5 -3
  12. package/dist/{chunk-P5OKDSLB.js.map → chunk-IODKUOBA.js.map} +1 -1
  13. package/dist/chunk-NBV35BR6.js +68 -0
  14. package/dist/chunk-NBV35BR6.js.map +1 -0
  15. package/dist/{chunk-5ISW5JUF.js → chunk-NCH4XUZ7.js} +2004 -6551
  16. package/dist/chunk-NCH4XUZ7.js.map +1 -0
  17. package/dist/chunk-PBE35ULD.js +52 -0
  18. package/dist/chunk-PBE35ULD.js.map +1 -0
  19. package/dist/{chunk-VLF5RHEQ.js → chunk-T2HVQVB4.js} +1 -66
  20. package/dist/chunk-T2HVQVB4.js.map +1 -0
  21. package/dist/{chunk-K3RM4MPM.js → chunk-U56XGKVY.js} +9 -24
  22. package/dist/chunk-U56XGKVY.js.map +1 -0
  23. package/dist/chunk-UZ5SODU7.js +29 -0
  24. package/dist/chunk-UZ5SODU7.js.map +1 -0
  25. package/dist/{delegates-CsXJPZDH.d.ts → coordination-DU0saWeg.d.ts} +875 -1099
  26. package/dist/index.d.ts +7 -8
  27. package/dist/index.js +10 -12
  28. package/dist/index.js.map +1 -1
  29. package/dist/intelligence.d.ts +1 -1
  30. package/dist/lifecycle.d.ts +281 -0
  31. package/dist/lifecycle.js +174 -0
  32. package/dist/lifecycle.js.map +1 -0
  33. package/dist/{loop-runner-bin-DLM_bVQO.d.ts → loop-runner-bin-eD3m0rHW.d.ts} +10 -27
  34. package/dist/loop-runner-bin.d.ts +5 -6
  35. package/dist/loop-runner-bin.js +6 -6
  36. package/dist/loops.d.ts +47 -10
  37. package/dist/loops.js +47 -42
  38. package/dist/mcp/bin.js +17 -329
  39. package/dist/mcp/bin.js.map +1 -1
  40. package/dist/mcp/index.d.ts +10 -190
  41. package/dist/mcp/index.js +949 -47
  42. package/dist/mcp/index.js.map +1 -1
  43. package/dist/{openai-tools-kdCS-T12.d.ts → openai-tools-CBurv8Cu.d.ts} +11 -13
  44. package/dist/otel-export-BKmNwiCb.d.ts +180 -0
  45. package/dist/profiles.d.ts +3 -3
  46. package/dist/profiles.js +1 -5
  47. package/dist/profiles.js.map +1 -1
  48. package/dist/{substrate-BoRXgvka.d.ts → substrate-rNj6TDc3.d.ts} +7 -23
  49. package/dist/{types-CdnEAE3U.d.ts → types-JufmXF2a.d.ts} +80 -1
  50. package/dist/worktree-DaxOvw-C.d.ts +702 -0
  51. package/dist/{worktree-fanout-CK2ypmEm.d.ts → worktree-fanout-DIffZohV.d.ts} +15 -5
  52. package/package.json +6 -1
  53. package/dist/chunk-4KGQHS7U.js.map +0 -1
  54. package/dist/chunk-5ISW5JUF.js.map +0 -1
  55. package/dist/chunk-74UAWZXE.js +0 -278
  56. package/dist/chunk-74UAWZXE.js.map +0 -1
  57. package/dist/chunk-DVQGYDN5.js +0 -59
  58. package/dist/chunk-DVQGYDN5.js.map +0 -1
  59. package/dist/chunk-INXDNX2W.js +0 -475
  60. package/dist/chunk-INXDNX2W.js.map +0 -1
  61. package/dist/chunk-K3RM4MPM.js.map +0 -1
  62. package/dist/chunk-VLF5RHEQ.js.map +0 -1
  63. package/dist/chunk-XRYEZPR6.js +0 -88
  64. package/dist/chunk-XRYEZPR6.js.map +0 -1
  65. package/dist/coordination-BPQmuwv8.d.ts +0 -666
  66. package/dist/delegation-profile-Bvfro2m1.d.ts +0 -99
@@ -1,666 +0,0 @@
1
- import { c as DelegateFeedbackArgs, d as DelegationFeedbackSnapshot, L as LocalHarness, E as ExecutorFactory, e as ExecutorRegistry, f as DeliverableSpec, S as Spend, g as DelegationTaskQueue, h as CoderDelegate, R as ResearcherDelegate, U as UiAuditorDelegate, T as TraceContext, A as Agent, i as Scope, j as ResultBlobStore, B as Budget } from './delegates-CsXJPZDH.js';
2
- import { T as ToolSpec, R as RouterConfig } from './router-client-C7kp_ECN.js';
3
- import { BackendType } from '@tangle-network/sandbox';
4
- import { S as SandboxClient, E as ExecCtx } from './types-CdnEAE3U.js';
5
-
6
- /**
7
- * @experimental
8
- *
9
- * The child→parent message bus: the ONE pipe carrying every message a worker, sub-driver, or
10
- * analyst sends up to the driver — settled outputs, questions, and trace-analyst findings. It
11
- * unifies channels that were ad-hoc before (the settled-worker cursor, the ask-parent question
12
- * channel, and analyst results) into a single typed primitive with two lanes:
13
- *
14
- * - PASS-THROUGH (`subscribe`): every published event reaches subscribers immediately — the
15
- * express lane for online steering and live observation (a UI, a hook, the parent's box).
16
- * - STANDBY (`pull`): events also queue so the driver consumes them on its own cadence. The queue
17
- * is PRIORITY-ordered: a higher-`priority` event (a blocking question) is bumped ahead of
18
- * queued settles/findings so the driver sees it first; ties resolve FIFO by publish order.
19
- *
20
- * Observability is first-class (A++): every event is stamped with a monotonic `seq` and wall-clock
21
- * `at`, the full ordered `history()` is retained as an audit/replay trail, and `stats()` exposes
22
- * published/pulled counts by kind. Subscribers receive the stamped record, not a bare event.
23
- *
24
- * The interface is transport-agnostic on purpose. Same box → this in-process queue. Cross box →
25
- * the SAME publish/pull/subscribe surface backed by a durable mailbox on the parent's box (children
26
- * POST events with at-least-once retry; payloads are blob refs so the event stays small). Consumers
27
- * depend only on this interface, so distribution is a transport swap, never an architecture change.
28
- */
29
- /** Every bus event is a discriminated union member keyed by `type`. */
30
- interface BusEvent {
31
- readonly type: string;
32
- }
33
- /** A published event stamped for ordering and observability. `seq` is the monotonic publish index;
34
- * `priority` drives pull order (higher = bumped ahead); `at` is the wall-clock publish time (ms). */
35
- interface BusRecord<E extends BusEvent> {
36
- readonly seq: number;
37
- readonly at: number;
38
- readonly priority: number;
39
- readonly event: E;
40
- }
41
- interface PublishOptions {
42
- /** Higher = pulled ahead of lower-priority queued events (default 0). A blocking question sets
43
- * this so it bumps to the front of the driver's inbox. */
44
- readonly priority?: number;
45
- /** Whether the event enters the pull queue (default true). Set `false` for record-only events —
46
- * the parent→child down-leg (steer / answer / resume): they belong in `history()` and reach
47
- * `subscribe` observers, but the parent must never `pull` its own outbound message back. */
48
- readonly queue?: boolean;
49
- }
50
- interface BusStats {
51
- readonly published: number;
52
- readonly pulled: number;
53
- /** Count published per event `type`. */
54
- readonly byKind: Readonly<Record<string, number>>;
55
- }
56
- interface EventBus<E extends BusEvent> {
57
- /** Stamp + queue the event, then deliver the stamped record to every subscriber in order.
58
- * Returns the stamped record. */
59
- publish(event: E, opts?: PublishOptions): Promise<BusRecord<E>>;
60
- /** Remove and return the highest-priority QUEUED event whose type is in `kinds` (any if omitted),
61
- * ties broken FIFO by `seq`; `undefined` when nothing matches. */
62
- pull(kinds?: ReadonlyArray<E['type']>): E | undefined;
63
- /** Register a pass-through handler; it receives the stamped record of every event published after
64
- * registration. Returns an unsubscribe fn. */
65
- subscribe(handler: (record: BusRecord<E>) => void | Promise<void>): () => void;
66
- /** Count of queued, not-yet-pulled events (filtered by `kinds` when given). */
67
- pending(kinds?: ReadonlyArray<E['type']>): number;
68
- /** The full ordered log of every event ever published (the audit/replay trail). */
69
- history(): ReadonlyArray<BusRecord<E>>;
70
- /** Throughput counters for observability dashboards. */
71
- stats(): BusStats;
72
- }
73
- declare function createEventBus<E extends BusEvent>(now?: () => number): EventBus<E>;
74
-
75
- /**
76
- * @experimental
77
- *
78
- * Feedback persistence surface for the MCP layer.
79
- *
80
- * The substrate cannot import `@tangle-network/agent-knowledge` (it would
81
- * induce a dependency cycle), so the store is an abstract interface. The
82
- * default implementation is in-memory; consumers wire their own adapter
83
- * (a real KbStore-backed sink, an HTTP relay to gtm-agent's knowledge
84
- * service, etc.) via `createMcpServer({ feedbackStore })`.
85
- *
86
- * Feedback events are append-only: every rating is a new event with a
87
- * fresh id, even when the same delegation is rated multiple times. The
88
- * caller decides how to roll up scores downstream.
89
- */
90
-
91
- /** @experimental */
92
- interface FeedbackEvent {
93
- id: string;
94
- refersTo: DelegateFeedbackArgs['refersTo'];
95
- rating: DelegateFeedbackArgs['rating'];
96
- by: DelegateFeedbackArgs['by'];
97
- capturedAt: string;
98
- namespace?: string;
99
- }
100
- /** @experimental */
101
- interface FeedbackStore {
102
- /** Append a new event. Never dedupes — every rating is its own event. */
103
- put(event: FeedbackEvent): Promise<void>;
104
- /**
105
- * List events filtered by `namespace`. When `namespace` is omitted, list
106
- * across all namespaces. Returns events in insertion order.
107
- */
108
- list(filter?: {
109
- namespace?: string;
110
- refersToRef?: string;
111
- }): Promise<FeedbackEvent[]>;
112
- }
113
- /** @experimental */
114
- declare class InMemoryFeedbackStore implements FeedbackStore {
115
- private readonly events;
116
- put(event: FeedbackEvent): Promise<void>;
117
- list(filter?: {
118
- namespace?: string;
119
- refersToRef?: string;
120
- }): Promise<FeedbackEvent[]>;
121
- }
122
- /**
123
- * Project a `FeedbackEvent` down to the snapshot shape carried on
124
- * `delegation_history` entries.
125
- *
126
- * @experimental
127
- */
128
- declare function eventToSnapshot(event: FeedbackEvent): DelegationFeedbackSnapshot;
129
-
130
- /**
131
- * @experimental
132
- *
133
- * The leaf runtime — the built-in `Executor` IMPLEMENTATIONS behind the ONE
134
- * open interface frozen in `./types`, plus the open resolver/registry that maps
135
- * an `AgentSpec` to one of them OR accepts a bring-your-own executor verbatim.
136
- *
137
- * The interface is the extension point, not a closed `inline|sandbox|cli` union:
138
- * - router/inline : a direct OpenAI-compatible Router call, no box (one-shot).
139
- * - sandbox : COMPOSES the existing `runLoop` kernel as a single-task
140
- * leaf and surfaces its token/cost usage as `UsageEvent`s;
141
- * forwards PR #150's optional `lineage` passthrough WITHOUT
142
- * reinventing checkpoint/fork (streaming).
143
- * - cli : a Halo/RLM subprocess; `budgetExempt` (no token accounting),
144
- * excluded from the equal-k arms by construction (streaming).
145
- * Every metered runtime reports through the SAME normalized `UsageEvent` channel
146
- * so the conserved budget pool meters them identically. A user's own agent is
147
- * first-class the moment it implements `Executor` — register it by name or
148
- * pass it as `AgentSpec.executor`.
149
- *
150
- * Layering: `estimateCost`/`isModelPriced` are substrate primitives from
151
- * `@tangle-network/agent-eval`; `runLoop`/`acquireSandbox` are runtime kernels
152
- * from this package. No per-vendor adapters live here.
153
- */
154
-
155
- /**
156
- * Router/inline connection seam. A direct OpenAI-compatible Router endpoint —
157
- * the cheapest leaf, no box, no tools. `model` overrides the profile's model
158
- * hint when present; otherwise the profile's `model.default` is required.
159
- */
160
- interface RouterSeam {
161
- routerBaseUrl: string;
162
- routerKey: string;
163
- model?: string;
164
- }
165
- /**
166
- * Sandbox executor seam. The `sandboxClient` the composed `runLoop` creates
167
- * boxes through, plus the optional trace/run/lineage wiring forwarded into the
168
- * loop. `lineage` is opaque here (PR #150's `RunLoopOptions.lineage`): forwarded
169
- * forward-compatibly, never inspected — this executor does NOT reinvent
170
- * checkpoint/fork.
171
- */
172
- interface SandboxSeam {
173
- sandboxClient: SandboxClient;
174
- /** Forwarded into the composed `runLoop`'s `ctx` (trace emitter, run handle, etc.). */
175
- loopCtx?: Partial<Omit<ExecCtx, 'sandboxClient' | 'signal'>>;
176
- /** PR #150 `RunLoopOptions.lineage` passthrough — opaque; forwarded, not parsed. */
177
- lineage?: unknown;
178
- /** Hard cap on the composed loop's iterations. The budget pool reserves against
179
- * the spawn `Budget.maxIterations`; this is the leaf's own ceiling. Default 1. */
180
- maxIterations?: number;
181
- }
182
- /** CLI subprocess seam. `bin` + `args` describe the Halo/RLM process to spawn. */
183
- interface CliSeam {
184
- bin: string;
185
- args?: string[];
186
- /** Extra environment for the subprocess (merged over `process.env`). */
187
- env?: Record<string, string>;
188
- /** Working directory for the subprocess. */
189
- cwd?: string;
190
- }
191
- /**
192
- * cli-worktree seam. A supervisor-authored `AgentProfile` driving a local coding-harness CLI
193
- * (claude / codex / opencode) on its own git worktree — the leaf `createWorktreeCliExecutor`
194
- * named as data. `harness` + `repoRoot` + `taskPrompt` are required; the authored
195
- * `profile.prompt.systemPrompt` + `profile.model.default` reach the harness via the §1.5
196
- * `harnessInvocation` mapper. Everything else mirrors `WorktreeCliExecutorOptions`.
197
- */
198
- interface CliWorktreeSeam {
199
- repoRoot: string;
200
- harness: LocalHarness;
201
- taskPrompt: string;
202
- runId?: string;
203
- baseRef?: string;
204
- harnessTimeoutMs?: number;
205
- }
206
- /**
207
- * cli-bridge seam. A local OpenAI-compatible bridge that fronts harness CLIs
208
- * (claude-code / opencode / kimi / pi) behind one HTTP surface; `model` doubles
209
- * as the harness selector (e.g. `claude-code/sonnet`, `opencode/<provider>/<model>`).
210
- * `agentProfile` is the bridge-dialect profile (metadata.disallowedTools, mcp)
211
- * forwarded verbatim per request — how an arm disables native tools or injects
212
- * a provider search MCP.
213
- *
214
- * The executor opens a RESUMABLE cli-bridge session — structurally identical to the
215
- * sandbox executor's persistent box, just local. `sessionId` is the stable
216
- * caller-owned id cli-bridge maps to the harness's internal conversation id; a
217
- * follow-up steer/resume on the SAME id continues the SAME harness session (opencode
218
- * `-s`, claude `--resume`, …). Omit it and the executor mints a stable one per spawn.
219
- */
220
- interface BridgeSeam {
221
- bridgeUrl: string;
222
- bridgeBearer: string;
223
- model: string;
224
- agentProfile?: Record<string, unknown>;
225
- timeoutMs?: number;
226
- /** Stable, caller-owned cli-bridge session id for harness-side resume. Defaults
227
- * to a freshly minted per-spawn id so each worker is its own resumable session. */
228
- sessionId?: string;
229
- /** Per-resume-turn inference cap before the worker settles on its last output.
230
- * Mirrors `routerToolsInlineExecutor.maxTurns`; default 200 (runaway backstop). */
231
- maxTurns?: number;
232
- }
233
- /**
234
- * Router seam WITH tool use — the tool-using router backend. Same direct
235
- * OpenAI-compatible endpoint as `RouterSeam`, but each turn passes `tools`; when
236
- * the model emits tool_calls they run via `executeToolCall` ON THIS HOST and the
237
- * results fold back as `tool` messages, repeating until the model answers without
238
- * a tool or `maxTurns` is hit. A real agentic loop, OFF-BOX — no sandbox, so it
239
- * is unaffected by a box's egress allowlist. One turn = one completion = the
240
- * equal-compute unit. `executeToolCall` receives the task so per-task tool
241
- * surfaces (e.g. a gym keyed by task) can dispatch correctly.
242
- */
243
- interface RouterToolsSeam {
244
- routerBaseUrl: string;
245
- routerKey: string;
246
- model?: string;
247
- tools: ReadonlyArray<ToolSpec>;
248
- executeToolCall: (name: string, args: Record<string, unknown>, task: unknown) => Promise<string>;
249
- /** Online observer of each tool step — the seam a `DetectorMonitor` taps to watch the live pipe
250
- * (raise a `finding` when the worker loops/errors). Called after every tool call resolves, with
251
- * real per-call wall-clock (`startedAt`/`endedAt`/`durationMs`) so a push `TraceSource` can carry
252
- * non-zero span durations onto the unified timeline. */
253
- onToolStep?: (step: {
254
- toolName: string;
255
- args: Record<string, unknown>;
256
- status: 'ok' | 'error';
257
- startedAt?: number;
258
- endedAt?: number;
259
- durationMs?: number;
260
- }) => void;
261
- /** Max inference turns. Default 200 (runaway backstop — set far above any
262
- * legitimate workflow). For tighter per-workflow limits use a cost budget
263
- * or wall-clock deadline at the call site. */
264
- maxTurns?: number;
265
- }
266
- /**
267
- * The leaf `createWorktreeCliExecutor` as a backend-as-data factory: a supervisor-authored
268
- * `AgentProfile` driving claude / codex / opencode on its own worktree. `budgetExempt` like
269
- * the other CLI leaves; the authored systemPrompt + model reach the harness via §1.5.
270
- */
271
- declare const cliWorktreeExecutor: ExecutorFactory<unknown>;
272
- /**
273
- * Config for {@link createExecutor}: the backend is DATA — the cost dial a profile,
274
- * an experiment config, or a replay journal can name — not an import choice. Each
275
- * variant carries its backend's seam (router/router-tools/bridge/cli/cli-worktree/sandbox).
276
- */
277
- type ExecutorConfig = ({
278
- backend: 'router';
279
- } & RouterSeam) | ({
280
- backend: 'router-tools';
281
- } & RouterToolsSeam) | ({
282
- backend: 'bridge';
283
- } & BridgeSeam) | ({
284
- backend: 'cli';
285
- } & CliSeam) | ({
286
- backend: 'cli-worktree';
287
- } & CliWorktreeSeam) | ({
288
- backend: 'sandbox';
289
- harness?: BackendType;
290
- } & SandboxSeam);
291
- /**
292
- * The single built-in executor factory. Picks a leaf backend by data (`config.backend`),
293
- * injects the matching seam, and delegates to that backend's built-in implementation.
294
- * The `Executor` port stays OPEN: bring-your-own agents implement `Executor` directly
295
- * and never pass through here. Use this (or `createExecutorRegistry`) instead of a
296
- * per-vendor adapter or a closed `inline|sandbox|cli` switch — those bypass the
297
- * `UsageEvent` reporting channel.
298
- */
299
- declare function createExecutor(config: ExecutorConfig): ExecutorFactory<unknown>;
300
- /**
301
- * The open resolver/registry. Pre-registers the three built-ins under their
302
- * runtime tags (`'router'`, `'sandbox'`, `'cli'`) and accepts `register(name,
303
- * factory)` for any additional runtime — and a BYO `AgentSpec.executor` resolves
304
- * without touching the registry at all. NOT a closed switch; registration + BYO
305
- * ARE the extension points.
306
- *
307
- * `resolve` precedence (frozen in `ExecutorRegistry`): a BYO `spec.executor` →
308
- * `harness === null` → the `'router'` factory; else a registered factory for the
309
- * harness-derived runtime (`'sandbox'` for any `BackendType`); else fail loud.
310
- */
311
- declare function createExecutorRegistry(): ExecutorRegistry;
312
-
313
- /**
314
- * @experimental
315
- *
316
- * `delegate` MCP tool — the ONE generic delegation verb, the agent-facing front door to
317
- * `delegate()` / `supervise()`. The agent hands it an INTENT (what it wants done); a default
318
- * authoring supervisor decomposes the intent and AUTHORS the worker profile it needs — there is no
319
- * hardcoded coder/researcher profile. It is the generic replacement for `delegate_code` /
320
- * `delegate_research`.
321
- *
322
- * Unlike those async, queue-backed tools (kick off → return a taskId → poll `delegation_status`),
323
- * `delegate` is SYNCHRONOUS: it awaits the full supervised run and returns the delivered output
324
- * TOGETHER WITH `spentTotal` — the conserved cost of the whole delegation (`iterations` / `tokens` /
325
- * `usd` / `ms`). Returning the real spend is the whole reason `delegate` beats `delegate_code`,
326
- * which has no cost channel.
327
- *
328
- * The supervisor's substrate (its brain `router`, the worker `backend`, the completion `deliverable`)
329
- * is INJECTED at server construction — never an agent-supplied arg — exactly as `delegate_code`
330
- * injects its `CoderDelegate`. The agent supplies only the intent (+ an optional per-call `model` /
331
- * `runId`).
332
- */
333
-
334
- /** @experimental */
335
- declare const DELEGATE_TOOL_NAME = "delegate";
336
- /** @experimental */
337
- declare const DELEGATE_DESCRIPTION: string;
338
- /** @experimental */
339
- declare const DELEGATE_INPUT_SCHEMA: {
340
- readonly type: "object";
341
- readonly properties: {
342
- readonly intent: {
343
- readonly type: "string";
344
- readonly description: "What you want accomplished, as an outcome. The supervisor authors the worker.";
345
- };
346
- readonly model: {
347
- readonly type: "string";
348
- readonly description: "Optional per-call override for the supervisor brain model.";
349
- };
350
- readonly runId: {
351
- readonly type: "string";
352
- readonly description: "Optional trace-correlation id for this delegation.";
353
- };
354
- };
355
- readonly required: readonly ["intent"];
356
- readonly additionalProperties: false;
357
- };
358
- /** Parsed `delegate` tool arguments. */
359
- interface DelegateArgs {
360
- intent: string;
361
- model?: string;
362
- runId?: string;
363
- }
364
- /** @experimental */
365
- declare function validateDelegateArgs(raw: unknown): DelegateArgs;
366
- /** The synchronous result the `delegate` tool returns to the calling agent: the delivered output (or
367
- * the no-winner reason) PLUS the conserved spend of the whole delegation. */
368
- type DelegateResult = {
369
- status: 'winner';
370
- out: unknown;
371
- outRef: string;
372
- spentTotal: Spend;
373
- } | {
374
- status: 'no-winner';
375
- reason: string;
376
- spentTotal: Spend;
377
- };
378
- /** @experimental */
379
- interface DelegateHandlerOptions {
380
- /** The supervisor brain's router substrate (REQUIRED — the default supervisor is router-brained). */
381
- router: RouterConfig;
382
- /** WHERE the authored workers run. Required for `supervise()` to spawn anything. */
383
- backend: ExecutorConfig;
384
- /** The completion oracle the authored workers settle against (settled ⟺ delivered). */
385
- deliverable?: DeliverableSpec;
386
- /** Default supervisor brain model when a call omits `model`. */
387
- model?: string;
388
- /** Restrict the run to this subset of models. */
389
- allowedModels?: readonly string[];
390
- }
391
- /**
392
- * Build the `delegate` tool handler. Closes over the injected supervisor substrate (`router` /
393
- * `backend` / `deliverable`); each call routes the agent's intent to `delegate()` and returns the
394
- * delivered output with its conserved cost.
395
- */
396
- declare function createDelegateHandler(options: DelegateHandlerOptions): (raw: unknown) => Promise<DelegateResult>;
397
-
398
- /**
399
- * @experimental
400
- *
401
- * Stdio JSON-RPC MCP server exposing the 5 delegation tools to sandbox
402
- * coding-harness agents (claude-code, codex, opencode, ...).
403
- *
404
- * The server is transport-bound but topology-free: tool execution is
405
- * delegated to handler functions composed from a queue, a feedback
406
- * store, and per-profile run delegates. Consumers wire those at
407
- * construction time. The `agent-runtime-mcp` bin spins up a default
408
- * configuration for the common case (real sandbox client + coder).
409
- *
410
- * Wire protocol: line-delimited JSON-RPC 2.0 over stdio. Each line is
411
- * one request; each response is one line. `tools/list` and `tools/call`
412
- * mirror the MCP 2024-11-05 spec; we do not pull in
413
- * `@modelcontextprotocol/sdk` to keep the dependency footprint zero.
414
- */
415
-
416
- /** @experimental */
417
- interface McpServerOptions {
418
- /**
419
- * Required to enable `delegate` — the ONE generic delegation verb (the replacement for
420
- * delegate_code / delegate_research). Inject the supervisor substrate: its brain `router`, the
421
- * worker `backend`, and the completion `deliverable`. The supervisor AUTHORS its own worker from
422
- * the agent's intent, so there is no worker profile to wire here.
423
- */
424
- delegateSupervisor?: DelegateHandlerOptions;
425
- /** Required to enable delegate_code. */
426
- coderDelegate?: CoderDelegate;
427
- /**
428
- * Required to enable delegate_research. The substrate cannot ship a
429
- * default — wire one that closes over your `runLoop` + a
430
- * researcher profile (typically `@tangle-network/agent-knowledge`'s
431
- * `researcherProfile` / `multiHarnessResearcherFanout`).
432
- */
433
- researcherDelegate?: ResearcherDelegate;
434
- /**
435
- * Required to enable delegate_ui_audit. Wire one that closes over your
436
- * `runLoop` + `uiAuditorProfile` + a `SandboxClient` (the
437
- * canonical in-process choice is `createInProcessUiAuditClient` from
438
- * `@tangle-network/agent-runtime/profiles`) + your vision judge.
439
- */
440
- uiAuditorDelegate?: UiAuditorDelegate;
441
- /** Override the default in-memory feedback store. */
442
- feedbackStore?: FeedbackStore;
443
- /** Override the default in-memory task queue. */
444
- queue?: DelegationTaskQueue;
445
- /**
446
- * Record deterministic detached-session resume keys on single-variant
447
- * coder/researcher submissions so a durable queue can resume them after a
448
- * restart. Enable only when the wired delegates dispatch via sandbox
449
- * sessions (`driveTurn`) AND `queue` persists records — the keys are inert
450
- * otherwise. The bin turns this on alongside the durable store for
451
- * session-backed (sibling/fleet) placements.
452
- */
453
- detachedDispatch?: boolean;
454
- /**
455
- * Extra tools to serve alongside the delegation tools, for example
456
- * `createCoordinationTools(...).tools`. Registered after the built-ins; a
457
- * duplicate name throws so delegation tools cannot be shadowed silently.
458
- */
459
- extraTools?: McpToolDescriptor[];
460
- /**
461
- * Inherited trace identity (`readTraceContextFromEnv()`) stamped on every
462
- * record the DEFAULT queue creates. Ignored when `queue` is supplied —
463
- * pass `traceContext` to that queue's constructor instead.
464
- */
465
- traceContext?: TraceContext;
466
- /** Server display name surfaced via `initialize`. Default `'agent-runtime-mcp'`. */
467
- serverName?: string;
468
- /** Server version surfaced via `initialize`. Default = the package version baked at build time. */
469
- serverVersion?: string;
470
- }
471
- /** @experimental */
472
- interface McpToolDescriptor {
473
- name: string;
474
- description: string;
475
- inputSchema: Record<string, unknown>;
476
- handler: (raw: unknown) => Promise<unknown>;
477
- }
478
- /** @experimental */
479
- interface McpServer {
480
- /** Tools currently registered (depend on which delegates were wired). */
481
- readonly tools: ReadonlyMap<string, McpToolDescriptor>;
482
- /** The underlying queue — exposed so tests can introspect it. */
483
- readonly queue: DelegationTaskQueue;
484
- /** The feedback store — exposed for the same reason. */
485
- readonly feedbackStore: FeedbackStore;
486
- /** Handle a single parsed JSON-RPC message. Returns the response object (or `null` for notifications). */
487
- handle(message: JsonRpcMessage): Promise<JsonRpcResponse | null>;
488
- /** Drive the server on a stdio-shaped transport until `stop()` is called. */
489
- serve(transport?: McpTransport): Promise<void>;
490
- /** Stop a `serve` call. Subsequent requests are rejected. */
491
- stop(): void;
492
- }
493
- /** @experimental */
494
- interface McpTransport {
495
- input: NodeJS.ReadableStream;
496
- output: NodeJS.WritableStream;
497
- }
498
- /** @experimental */
499
- interface JsonRpcMessage {
500
- jsonrpc: '2.0';
501
- id?: number | string | null;
502
- method: string;
503
- params?: unknown;
504
- }
505
- /** @experimental */
506
- interface JsonRpcResponse {
507
- jsonrpc: '2.0';
508
- id: number | string | null;
509
- result?: unknown;
510
- error?: {
511
- code: number;
512
- message: string;
513
- data?: unknown;
514
- };
515
- }
516
- /** @experimental */
517
- declare function createMcpServer(options?: McpServerOptions): McpServer;
518
- /**
519
- * In-process pair of `Readable` + `Writable` streams suitable for driving
520
- * `server.serve(...)` from a test. Returns the agent-side stream (the
521
- * client writes to it) and the server-side stream (the test reads from it).
522
- *
523
- * @experimental
524
- */
525
- declare function createInProcessTransport(): {
526
- transport: McpTransport;
527
- clientWrite(line: string): void;
528
- clientClose(): void;
529
- readServer(): Promise<JsonRpcResponse[]>;
530
- };
531
-
532
- /**
533
- * @experimental
534
- *
535
- * MCP binding for a live `Scope`. A sandbox driver gets the same small verbs
536
- * the in-process driver has: spawn, observe, await, steer, ask/answer, analyze,
537
- * and stop. Settled outputs remain Scope artifacts; product code can project
538
- * them into any UI/report envelope it needs.
539
- */
540
-
541
- /** A worker the driver has drained via `await_event`. */
542
- interface SettledWorker {
543
- readonly id: string;
544
- readonly status: 'done' | 'down';
545
- readonly score?: number;
546
- readonly valid?: boolean;
547
- readonly outRef?: string;
548
- readonly reason?: string;
549
- }
550
- type QuestionLevel = 'worker' | 'driver' | 'loop';
551
- type QuestionUrgency = 'continue-without' | 'blocks-step' | 'blocks-run';
552
- interface QuestionOption {
553
- readonly label: string;
554
- readonly tradeoff: string;
555
- }
556
- interface Question {
557
- readonly id: string;
558
- readonly from: string;
559
- readonly level: QuestionLevel;
560
- readonly question: string;
561
- readonly reason: string;
562
- readonly urgency: QuestionUrgency;
563
- readonly options?: ReadonlyArray<QuestionOption>;
564
- }
565
- type QuestionDecision = {
566
- readonly kind: 'answer';
567
- readonly answer: string;
568
- readonly by: string;
569
- } | {
570
- readonly kind: 'defer';
571
- readonly reason: string;
572
- } | {
573
- readonly kind: 'escalate';
574
- readonly to: 'parent' | 'user' | string;
575
- readonly reason: string;
576
- };
577
- interface QuestionRecord extends Question {
578
- readonly status: 'open' | 'answered' | 'deferred' | 'escalated';
579
- readonly decision?: QuestionDecision;
580
- readonly openedAt: number;
581
- }
582
- type QuestionPolicy = 'auto' | 'mustDecide' | 'bubble' | 'failClosed';
583
- interface AnalystRegistry {
584
- readonly kinds: ReadonlyArray<{
585
- id: string;
586
- description: string;
587
- area: string;
588
- }>;
589
- readonly run: (kindId: string, trace: unknown) => Promise<unknown>;
590
- }
591
- /** A trace-analyst result re-entered as a message on the bus (the `finding` event kind). */
592
- interface AnalystFindingEvent {
593
- readonly fromWorker: string;
594
- readonly analyst: string;
595
- readonly findings: unknown;
596
- }
597
- /** A parent→child message (the down-leg): recorded for observability, delivered via the child inbox,
598
- * never pulled back by the parent. `delivered` mirrors whether the live child accepted it. */
599
- interface DownMessageEvent {
600
- readonly toWorker: string;
601
- readonly instruction: string;
602
- readonly delivered: boolean;
603
- }
604
- /** Every message on the one typed pipe. UP (child→parent): question / settled / finding — queued for
605
- * the driver to `pull`. DOWN (parent→child): steer / answer — record-only (history + subscribers),
606
- * routed to the child inbox. New kinds are additive. */
607
- type CoordinationEvent = {
608
- readonly type: 'question';
609
- readonly question: QuestionRecord;
610
- } | {
611
- readonly type: 'settled';
612
- readonly worker: SettledWorker;
613
- } | {
614
- readonly type: 'finding';
615
- readonly finding: AnalystFindingEvent;
616
- } | {
617
- readonly type: 'steer';
618
- readonly down: DownMessageEvent;
619
- } | {
620
- readonly type: 'answer';
621
- readonly down: DownMessageEvent;
622
- readonly questionId: string;
623
- };
624
- type MakeWorkerAgent = (profile: unknown) => Agent<unknown, unknown>;
625
- interface CoordinationToolsOptions {
626
- readonly scope: Scope<unknown>;
627
- readonly blobs: ResultBlobStore;
628
- readonly makeWorkerAgent: MakeWorkerAgent;
629
- readonly perWorker: Budget;
630
- readonly analysts?: AnalystRegistry;
631
- readonly onEvent?: (event: CoordinationEvent) => void | Promise<void>;
632
- readonly questionPolicy?: QuestionPolicy;
633
- /** Analyst kind ids to run AUTOMATICALLY when a worker settles `done` (the analyst-on-settle
634
- * hook). Each result is published as a `finding` event on the bus — pass-through to subscribers
635
- * and queued for the driver to pull via `await_event`. Omit/empty = no auto-analysis (default;
636
- * the driver can still run lenses on demand via `run_analyst`). Requires `analysts`. */
637
- readonly analyzeOnSettle?: ReadonlyArray<string>;
638
- }
639
- /**
640
- * The supervisor-side toolbox returned by {@link createCoordinationTools}: the MCP tool
641
- * descriptors a driver `AgentProfile` calls to spawn, steer, observe, and settle workers
642
- * over a live `Scope`, plus the typed accessors (`settled`/`questions`/`history`/`stats`/
643
- * `raiseFinding`) for the bidirectional coordination bus. This is the live, backend-of-your-
644
- * choice, steerable counterpart to the one-shot own-sandbox delegation MCP.
645
- */
646
- interface CoordinationTools {
647
- readonly tools: McpToolDescriptor[];
648
- isStopped(): boolean;
649
- stopReason(): string | undefined;
650
- settled(): ReadonlyArray<SettledWorker>;
651
- questions(): ReadonlyArray<QuestionRecord>;
652
- /** The full ordered log of every bus event — UP (settled / question / finding) and DOWN
653
- * (steer / answer) — the observability audit + replay trail. Each record carries seq,
654
- * timestamp, and priority. */
655
- history(): ReadonlyArray<BusRecord<CoordinationEvent>>;
656
- /** Bus throughput counters (published / pulled / by-kind) for live dashboards. */
657
- stats(): BusStats;
658
- /** Raise a `finding` on the bus from outside the settle hook — the seam an ONLINE detector
659
- * (mid-run, on the worker pipe) uses to tell the driver "this worker is looping/erroring" the
660
- * moment it happens, instead of only at settle. Queued for `await_event` + pass-through. */
661
- raiseFinding(finding: AnalystFindingEvent): Promise<void>;
662
- }
663
- /** Build the driver's MCP tools over a live scope. */
664
- declare function createCoordinationTools(opts: CoordinationToolsOptions): CoordinationTools;
665
-
666
- export { type AnalystRegistry as A, type BusEvent as B, type CoordinationEvent as C, DELEGATE_DESCRIPTION as D, type ExecutorConfig as E, type FeedbackStore as F, createEventBus as G, createExecutor as H, InMemoryFeedbackStore as I, type JsonRpcMessage as J, createExecutorRegistry as K, type MakeWorkerAgent as M, type PublishOptions as P, type Question as Q, type SettledWorker as S, type CoordinationTools as a, type CoordinationToolsOptions as b, DELEGATE_INPUT_SCHEMA as c, DELEGATE_TOOL_NAME as d, type DelegateArgs as e, type DelegateHandlerOptions as f, type DelegateResult as g, type FeedbackEvent as h, type JsonRpcResponse as i, type McpServer as j, type McpServerOptions as k, type McpToolDescriptor as l, type McpTransport as m, type QuestionDecision as n, type QuestionPolicy as o, type QuestionRecord as p, createCoordinationTools as q, createDelegateHandler as r, createInProcessTransport as s, createMcpServer as t, eventToSnapshot as u, validateDelegateArgs as v, type BusRecord as w, type BusStats as x, type EventBus as y, cliWorktreeExecutor as z };