@tangle-network/agent-runtime 0.77.0 → 0.79.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 (42) hide show
  1. package/dist/agent.d.ts +1 -1
  2. package/dist/agent.js +3 -3
  3. package/dist/analyst-loop.d.ts +1 -1
  4. package/dist/{chunk-O2UPHN7X.js → chunk-5JAUQZQA.js} +1 -1
  5. package/dist/chunk-5JAUQZQA.js.map +1 -0
  6. package/dist/{chunk-RQYPH2QE.js → chunk-EZ2QESTP.js} +871 -33
  7. package/dist/chunk-EZ2QESTP.js.map +1 -0
  8. package/dist/{chunk-LFL7K5FM.js → chunk-F6G3SSHY.js} +2 -2
  9. package/dist/{chunk-KKHMDE5I.js → chunk-GZX3PI7V.js} +3 -3
  10. package/dist/{chunk-JPURCA2O.js → chunk-LWGVVP2C.js} +2 -2
  11. package/dist/{chunk-CEW5BMGN.js → chunk-N2JJDGLJ.js} +2 -2
  12. package/dist/chunk-N2JJDGLJ.js.map +1 -0
  13. package/dist/{coordination-CZe4lTxy.d.ts → coordination-09JTQnlF.d.ts} +88 -25
  14. package/dist/index.d.ts +9 -9
  15. package/dist/index.js +6 -6
  16. package/dist/intelligence.d.ts +1 -1
  17. package/dist/lifecycle.d.ts +2 -2
  18. package/dist/lifecycle.js +2 -2
  19. package/dist/{local-harness-BE_h8szs.d.ts → local-harness-DU7yV6mG.d.ts} +1 -1
  20. package/dist/{loop-runner-bin-Dbtg787n.d.ts → loop-runner-bin-Ddgf4DkS.d.ts} +2 -2
  21. package/dist/loop-runner-bin.d.ts +5 -5
  22. package/dist/loop-runner-bin.js +4 -4
  23. package/dist/loops.d.ts +12 -11
  24. package/dist/loops.js +13 -3
  25. package/dist/mcp/bin.js +2 -2
  26. package/dist/mcp/bin.js.map +1 -1
  27. package/dist/mcp/index.d.ts +12 -12
  28. package/dist/mcp/index.js +4 -4
  29. package/dist/mcp/index.js.map +1 -1
  30. package/dist/{mcp-serve-verifier-CT1KLTG_.d.ts → mcp-serve-verifier-BvMAV_8U.d.ts} +1 -1
  31. package/dist/{openai-tools-D5tcirFF.d.ts → openai-tools-B-3v06BE.d.ts} +1 -1
  32. package/dist/profiles.d.ts +1 -1
  33. package/dist/{types-B-jWSfcu.d.ts → types-BF-MEsQB.d.ts} +21 -0
  34. package/dist/{worktree-CDxqwxGo.d.ts → worktree-CUn0d-ZT.d.ts} +2 -2
  35. package/dist/{worktree-fanout-CljF1L2v.d.ts → worktree-fanout-DwwatTdY.d.ts} +3 -3
  36. package/package.json +3 -7
  37. package/dist/chunk-CEW5BMGN.js.map +0 -1
  38. package/dist/chunk-O2UPHN7X.js.map +0 -1
  39. package/dist/chunk-RQYPH2QE.js.map +0 -1
  40. /package/dist/{chunk-LFL7K5FM.js.map → chunk-F6G3SSHY.js.map} +0 -0
  41. /package/dist/{chunk-KKHMDE5I.js.map → chunk-GZX3PI7V.js.map} +0 -0
  42. /package/dist/{chunk-JPURCA2O.js.map → chunk-LWGVVP2C.js.map} +0 -0
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  harnessInvocation,
9
9
  runLocalHarness
10
- } from "./chunk-O2UPHN7X.js";
10
+ } from "./chunk-5JAUQZQA.js";
11
11
  import {
12
12
  AgentEvalError,
13
13
  ConfigError,
@@ -208,6 +208,786 @@ function assertSeqUnique(root, events, ev) {
208
208
  }
209
209
  }
210
210
 
211
+ // src/runtime/environment-provider.ts
212
+ function createAgentEnvironmentProviderRegistry(providers = []) {
213
+ const entries = /* @__PURE__ */ new Map();
214
+ const registry = {
215
+ register(provider, options = {}) {
216
+ if (!provider.name) {
217
+ throw new ValidationError("agent environment provider registry: provider.name required");
218
+ }
219
+ if (!options.replace && entries.has(provider.name)) {
220
+ throw new ValidationError(
221
+ `agent environment provider registry: provider "${provider.name}" already registered`
222
+ );
223
+ }
224
+ entries.set(provider.name, provider);
225
+ },
226
+ has(name) {
227
+ return entries.has(name);
228
+ },
229
+ get(name) {
230
+ return entries.get(name);
231
+ },
232
+ require(name) {
233
+ const provider = entries.get(name);
234
+ if (!provider) {
235
+ const available = Array.from(entries.keys()).sort();
236
+ const suffix = available.length > 0 ? `; available: ${available.join(", ")}` : "";
237
+ throw new ValidationError(
238
+ `agent environment provider registry: provider "${name}" is not registered${suffix}`
239
+ );
240
+ }
241
+ return provider;
242
+ },
243
+ names() {
244
+ return Array.from(entries.keys()).sort();
245
+ },
246
+ providers() {
247
+ return registry.names().map((name) => registry.require(name));
248
+ },
249
+ async capabilities(name) {
250
+ return registry.require(name).capabilities();
251
+ }
252
+ };
253
+ for (const provider of providers) registry.register(provider);
254
+ return registry;
255
+ }
256
+ function resolveAgentEnvironmentProvider(provider, registry) {
257
+ if (typeof provider !== "string") return provider;
258
+ if (!registry) {
259
+ throw new ValidationError(
260
+ `agent environment provider "${provider}" requires an AgentEnvironmentProviderRegistry`
261
+ );
262
+ }
263
+ return registry.require(provider);
264
+ }
265
+ function providerAsSandboxClient(provider, options = {}) {
266
+ return {
267
+ async create(createOptions) {
268
+ const mapped = {
269
+ ...options.defaults ?? {},
270
+ ...createInputFromSandboxOptions(createOptions),
271
+ ...options.mapCreateOptions?.(createOptions) ?? {}
272
+ };
273
+ if (mapped.profile === void 0) {
274
+ throw new ValidationError(
275
+ `providerAsSandboxClient(${provider.name}): profile required in defaults or CreateSandboxOptions.backend.profile`
276
+ );
277
+ }
278
+ const environment = await provider.create(mapped);
279
+ return environmentAsSandboxInstance(environment, {
280
+ requireTerminalEvent: options.requireTerminalEvent ?? true
281
+ });
282
+ }
283
+ };
284
+ }
285
+ function sandboxClientAsProvider(client, options = {}) {
286
+ const providerName = options.name ?? "tangle-sandbox";
287
+ return {
288
+ name: providerName,
289
+ capabilities: async () => {
290
+ if (options.capabilities) {
291
+ return typeof options.capabilities === "function" ? options.capabilities() : options.capabilities;
292
+ }
293
+ return defaultTangleSandboxCapabilities();
294
+ },
295
+ ...options.validateProfile ? { validateProfile: options.validateProfile } : {},
296
+ async create(input) {
297
+ const createOptions = options.mapCreateInput?.(input) ?? sandboxOptionsFromCreateInput(input, options.defaultBackend ?? "opencode");
298
+ const box = await client.create(createOptions);
299
+ return sandboxInstanceAsEnvironment(box, providerName, client);
300
+ },
301
+ ...hasGet(client) ? {
302
+ async get(id) {
303
+ const box = await client.get(id);
304
+ return box ? sandboxInstanceAsEnvironment(box, providerName, client) : null;
305
+ }
306
+ } : {},
307
+ ...hasList(client) ? {
308
+ async list(query) {
309
+ const boxes = await client.list(query?.providerOptions);
310
+ return boxes.map((box) => ({
311
+ id: String(box.id),
312
+ provider: providerName,
313
+ name: typeof box.name === "string" ? box.name : void 0,
314
+ status: statusFromUnknown(readBoxStatus(box)),
315
+ metadata: readBoxMetadata(box)
316
+ }));
317
+ }
318
+ } : {}
319
+ };
320
+ }
321
+ function providerAsExecutor(provider, options = {}) {
322
+ return (spec, ctx) => createProviderExecutor(provider, spec.profile, ctx, options);
323
+ }
324
+ function createProviderExecutor(provider, profile, ctx, options) {
325
+ const controller = new AbortController();
326
+ const abortIfSignalled = () => {
327
+ if (ctx.signal.aborted) controller.abort();
328
+ };
329
+ abortIfSignalled();
330
+ if (!ctx.signal.aborted) ctx.signal.addEventListener("abort", abortIfSignalled, { once: true });
331
+ let environment;
332
+ let artifact;
333
+ return {
334
+ runtime: options.runtime ?? provider.name,
335
+ execute(task, signal) {
336
+ return streamProviderExecutor({
337
+ provider,
338
+ profile,
339
+ task,
340
+ signal,
341
+ controller,
342
+ options,
343
+ onEnvironment: (env) => {
344
+ environment = env;
345
+ },
346
+ onArtifact: (next) => {
347
+ artifact = next;
348
+ }
349
+ });
350
+ },
351
+ async teardown(_grace) {
352
+ controller.abort();
353
+ await environment?.destroy?.();
354
+ return { destroyed: true };
355
+ },
356
+ resultArtifact() {
357
+ if (!artifact) {
358
+ throw new ValidationError(
359
+ `providerAsExecutor(${provider.name}): resultArtifact() read before stream drained`
360
+ );
361
+ }
362
+ return artifact;
363
+ }
364
+ };
365
+ }
366
+ async function* streamProviderExecutor(args) {
367
+ const started = Date.now();
368
+ const linked = mergeAbortSignals(args.signal, args.controller.signal);
369
+ const environment = await args.provider.create({
370
+ ...args.options.defaults ?? {},
371
+ profile: args.profile,
372
+ signal: linked
373
+ });
374
+ args.onEnvironment(environment);
375
+ const turn = args.options.taskToTurn?.(args.task, args.profile) ?? taskToTurnInput(args.task, linked);
376
+ const events = [];
377
+ const tokens = zeroTokenUsage();
378
+ let usd = 0;
379
+ let text = "";
380
+ let terminal = false;
381
+ try {
382
+ for await (const event of environment.stream({ ...turn, signal: linked })) {
383
+ events.push(event);
384
+ text += textFromEnvironmentEvent(event);
385
+ const usage = usageFromEnvironmentEvent(event);
386
+ if (usage.input || usage.output) {
387
+ tokens.input += usage.input;
388
+ tokens.output += usage.output;
389
+ yield { kind: "tokens", input: usage.input, output: usage.output };
390
+ }
391
+ if (usage.usd) {
392
+ usd += usage.usd;
393
+ yield { kind: "cost", usd: usage.usd };
394
+ }
395
+ if (isTerminalEnvironmentEvent(event)) terminal = true;
396
+ }
397
+ if ((args.options.requireTerminalEvent ?? true) && !terminal) {
398
+ throw new ValidationError(
399
+ `providerAsExecutor(${args.provider.name}): stream ended without a terminal result/done/status event`
400
+ );
401
+ }
402
+ yield { kind: "iteration" };
403
+ const result = resultFromEvents(events, text);
404
+ const spent = {
405
+ iterations: 1,
406
+ tokens,
407
+ usd,
408
+ ms: Date.now() - started
409
+ };
410
+ args.onArtifact({
411
+ outRef: contentRef(`provider:${args.provider.name}`, result),
412
+ out: result,
413
+ spent
414
+ });
415
+ } finally {
416
+ if (args.options.destroyOnSettle ?? true) await environment.destroy?.();
417
+ }
418
+ }
419
+ function createInputFromSandboxOptions(options) {
420
+ const profile = options?.backend?.profile;
421
+ const backend = options?.backend?.type;
422
+ return {
423
+ ...profile !== void 0 ? { profile } : {},
424
+ ...backend ? { backend } : {},
425
+ workspace: {
426
+ ...options?.environment ? { environment: options.environment } : {},
427
+ ...options?.image ? { image: options.image } : {},
428
+ ...options?.git?.url ? { repoUrl: options.git.url } : {},
429
+ ...options?.git?.ref ? { gitRef: options.git.ref } : {}
430
+ },
431
+ ...options?.resources ? { resources: options.resources } : {},
432
+ ...options?.env ? { env: options.env } : {},
433
+ ...options?.secrets ? { secrets: options.secrets } : {},
434
+ ...options?.metadata ? { metadata: options.metadata } : {},
435
+ ...options?.name ? { name: options.name } : {},
436
+ ...options?.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {},
437
+ providerOptions: { sandboxCreateOptions: options ?? {} }
438
+ };
439
+ }
440
+ function sandboxOptionsFromCreateInput(input, defaultBackend) {
441
+ const backendType = input.backend ?? defaultBackend;
442
+ const workspace = input.workspace ?? {};
443
+ const providerOptions = input.providerOptions?.sandboxCreateOptions;
444
+ const base = providerOptions && typeof providerOptions === "object" ? { ...providerOptions } : {};
445
+ return {
446
+ ...base,
447
+ ...workspace.environment ? { environment: workspace.environment } : {},
448
+ ...workspace.image ? { image: workspace.image } : {},
449
+ ...workspace.repoUrl ? { git: { url: workspace.repoUrl, ref: workspace.gitRef } } : {},
450
+ ...input.resources ? { resources: input.resources } : {},
451
+ ...input.env ? { env: input.env } : {},
452
+ ...Array.isArray(input.secrets) ? { secrets: input.secrets } : {},
453
+ ...input.metadata ? { metadata: input.metadata } : {},
454
+ ...input.name ? { name: input.name } : {},
455
+ ...input.idempotencyKey ? { idempotencyKey: input.idempotencyKey } : {},
456
+ backend: {
457
+ ...base.backend ?? {},
458
+ type: backendType,
459
+ profile: input.profile
460
+ }
461
+ };
462
+ }
463
+ function environmentAsSandboxInstance(environment, options) {
464
+ const box = {
465
+ id: environment.id,
466
+ name: environment.name,
467
+ status: "running",
468
+ async refresh() {
469
+ await environment.refresh?.();
470
+ },
471
+ async *streamPrompt(message, promptOptions) {
472
+ let terminal = false;
473
+ const input = turnInputFromPrompt(message, promptOptions);
474
+ for await (const event of environment.stream(input)) {
475
+ if (isTerminalEnvironmentEvent(event)) terminal = true;
476
+ const usageEvent = usageSandboxEvent(event);
477
+ if (usageEvent) yield usageEvent;
478
+ yield sandboxEventFromEnvironmentEvent(event);
479
+ }
480
+ if (options.requireTerminalEvent && !terminal) {
481
+ throw new ValidationError(
482
+ `providerAsSandboxClient(${environment.provider}): stream ended without a terminal result/done/status event`
483
+ );
484
+ }
485
+ },
486
+ async prompt(message, promptOptions) {
487
+ const events = [];
488
+ let text = "";
489
+ let usage;
490
+ let terminal = false;
491
+ for await (const event of environment.stream(turnInputFromPrompt(message, promptOptions))) {
492
+ events.push(event);
493
+ if (isTerminalEnvironmentEvent(event)) terminal = true;
494
+ text += textFromEnvironmentEvent(event);
495
+ usage = mergeTokenUsage(usage, event.usage);
496
+ }
497
+ if (options.requireTerminalEvent && !terminal) {
498
+ throw new ValidationError(
499
+ `providerAsSandboxClient(${environment.provider}): prompt ended without a terminal result/done/status event`
500
+ );
501
+ }
502
+ return {
503
+ response: resultFromEvents(events, text).content,
504
+ success: true,
505
+ durationMs: 0,
506
+ ...usage ? { usage } : {}
507
+ };
508
+ },
509
+ ...environment.dispatch ? {
510
+ async dispatchPrompt(message, promptOptions) {
511
+ const session = await environment.dispatch?.(
512
+ turnInputFromPrompt(message, promptOptions)
513
+ );
514
+ if (!session)
515
+ throw new ValidationError("providerAsSandboxClient: dispatch returned no session");
516
+ return sandboxDispatchResultFromSessionRef(session);
517
+ }
518
+ } : {},
519
+ ...environment.session ? {
520
+ session(id) {
521
+ return sessionAsSandboxSession(environment.session?.(id));
522
+ }
523
+ } : {},
524
+ ...environment.read ? { read: environment.read.bind(environment) } : {},
525
+ ...environment.write ? { write: environment.write.bind(environment) } : {},
526
+ ...environment.exec ? {
527
+ exec: environment.exec.bind(environment)
528
+ } : {},
529
+ ...environment.checkpoint ? {
530
+ async checkpoint(checkpointOptions) {
531
+ const checkpoint = await environment.checkpoint?.(checkpointOptions);
532
+ return { checkpointId: checkpoint?.id, id: checkpoint?.id };
533
+ }
534
+ } : {},
535
+ ...environment.fork ? {
536
+ async fork(checkpointId, forkOptions) {
537
+ const forked = await environment.fork?.({ id: checkpointId }, forkOptions);
538
+ if (!forked)
539
+ throw new ValidationError("providerAsSandboxClient: fork returned no environment");
540
+ return environmentAsSandboxInstance(forked, options);
541
+ }
542
+ } : {},
543
+ async delete() {
544
+ await environment.destroy?.();
545
+ }
546
+ };
547
+ return box;
548
+ }
549
+ function sandboxInstanceAsEnvironment(box, providerName, client) {
550
+ const environment = {
551
+ id: String(box.id),
552
+ provider: providerName,
553
+ ...typeof box.name === "string" ? { name: box.name } : {},
554
+ async status() {
555
+ await maybeRefresh(box);
556
+ return statusFromUnknown(readBoxStatus(box));
557
+ },
558
+ async *stream(input) {
559
+ for await (const event of box.streamPrompt(
560
+ promptFromTurnInput(input),
561
+ promptOptionsFromTurnInput(input)
562
+ )) {
563
+ yield environmentEventFromSandboxEvent(event);
564
+ }
565
+ },
566
+ ...hasDispatchPrompt(box) ? {
567
+ async dispatch(input) {
568
+ const dispatched = await box.dispatchPrompt(
569
+ promptFromTurnInput(input),
570
+ promptOptionsFromTurnInput(input)
571
+ );
572
+ return sessionRefFromSandboxDispatch(dispatched, providerName);
573
+ }
574
+ } : {},
575
+ ...hasSession(box) ? {
576
+ session(id) {
577
+ return sandboxSessionAsAgentSession(box.session(id));
578
+ }
579
+ } : {},
580
+ ...hasRead(box) ? { read: box.read.bind(box) } : {},
581
+ ...hasWrite(box) ? { write: box.write.bind(box) } : {},
582
+ ...hasExec(box) ? {
583
+ async exec(command, options) {
584
+ return execResultFromSandboxExecResult(await box.exec(command, options));
585
+ }
586
+ } : {},
587
+ ...hasCheckpoint(box) ? {
588
+ async checkpoint(options) {
589
+ const result = await box.checkpoint(options);
590
+ return { id: checkpointIdFromResult(result), provider: providerName };
591
+ }
592
+ } : {},
593
+ ...hasFork(box) ? {
594
+ async fork(checkpoint, options) {
595
+ const forked = await box.fork(checkpoint.id, options);
596
+ return sandboxInstanceAsEnvironment(forked, providerName, client);
597
+ }
598
+ } : {},
599
+ async placement() {
600
+ return placementInfoFromLoopPlacement(client.describePlacement?.(box), box);
601
+ },
602
+ async refresh() {
603
+ await maybeRefresh(box);
604
+ },
605
+ async destroy() {
606
+ await destroyBox(box);
607
+ }
608
+ };
609
+ return environment;
610
+ }
611
+ function sandboxSessionAsAgentSession(session) {
612
+ return {
613
+ id: session.id,
614
+ async status() {
615
+ const status = await session.status();
616
+ if (!status) return null;
617
+ return sessionStatusFromUnknown(status.status);
618
+ },
619
+ async *events(options) {
620
+ for await (const event of session.events(options))
621
+ yield environmentEventFromSandboxEvent(event);
622
+ },
623
+ async result() {
624
+ return agentTurnResultFromPromptResult(await session.result());
625
+ },
626
+ async prompt(input) {
627
+ return agentTurnResultFromPromptResult(
628
+ await session.prompt(promptFromTurnInput(input), promptOptionsFromTurnInput(input))
629
+ );
630
+ },
631
+ cancel() {
632
+ return session.cancel();
633
+ }
634
+ };
635
+ }
636
+ function sessionAsSandboxSession(session) {
637
+ if (!session) throw new ValidationError("providerAsSandboxClient: session(id) returned undefined");
638
+ return {
639
+ id: session.id,
640
+ status: session.status.bind(session),
641
+ async *events(options) {
642
+ for await (const event of session.events(options))
643
+ yield sandboxEventFromEnvironmentEvent(event);
644
+ },
645
+ async result() {
646
+ return promptResultFromAgentTurnResult(await session.result());
647
+ },
648
+ async prompt(message, options) {
649
+ return promptResultFromAgentTurnResult(
650
+ await session.prompt(turnInputFromPrompt(message, options))
651
+ );
652
+ },
653
+ cancel: session.cancel.bind(session)
654
+ };
655
+ }
656
+ function environmentEventFromSandboxEvent(event) {
657
+ const data = event.data && typeof event.data === "object" ? event.data : {};
658
+ return {
659
+ type: String(event.type),
660
+ data,
661
+ ...event.id ? { id: event.id } : {},
662
+ usage: tokenUsageFromData(data),
663
+ providerEvent: event
664
+ };
665
+ }
666
+ function sandboxEventFromEnvironmentEvent(event) {
667
+ return {
668
+ type: event.type,
669
+ data: {
670
+ ...event.data,
671
+ ...event.usage ? { usage: tokenUsageData(event.usage) } : {}
672
+ },
673
+ ...event.id ? { id: event.id } : {}
674
+ };
675
+ }
676
+ function usageSandboxEvent(event) {
677
+ if (!event.usage || isUsageType(event.type)) return void 0;
678
+ const usage = tokenUsageData(event.usage);
679
+ if (usage.inputTokens === void 0 && usage.outputTokens === void 0 && usage.totalCostUsd === void 0) {
680
+ return void 0;
681
+ }
682
+ return { type: "llm_call", data: usage };
683
+ }
684
+ function tokenUsageData(usage) {
685
+ return {
686
+ inputTokens: usage.inputTokens,
687
+ outputTokens: usage.outputTokens,
688
+ totalCostUsd: usage.cost
689
+ };
690
+ }
691
+ function turnInputFromPrompt(message, options) {
692
+ return {
693
+ ...typeof message === "string" ? { prompt: message } : { parts: message },
694
+ ...options?.sessionId ? { sessionId: options.sessionId } : {},
695
+ ...options?.model ? { model: options.model } : {},
696
+ ...options?.timeoutMs ? { timeoutMs: options.timeoutMs } : {},
697
+ ...options?.executionId ? { executionId: options.executionId } : {},
698
+ ...options?.lastEventId ? { lastEventId: options.lastEventId } : {},
699
+ ...options?.turnId ? { turnId: options.turnId } : {},
700
+ ...options?.detach !== void 0 ? { detach: options.detach } : {},
701
+ ...options?.context ? { context: options.context } : {},
702
+ ...options?.signal ? { signal: options.signal } : {},
703
+ ...options?.backend ? { providerOptions: { backend: options.backend } } : {}
704
+ };
705
+ }
706
+ function promptFromTurnInput(input) {
707
+ if (input.parts) return input.parts;
708
+ return input.prompt ?? "";
709
+ }
710
+ function promptOptionsFromTurnInput(input) {
711
+ return {
712
+ ...input.sessionId ? { sessionId: input.sessionId } : {},
713
+ ...input.model ? { model: input.model } : {},
714
+ ...input.timeoutMs ? { timeoutMs: input.timeoutMs } : {},
715
+ ...input.context ? { context: input.context } : {},
716
+ ...input.signal ? { signal: input.signal } : {},
717
+ ...input.executionId ? { executionId: input.executionId } : {},
718
+ ...input.lastEventId ? { lastEventId: input.lastEventId } : {},
719
+ ...input.turnId ? { turnId: input.turnId } : {},
720
+ ...input.detach !== void 0 ? { detach: input.detach } : {}
721
+ };
722
+ }
723
+ function taskToTurnInput(task, signal) {
724
+ return { prompt: taskToPrompt(task), signal };
725
+ }
726
+ function taskToPrompt(task) {
727
+ if (typeof task === "string") return task;
728
+ if (task && typeof task === "object") {
729
+ const record = task;
730
+ for (const key of ["prompt", "content", "task", "message"]) {
731
+ if (typeof record[key] === "string") return record[key];
732
+ }
733
+ }
734
+ return JSON.stringify(task);
735
+ }
736
+ function resultFromEvents(events, fallbackText) {
737
+ for (let i = events.length - 1; i >= 0; i -= 1) {
738
+ const event = events[i];
739
+ const text = event ? resultTextFromData(event.data) : void 0;
740
+ if (text !== void 0) return { content: text, events };
741
+ }
742
+ return { content: fallbackText, events };
743
+ }
744
+ function textFromEnvironmentEvent(event) {
745
+ if (typeof event.normalized === "object" && event.normalized && event.normalized.type === "message.part.updated") {
746
+ return typeof event.normalized.delta === "string" ? event.normalized.delta : "";
747
+ }
748
+ const data = event.data;
749
+ for (const key of ["delta", "chunk", "content", "text"]) {
750
+ if (typeof data[key] === "string" && !isTerminalEnvironmentEvent(event)) return data[key];
751
+ }
752
+ return "";
753
+ }
754
+ function resultTextFromData(data) {
755
+ for (const key of ["finalText", "text", "response", "resultSummary", "content"]) {
756
+ if (typeof data[key] === "string") return data[key];
757
+ }
758
+ return void 0;
759
+ }
760
+ function isTerminalEnvironmentEvent(event) {
761
+ if (event.type === "result" || event.type === "done" || event.type === "final") return true;
762
+ if (event.type.endsWith(".completed") || event.type.endsWith(".failed")) return true;
763
+ if (event.type === "status") {
764
+ const status = event.data.status;
765
+ return status === "completed" || status === "failed" || status === "cancelled";
766
+ }
767
+ return false;
768
+ }
769
+ function isUsageType(type) {
770
+ return type === "llm_call" || type === "usage" || type === "cost.usage";
771
+ }
772
+ function usageFromEnvironmentEvent(event) {
773
+ const usage = event.usage ?? tokenUsageFromData(event.data);
774
+ return {
775
+ input: finiteNumber(usage?.inputTokens) ?? 0,
776
+ output: finiteNumber(usage?.outputTokens) ?? 0,
777
+ usd: finiteNumber(usage?.cost) ?? finiteNumber(event.data.costUsd) ?? finiteNumber(event.data.totalCostUsd) ?? 0
778
+ };
779
+ }
780
+ function tokenUsageFromData(data) {
781
+ const usageRecord = data.usage && typeof data.usage === "object" ? data.usage : data.tokenUsage && typeof data.tokenUsage === "object" ? data.tokenUsage : data;
782
+ const inputTokens = finiteNumber(usageRecord.inputTokens) ?? finiteNumber(usageRecord.tokensIn) ?? finiteNumber(usageRecord.prompt_tokens);
783
+ const outputTokens = finiteNumber(usageRecord.outputTokens) ?? finiteNumber(usageRecord.tokensOut) ?? finiteNumber(usageRecord.completion_tokens);
784
+ const cost = finiteNumber(usageRecord.cost) ?? finiteNumber(usageRecord.costUsd) ?? finiteNumber(usageRecord.totalCostUsd) ?? finiteNumber(data.costUsd) ?? finiteNumber(data.totalCostUsd);
785
+ if (inputTokens === void 0 && outputTokens === void 0 && cost === void 0)
786
+ return void 0;
787
+ return {
788
+ inputTokens: inputTokens ?? 0,
789
+ outputTokens: outputTokens ?? 0,
790
+ ...cost !== void 0 ? { cost } : {}
791
+ };
792
+ }
793
+ function mergeTokenUsage(left, right) {
794
+ if (!left) return right;
795
+ if (!right) return left;
796
+ return {
797
+ inputTokens: left.inputTokens + right.inputTokens,
798
+ outputTokens: left.outputTokens + right.outputTokens,
799
+ ...left.cost !== void 0 || right.cost !== void 0 ? { cost: (left.cost ?? 0) + (right.cost ?? 0) } : {}
800
+ };
801
+ }
802
+ function finiteNumber(value) {
803
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
804
+ }
805
+ function promptResultFromAgentTurnResult(result) {
806
+ return {
807
+ response: result.text,
808
+ success: result.success,
809
+ durationMs: 0,
810
+ ...result.error ? { error: result.error } : {},
811
+ ...result.usage ? { usage: result.usage } : {}
812
+ };
813
+ }
814
+ function agentTurnResultFromPromptResult(result) {
815
+ const record = result;
816
+ const text = typeof record.response === "string" ? record.response : typeof record.text === "string" ? record.text : typeof record.finalText === "string" ? record.finalText : "";
817
+ const success = typeof record.success === "boolean" ? record.success : true;
818
+ return {
819
+ text,
820
+ success,
821
+ ...typeof record.error === "string" ? { error: record.error } : {},
822
+ usage: tokenUsageFromData(record)
823
+ };
824
+ }
825
+ function sandboxDispatchResultFromSessionRef(session) {
826
+ const hasStatus = session.metadata && Object.hasOwn(session.metadata, "status");
827
+ const status = hasStatus ? sessionStatusFromUnknown(session.metadata?.status) : "running";
828
+ return {
829
+ sessionId: session.id,
830
+ status,
831
+ alreadyExisted: session.metadata?.alreadyExisted === true
832
+ };
833
+ }
834
+ function sessionRefFromSandboxDispatch(dispatched, providerName) {
835
+ const record = dispatched && typeof dispatched === "object" ? dispatched : void 0;
836
+ const id = record?.sessionId ?? record?.id;
837
+ if (typeof id !== "string" || id.length === 0) {
838
+ throw new ValidationError("sandboxClientAsProvider: dispatch returned no session id");
839
+ }
840
+ if (!record) {
841
+ throw new ValidationError("sandboxClientAsProvider: dispatch returned no session record");
842
+ }
843
+ return {
844
+ id,
845
+ provider: providerName,
846
+ metadata: {
847
+ ...record.status ? { status: record.status } : {},
848
+ ...record.alreadyExisted !== void 0 ? { alreadyExisted: record.alreadyExisted } : {}
849
+ }
850
+ };
851
+ }
852
+ function execResultFromSandboxExecResult(result) {
853
+ const record = result;
854
+ const exitCode = finiteNumber(record.exitCode) ?? finiteNumber(record.code);
855
+ if (exitCode === void 0) {
856
+ throw new ValidationError("sandboxClientAsProvider: exec returned no exit code");
857
+ }
858
+ return {
859
+ exitCode,
860
+ stdout: typeof record.stdout === "string" ? record.stdout : "",
861
+ stderr: typeof record.stderr === "string" ? record.stderr : ""
862
+ };
863
+ }
864
+ function statusFromUnknown(status) {
865
+ if (status === "pending" || status === "provisioning" || status === "running") return status;
866
+ if (status === "stopped" || status === "failed" || status === "expired") return status;
867
+ if (status === "completed") return "stopped";
868
+ if (status === "cancelled") return "stopped";
869
+ return "unknown";
870
+ }
871
+ function sessionStatusFromUnknown(status) {
872
+ if (status === "completed" || status === "cancelled") return status;
873
+ return statusFromUnknown(status);
874
+ }
875
+ function readBoxStatus(box) {
876
+ return box.status;
877
+ }
878
+ function readBoxMetadata(box) {
879
+ const metadata = box.metadata;
880
+ return metadata && typeof metadata === "object" ? metadata : void 0;
881
+ }
882
+ async function maybeRefresh(box) {
883
+ const refresh = box.refresh;
884
+ if (typeof refresh === "function") await refresh.call(box);
885
+ }
886
+ async function destroyBox(box) {
887
+ const deleteBox = box.delete;
888
+ if (typeof deleteBox === "function") await deleteBox.call(box);
889
+ }
890
+ function placementInfoFromLoopPlacement(placement, box) {
891
+ if (!placement) return { kind: "sandbox", sandboxId: String(box.id) };
892
+ return {
893
+ kind: placement.kind === "fleet" ? "fleet" : "sandbox",
894
+ ...placement.sandboxId ? { sandboxId: placement.sandboxId } : { sandboxId: String(box.id) },
895
+ ...placement.fleetId ? { fleetId: placement.fleetId } : {},
896
+ ...placement.machineId ? { machineId: placement.machineId } : {}
897
+ };
898
+ }
899
+ function checkpointIdFromResult(result) {
900
+ const record = result && typeof result === "object" ? result : {};
901
+ const id = record.checkpointId ?? record.id;
902
+ if (typeof id !== "string" || id.length === 0) {
903
+ throw new ValidationError("sandboxClientAsProvider: checkpoint returned no checkpoint id");
904
+ }
905
+ return id;
906
+ }
907
+ function defaultTangleSandboxCapabilities() {
908
+ return {
909
+ profile: {
910
+ namedProfiles: true,
911
+ systemPrompt: true,
912
+ instructions: true,
913
+ tools: true,
914
+ permissions: true,
915
+ mcp: true,
916
+ subagents: true,
917
+ resources: {
918
+ files: true,
919
+ instructions: true,
920
+ tools: true,
921
+ skills: true,
922
+ agents: true,
923
+ commands: true
924
+ },
925
+ hooks: true,
926
+ modes: true,
927
+ runtimeUpdate: true,
928
+ validation: true
929
+ },
930
+ streaming: { live: true, replay: true, detach: true, turnIdempotency: true },
931
+ sessions: { continue: true, list: true, messages: true },
932
+ workspace: { read: true, write: true, exec: true, git: true, upload: true, download: true },
933
+ branching: { checkpoint: true, fork: true },
934
+ placement: true,
935
+ usage: true,
936
+ confidential: true
937
+ };
938
+ }
939
+ function mergeAbortSignals(a, b) {
940
+ const controller = new AbortController();
941
+ const abort = () => controller.abort();
942
+ if (a.aborted || b.aborted) controller.abort();
943
+ else {
944
+ a.addEventListener("abort", abort, { once: true });
945
+ b.addEventListener("abort", abort, { once: true });
946
+ }
947
+ return controller.signal;
948
+ }
949
+ function contentRef(prefix, value) {
950
+ let str;
951
+ try {
952
+ str = JSON.stringify(value) ?? String(value);
953
+ } catch {
954
+ str = String(value);
955
+ }
956
+ let hash = 2166136261;
957
+ for (let i = 0; i < str.length; i += 1) {
958
+ hash ^= str.charCodeAt(i);
959
+ hash = Math.imul(hash, 16777619);
960
+ }
961
+ return `${prefix}:${(hash >>> 0).toString(16).padStart(8, "0")}`;
962
+ }
963
+ function hasGet(client) {
964
+ return typeof client.get === "function";
965
+ }
966
+ function hasList(client) {
967
+ return typeof client.list === "function";
968
+ }
969
+ function hasDispatchPrompt(box) {
970
+ return typeof box.dispatchPrompt === "function";
971
+ }
972
+ function hasSession(box) {
973
+ return typeof box.session === "function";
974
+ }
975
+ function hasRead(box) {
976
+ return typeof box.read === "function";
977
+ }
978
+ function hasWrite(box) {
979
+ return typeof box.write === "function";
980
+ }
981
+ function hasExec(box) {
982
+ return typeof box.exec === "function";
983
+ }
984
+ function hasCheckpoint(box) {
985
+ return typeof box.checkpoint === "function";
986
+ }
987
+ function hasFork(box) {
988
+ return typeof box.fork === "function";
989
+ }
990
+
211
991
  // src/runtime-hooks.ts
212
992
  function defineRuntimeHooks(hooks) {
213
993
  return hooks;
@@ -930,6 +1710,20 @@ async function executeIteration(args) {
930
1710
  const events = [];
931
1711
  for await (const event of stream) {
932
1712
  events.push(event);
1713
+ if (args.ctx.onSandboxEvent) {
1714
+ try {
1715
+ const observerEvent = cloneEventForObserver(event);
1716
+ const result = args.ctx.onSandboxEvent(observerEvent, {
1717
+ iterationIndex: args.item.index,
1718
+ agentRunName: slot.agentRunName
1719
+ });
1720
+ if (result && typeof result.then === "function") {
1721
+ void result.then(void 0, () => {
1722
+ });
1723
+ }
1724
+ } catch {
1725
+ }
1726
+ }
933
1727
  const llmCall = extractLlmCallEvent(event, slot.agentRunName);
934
1728
  if (llmCall) {
935
1729
  slot.costUsd += llmCall.costUsd ?? 0;
@@ -1206,6 +2000,30 @@ async function emitTrace(emitter, event) {
1206
2000
  if (!emitter) return;
1207
2001
  await emitter.emit(event);
1208
2002
  }
2003
+ function cloneEventForObserver(event) {
2004
+ try {
2005
+ return structuredClone(event);
2006
+ } catch {
2007
+ return copyPlainSpine(event, /* @__PURE__ */ new WeakMap());
2008
+ }
2009
+ }
2010
+ function copyPlainSpine(value, seen) {
2011
+ if (value === null || typeof value !== "object") return value;
2012
+ const existing = seen.get(value);
2013
+ if (existing !== void 0) return existing;
2014
+ if (Array.isArray(value)) {
2015
+ const copy2 = [];
2016
+ seen.set(value, copy2);
2017
+ for (const item of value) copy2.push(copyPlainSpine(item, seen));
2018
+ return copy2;
2019
+ }
2020
+ const proto = Object.getPrototypeOf(value);
2021
+ if (proto !== Object.prototype && proto !== null) return {};
2022
+ const copy = {};
2023
+ seen.set(value, copy);
2024
+ for (const [key, v] of Object.entries(value)) copy[key] = copyPlainSpine(v, seen);
2025
+ return copy;
2026
+ }
1209
2027
  function hashJson(value) {
1210
2028
  let str;
1211
2029
  try {
@@ -2169,7 +2987,8 @@ var sandboxSeamKey = "sandbox";
2169
2987
  var cliSeamKey = "cli";
2170
2988
  var bridgeSeamKey = "bridge";
2171
2989
  var cliWorktreeSeamKey = "cli-worktree";
2172
- function contentRef(prefix, value) {
2990
+ var providerSeamKey = "provider";
2991
+ function contentRef2(prefix, value) {
2173
2992
  let str;
2174
2993
  try {
2175
2994
  str = JSON.stringify(value) ?? String(value);
@@ -2222,7 +3041,7 @@ var routerInlineExecutor = (spec, ctx) => {
2222
3041
  ms: Date.now() - started
2223
3042
  };
2224
3043
  const out = { content: r.content };
2225
- artifact = { outRef: contentRef("router", { model, content: r.content }), out, spent };
3044
+ artifact = { outRef: contentRef2("router", { model, content: r.content }), out, spent };
2226
3045
  return artifact;
2227
3046
  },
2228
3047
  teardown(_grace) {
@@ -2276,7 +3095,7 @@ var routerToolsInlineExecutor = (spec, ctx) => {
2276
3095
  if (pending.length) messages.push({ role: "user", content: inbox.fold(pending) });
2277
3096
  return pending.length > 0;
2278
3097
  };
2279
- const external = mergeAbortSignals(signal, controller.signal);
3098
+ const external = mergeAbortSignals2(signal, controller.signal);
2280
3099
  for (let t = 0; t < maxTurns; t += 1) {
2281
3100
  flush();
2282
3101
  const interruptSig = inbox.freshInterrupt();
@@ -2380,7 +3199,7 @@ var routerToolsInlineExecutor = (spec, ctx) => {
2380
3199
  const usd = isModelPriced2(model) ? estimateCost2(tokens.input, tokens.output, model) : 0;
2381
3200
  const spent = { iterations: turns, tokens, usd, ms: Date.now() - started };
2382
3201
  const out = { content: lastText };
2383
- artifact = { outRef: contentRef("router-tools", { model, content: lastText }), out, spent };
3202
+ artifact = { outRef: contentRef2("router-tools", { model, content: lastText }), out, spent };
2384
3203
  return artifact;
2385
3204
  },
2386
3205
  teardown(_grace) {
@@ -2464,7 +3283,7 @@ async function* streamSandboxLeaf(args) {
2464
3283
  }
2465
3284
  const agentRun = {
2466
3285
  profile: args.spec.profile,
2467
- taskToPrompt: (t) => taskToPrompt(t),
3286
+ taskToPrompt: (t) => taskToPrompt2(t),
2468
3287
  name: args.spec.profile.name ?? args.harness,
2469
3288
  sandboxOverrides: { backend: { type: args.harness } }
2470
3289
  };
@@ -2494,7 +3313,7 @@ async function* streamSandboxLeaf(args) {
2494
3313
  ms: Date.now() - started
2495
3314
  };
2496
3315
  args.onArtifact({
2497
- outRef: contentRef("sandbox", { harness: args.harness, out }),
3316
+ outRef: contentRef2("sandbox", { harness: args.harness, out }),
2498
3317
  out,
2499
3318
  ...verdict ? { verdict } : {},
2500
3319
  spent
@@ -2551,7 +3370,7 @@ var cliExecutor = (_spec, ctx) => {
2551
3370
  };
2552
3371
  };
2553
3372
  async function* streamCliLeaf(args) {
2554
- const prompt = taskToPrompt(args.task);
3373
+ const prompt = taskToPrompt2(args.task);
2555
3374
  const proc = spawn3(args.seam.bin, args.seam.args ?? [], {
2556
3375
  ...args.seam.cwd ? { cwd: args.seam.cwd } : {},
2557
3376
  env: { ...process.env, ...args.seam.env ?? {} },
@@ -2589,7 +3408,7 @@ async function* streamCliLeaf(args) {
2589
3408
  );
2590
3409
  }
2591
3410
  const out = { content: chunks.join("") };
2592
- args.onArtifact({ outRef: contentRef("cli", out), out, spent: zeroSpend2() });
3411
+ args.onArtifact({ outRef: contentRef2("cli", out), out, spent: zeroSpend2() });
2593
3412
  yield { kind: "iteration" };
2594
3413
  }
2595
3414
  function killWithGrace(proc, grace) {
@@ -2662,13 +3481,13 @@ async function* streamBridgeSession(args) {
2662
3481
  const { seam, inbox } = args;
2663
3482
  const started = Date.now();
2664
3483
  const url = `${seam.bridgeUrl.replace(/\/$/, "")}/v1/chat/completions`;
2665
- const external = mergeAbortSignals(args.signal, args.controller.signal);
3484
+ const external = mergeAbortSignals2(args.signal, args.controller.signal);
2666
3485
  const tokens = zeroTokenUsage();
2667
3486
  let usd = 0;
2668
3487
  let turns = 0;
2669
3488
  let lastText = "";
2670
3489
  const toolCalls = [];
2671
- let nextPrompt = taskToPrompt(args.task);
3490
+ let nextPrompt = taskToPrompt2(args.task);
2672
3491
  const system = args.spec.profile.prompt?.systemPrompt;
2673
3492
  for (let t = 0; t < args.maxTurns; t += 1) {
2674
3493
  const pending = inbox.drain();
@@ -2763,7 +3582,7 @@ ${folded}` : folded;
2763
3582
  };
2764
3583
  const out = { content: lastText, toolCalls };
2765
3584
  args.onArtifact({
2766
- outRef: contentRef("bridge", { model: seam.model, session: args.sessionId, content: lastText }),
3585
+ outRef: contentRef2("bridge", { model: seam.model, session: args.sessionId, content: lastText }),
2767
3586
  out,
2768
3587
  spent
2769
3588
  });
@@ -2857,6 +3676,14 @@ function createExecutor(config) {
2857
3676
  return cliExecutor(spec, seamed);
2858
3677
  case "cli-worktree":
2859
3678
  return cliWorktreeExecutor(spec, seamed);
3679
+ case "provider": {
3680
+ const providerSeam = readSeam(seamed, providerSeamKey, "provider");
3681
+ const provider = resolveAgentEnvironmentProvider(
3682
+ providerSeam.provider,
3683
+ providerSeam.registry
3684
+ );
3685
+ return providerAsExecutor(provider, providerSeam)(spec, seamed);
3686
+ }
2860
3687
  case "sandbox": {
2861
3688
  const harness = spec.harness ?? config.harness ?? null;
2862
3689
  return sandboxExecutor({ ...spec, harness }, seamed);
@@ -2906,7 +3733,7 @@ function readSeam(ctx, key, who) {
2906
3733
  }
2907
3734
  return seam;
2908
3735
  }
2909
- function taskToPrompt(task) {
3736
+ function taskToPrompt2(task) {
2910
3737
  if (typeof task === "string") return task;
2911
3738
  if (task && typeof task === "object") {
2912
3739
  const obj = task;
@@ -2922,7 +3749,7 @@ function taskToMessages(task, spec) {
2922
3749
  if (typeof system === "string" && system.length > 0) {
2923
3750
  messages.push({ role: "system", content: system });
2924
3751
  }
2925
- messages.push({ role: "user", content: taskToPrompt(task) });
3752
+ messages.push({ role: "user", content: taskToPrompt2(task) });
2926
3753
  return messages;
2927
3754
  }
2928
3755
  function singleShotDriver(maxIterations) {
@@ -2948,7 +3775,7 @@ function linkSignals2(a, b) {
2948
3775
  b.addEventListener("abort", onAbort, { once: true });
2949
3776
  return c.signal;
2950
3777
  }
2951
- function mergeAbortSignals(...signals) {
3778
+ function mergeAbortSignals2(...signals) {
2952
3779
  const c = new AbortController();
2953
3780
  const onAbort = () => c.abort();
2954
3781
  for (const s of signals) {
@@ -4461,7 +5288,7 @@ var DelegationTaskQueue = class _DelegationTaskQueue {
4461
5288
  static async restore(options = {}) {
4462
5289
  const queue = new _DelegationTaskQueue(options);
4463
5290
  const loaded = await queue.store.loadAll();
4464
- queue.rehydrate(loaded);
5291
+ await queue.rehydrate(loaded);
4465
5292
  return queue;
4466
5293
  }
4467
5294
  /**
@@ -4643,17 +5470,18 @@ var DelegationTaskQueue = class _DelegationTaskQueue {
4643
5470
  record.trace = trace;
4644
5471
  if (truncated) record.traceTruncated = true;
4645
5472
  }
4646
- rehydrate(loaded) {
5473
+ async rehydrate(loaded) {
4647
5474
  const records = [...loaded].sort((a, b) => a.startedAt.localeCompare(b.startedAt));
4648
5475
  for (const record of records) {
4649
5476
  this.records.set(record.taskId, record);
4650
5477
  if (record.idempotencyKey) this.byIdempotencyKey.set(record.idempotencyKey, record.taskId);
4651
5478
  }
5479
+ const restoreWrites = [];
4652
5480
  for (const record of this.records.values()) {
4653
5481
  if (isTerminal(record.status)) continue;
4654
5482
  if (record.detachedSessionRef && this.resumeDelegate) {
4655
5483
  record.status = "running";
4656
- this.persist(record);
5484
+ restoreWrites.push(this.persist(record));
4657
5485
  this.startResume(record, record.detachedSessionRef, this.resumeDelegate);
4658
5486
  continue;
4659
5487
  }
@@ -4663,9 +5491,12 @@ var DelegationTaskQueue = class _DelegationTaskQueue {
4663
5491
  message: record.detachedSessionRef ? `delegation driver restarted while the task was in flight; detached session "${record.detachedSessionRef}" needs a resumeDelegate to be resumed` : "delegation driver restarted while the task was in flight; the run was not detached and cannot be resumed",
4664
5492
  kind: "DriverRestartError"
4665
5493
  };
4666
- this.persist(record);
5494
+ restoreWrites.push(this.persist(record));
4667
5495
  }
4668
- this.enforceRetention();
5496
+ const retentionWrite = this.enforceRetention();
5497
+ if (retentionWrite) restoreWrites.push(retentionWrite);
5498
+ await Promise.all(restoreWrites);
5499
+ if (this.persistFailure) throw this.persistFailure;
4669
5500
  }
4670
5501
  startResume(record, detachedSessionRef, driver) {
4671
5502
  const controller = new AbortController();
@@ -4748,7 +5579,7 @@ var DelegationTaskQueue = class _DelegationTaskQueue {
4748
5579
  ]);
4749
5580
  }
4750
5581
  persist(record) {
4751
- if (this.persistFailure) return;
5582
+ if (this.persistFailure) return Promise.resolve();
4752
5583
  const snapshot = structuredClone(record);
4753
5584
  this.persistTail = this.persistTail.then(async () => {
4754
5585
  if (this.persistFailure) return;
@@ -4758,9 +5589,10 @@ var DelegationTaskQueue = class _DelegationTaskQueue {
4758
5589
  this.failPersistence(err);
4759
5590
  }
4760
5591
  });
5592
+ return this.persistTail;
4761
5593
  }
4762
5594
  persistRemoval(taskIds) {
4763
- if (this.persistFailure || taskIds.length === 0) return;
5595
+ if (this.persistFailure || taskIds.length === 0) return void 0;
4764
5596
  this.persistTail = this.persistTail.then(async () => {
4765
5597
  if (this.persistFailure) return;
4766
5598
  try {
@@ -4769,6 +5601,7 @@ var DelegationTaskQueue = class _DelegationTaskQueue {
4769
5601
  this.failPersistence(err);
4770
5602
  }
4771
5603
  });
5604
+ return this.persistTail;
4772
5605
  }
4773
5606
  failPersistence(cause) {
4774
5607
  if (this.persistFailure) return;
@@ -4780,13 +5613,13 @@ var DelegationTaskQueue = class _DelegationTaskQueue {
4780
5613
  this.onPersistError(error);
4781
5614
  }
4782
5615
  enforceRetention() {
4783
- if (!Number.isFinite(this.maxTerminalRecords)) return;
5616
+ if (!Number.isFinite(this.maxTerminalRecords)) return void 0;
4784
5617
  const terminal = [];
4785
5618
  for (const record of this.records.values()) {
4786
5619
  if (isTerminal(record.status)) terminal.push(record);
4787
5620
  }
4788
5621
  const excess = terminal.length - this.maxTerminalRecords;
4789
- if (excess <= 0) return;
5622
+ if (excess <= 0) return void 0;
4790
5623
  terminal.sort(
4791
5624
  (a, b) => (a.completedAt ?? a.startedAt).localeCompare(b.completedAt ?? b.startedAt)
4792
5625
  );
@@ -4797,7 +5630,7 @@ var DelegationTaskQueue = class _DelegationTaskQueue {
4797
5630
  this.byIdempotencyKey.delete(record.idempotencyKey);
4798
5631
  }
4799
5632
  }
4800
- this.persistRemoval(evicted.map((record) => record.taskId));
5633
+ return this.persistRemoval(evicted.map((record) => record.taskId));
4801
5634
  }
4802
5635
  };
4803
5636
  function isTerminal(status) {
@@ -5277,7 +6110,7 @@ var DELEGATE_FEEDBACK_DESCRIPTION = [
5277
6110
  "on the same target are expected and never deduped.",
5278
6111
  "",
5279
6112
  "`refersTo.kind`:",
5280
- ' - "delegation": ref is a taskId returned by delegate_code/delegate_research',
6113
+ ' - "delegation": ref is a taskId returned by delegate_ui_audit',
5281
6114
  ' - "artifact": ref is a URI/path/git-sha \u2014 anything you can dereference',
5282
6115
  ' - "outcome": ref is a free-form description of a downstream result',
5283
6116
  "",
@@ -5749,13 +6582,13 @@ var DELEGATION_STATUS_DESCRIPTION = [
5749
6582
  "(pending | running | completed | failed | cancelled), optional progress,",
5750
6583
  'and the final result when status === "completed".',
5751
6584
  "",
5752
- "Use when: you previously called delegate_code or delegate_research and",
5753
- "need to know whether the work is done. The agent's right rhythm is to",
6585
+ "Use when: you previously kicked off an async delegation (delegate_ui_audit)",
6586
+ "and need to know whether the work is done. The agent's right rhythm is to",
5754
6587
  "call this every minute or two while waiting; do not busy-poll.",
5755
6588
  "",
5756
- "For a completed coder task, `result.output` is a CoderOutput with branch,",
5757
- "patch, test/typecheck results, and diff stats. For a completed research",
5758
- "task, `result.output` is the items + citations + proposedWrites bundle.",
6589
+ "For a completed delegate_ui_audit run, `result.output` is the array of UI",
6590
+ "findings \u2014 one self-contained Markdown finding per issue, each with an",
6591
+ "embedded screenshot and a suggested fix.",
5759
6592
  "",
5760
6593
  "Pass includeTrace: true to also receive the journaled loop-trace span",
5761
6594
  "tree (loop \u2192 round \u2192 iteration, with placement/cost/verdict metadata).",
@@ -5767,7 +6600,7 @@ var DELEGATION_STATUS_DESCRIPTION = [
5767
6600
  var DELEGATION_STATUS_INPUT_SCHEMA = {
5768
6601
  type: "object",
5769
6602
  properties: {
5770
- taskId: { type: "string", description: "Returned by delegate_code / delegate_research." },
6603
+ taskId: { type: "string", description: "Returned by delegate_ui_audit." },
5771
6604
  includeTrace: {
5772
6605
  type: "boolean",
5773
6606
  description: "Also return the journaled loop-trace span tree for this delegation. Default false."
@@ -6142,6 +6975,11 @@ export {
6142
6975
  contentAddress,
6143
6976
  InMemoryResultBlobStore,
6144
6977
  InMemorySpawnJournal,
6978
+ createAgentEnvironmentProviderRegistry,
6979
+ resolveAgentEnvironmentProvider,
6980
+ providerAsSandboxClient,
6981
+ sandboxClientAsProvider,
6982
+ providerAsExecutor,
6145
6983
  defineRuntimeHooks,
6146
6984
  composeRuntimeHooks,
6147
6985
  notifyRuntimeHookEvent,
@@ -6231,4 +7069,4 @@ export {
6231
7069
  createInProcessTransport,
6232
7070
  serveCoordinationMcp
6233
7071
  };
6234
- //# sourceMappingURL=chunk-RQYPH2QE.js.map
7072
+ //# sourceMappingURL=chunk-EZ2QESTP.js.map