@tangle-network/agent-runtime 0.45.0 → 0.46.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 (63) hide show
  1. package/README.md +3 -3
  2. package/dist/agent.d.ts +5 -5
  3. package/dist/agent.js +2 -2
  4. package/dist/agent.js.map +1 -1
  5. package/dist/analyst-loop.d.ts +5 -40
  6. package/dist/analyst-loop.js +2 -4
  7. package/dist/{chunk-KEWO4KI6.js → chunk-65FQLI4V.js} +628 -138
  8. package/dist/chunk-65FQLI4V.js.map +1 -0
  9. package/dist/{chunk-NYN5RTLP.js → chunk-GN75RGM6.js} +7 -7
  10. package/dist/chunk-GN75RGM6.js.map +1 -0
  11. package/dist/{chunk-PRX45WE2.js → chunk-GSUO5QS6.js} +1 -119
  12. package/dist/chunk-GSUO5QS6.js.map +1 -0
  13. package/dist/{chunk-FK53TXOP.js → chunk-HNUXAZIJ.js} +4 -27
  14. package/dist/chunk-HNUXAZIJ.js.map +1 -0
  15. package/dist/{chunk-IJ6FGOPO.js → chunk-I42NHLKX.js} +3 -3
  16. package/dist/chunk-I42NHLKX.js.map +1 -0
  17. package/dist/{chunk-IJGS6J7X.js → chunk-JNPK46YH.js} +2 -2
  18. package/dist/{chunk-QR4UUC5P.js → chunk-KADIJAD4.js} +33 -19
  19. package/dist/chunk-KADIJAD4.js.map +1 -0
  20. package/dist/{chunk-Z2QXVBA6.js → chunk-KPN7OQ64.js} +4 -4
  21. package/dist/chunk-KPN7OQ64.js.map +1 -0
  22. package/dist/{chunk-KSMX62JF.js → chunk-VR4JIC5H.js} +2 -2
  23. package/dist/{coder-CczgMqFx.d.ts → coder-DCWFQpmJ.d.ts} +1 -1
  24. package/dist/{dynamic-BvllHV6M.d.ts → driver-C-mtBo7h.d.ts} +6 -6
  25. package/dist/{improvement-adapter-CWegd3vw.d.ts → improvement-adapter-BC4HhuAR.d.ts} +1 -1
  26. package/dist/improvement.d.ts +2 -2
  27. package/dist/index.d.ts +8 -8
  28. package/dist/index.js +8 -8
  29. package/dist/{kb-gate-D9GBocLN.d.ts → kb-gate-2Gwpz_27.d.ts} +7 -7
  30. package/dist/{loop-runner-bin-CPrCoKqC.d.ts → loop-runner-bin-D-K6bRp3.d.ts} +11 -11
  31. package/dist/loop-runner-bin.d.ts +6 -6
  32. package/dist/loop-runner-bin.js +6 -6
  33. package/dist/loops.d.ts +5 -5
  34. package/dist/loops.js +10 -10
  35. package/dist/mcp/bin.js +6 -6
  36. package/dist/mcp/bin.js.map +1 -1
  37. package/dist/mcp/index.d.ts +11 -11
  38. package/dist/mcp/index.js +7 -7
  39. package/dist/{otel-export-Dy2DyUCU.d.ts → otel-export-nurzFwuJ.d.ts} +1 -1
  40. package/dist/profiles.d.ts +8 -8
  41. package/dist/profiles.js +1 -1
  42. package/dist/profiles.js.map +1 -1
  43. package/dist/{run-loop--hSoIknW.d.ts → run-loop-CU2Y00Si.d.ts} +2 -2
  44. package/dist/runtime.d.ts +156 -52
  45. package/dist/runtime.js +10 -10
  46. package/dist/{types-1HbsFa7H.d.ts → types-BfoeiQRZ.d.ts} +20 -20
  47. package/dist/{types-DdzkffAm.d.ts → types-DnYoHvvZ.d.ts} +17 -5
  48. package/dist/{types-BtRLF2U3.d.ts → types-p8dWBIXL.d.ts} +1 -1
  49. package/dist/workflow.d.ts +3 -3
  50. package/dist/workflow.js +2 -2
  51. package/dist/workflow.js.map +1 -1
  52. package/package.json +13 -24
  53. package/skills/agent-runtime-adoption/SKILL.md +3 -3
  54. package/skills/generate-eval/SKILL.md +60 -0
  55. package/dist/chunk-FK53TXOP.js.map +0 -1
  56. package/dist/chunk-IJ6FGOPO.js.map +0 -1
  57. package/dist/chunk-KEWO4KI6.js.map +0 -1
  58. package/dist/chunk-NYN5RTLP.js.map +0 -1
  59. package/dist/chunk-PRX45WE2.js.map +0 -1
  60. package/dist/chunk-QR4UUC5P.js.map +0 -1
  61. package/dist/chunk-Z2QXVBA6.js.map +0 -1
  62. /package/dist/{chunk-IJGS6J7X.js.map → chunk-JNPK46YH.js.map} +0 -0
  63. /package/dist/{chunk-KSMX62JF.js.map → chunk-VR4JIC5H.js.map} +0 -0
@@ -3,22 +3,120 @@ import {
3
3
  PlannerError,
4
4
  RuntimeRunStateError,
5
5
  ValidationError,
6
- addTokenUsage,
7
- deleteBoxSafe,
8
- extractLlmCallEvent,
9
- mapWithConcurrency,
10
- randomSuffix,
11
- randomUuid,
12
- sleep,
13
- stringifySafe,
14
- throwAbort,
15
- throwIfAborted,
16
- withTimeout,
17
- zeroTokenUsage
18
- } from "./chunk-PRX45WE2.js";
6
+ extractLlmCallEvent
7
+ } from "./chunk-GSUO5QS6.js";
19
8
 
20
9
  // src/durable/spawn-journal.ts
21
10
  import { createHash } from "crypto";
11
+
12
+ // src/runtime/util.ts
13
+ async function deleteBoxSafe(box) {
14
+ if (!box || typeof box.delete !== "function") return true;
15
+ try {
16
+ await box.delete();
17
+ return true;
18
+ } catch {
19
+ return false;
20
+ }
21
+ }
22
+ function randomSuffix(len = 8) {
23
+ return Math.random().toString(36).slice(2, 2 + len);
24
+ }
25
+ function randomUuid() {
26
+ return crypto.randomUUID();
27
+ }
28
+ function abortError() {
29
+ const err = new Error("aborted");
30
+ err.name = "AbortError";
31
+ return err;
32
+ }
33
+ function throwAbort() {
34
+ throw abortError();
35
+ }
36
+ function throwIfAborted(signal) {
37
+ if (signal?.aborted) throw abortError();
38
+ }
39
+ function sleep(ms, signal) {
40
+ return new Promise((resolve) => {
41
+ if (signal?.aborted) {
42
+ resolve();
43
+ return;
44
+ }
45
+ let onAbort;
46
+ const timer = setTimeout(() => {
47
+ if (onAbort && signal) signal.removeEventListener("abort", onAbort);
48
+ resolve();
49
+ }, ms);
50
+ if (signal) {
51
+ onAbort = () => {
52
+ clearTimeout(timer);
53
+ resolve();
54
+ };
55
+ signal.addEventListener("abort", onAbort, { once: true });
56
+ }
57
+ });
58
+ }
59
+ function withTimeout(promise, ms) {
60
+ return new Promise((resolve) => {
61
+ const timer = setTimeout(() => resolve(void 0), ms);
62
+ promise.then(
63
+ (value) => {
64
+ clearTimeout(timer);
65
+ resolve(value);
66
+ },
67
+ () => {
68
+ clearTimeout(timer);
69
+ resolve(void 0);
70
+ }
71
+ );
72
+ });
73
+ }
74
+ function stringifySafe(value, opts = {}) {
75
+ let s;
76
+ try {
77
+ if (typeof value === "string") {
78
+ s = value;
79
+ } else {
80
+ const json = opts.pretty ? JSON.stringify(value, null, 2) : JSON.stringify(value);
81
+ s = json ?? String(value);
82
+ }
83
+ } catch {
84
+ s = String(value);
85
+ }
86
+ if (opts.max !== void 0 && s.length > opts.max) return `${s.slice(0, opts.max)}\u2026`;
87
+ return s;
88
+ }
89
+ function zeroTokenUsage() {
90
+ return { input: 0, output: 0 };
91
+ }
92
+ function addTokenUsage(acc, delta) {
93
+ acc.input += delta.input ?? 0;
94
+ acc.output += delta.output ?? 0;
95
+ }
96
+ async function mapWithConcurrency(items, limit, fn) {
97
+ const bound = Math.max(1, Math.floor(limit));
98
+ const results = new Array(items.length);
99
+ let next = 0;
100
+ let failed = false;
101
+ const worker = async () => {
102
+ while (!failed) {
103
+ const i = next;
104
+ next += 1;
105
+ if (i >= items.length) return;
106
+ try {
107
+ results[i] = await fn(items[i], i);
108
+ } catch (err) {
109
+ failed = true;
110
+ throw err;
111
+ }
112
+ }
113
+ };
114
+ const workerCount = Math.min(bound, items.length);
115
+ await Promise.all(Array.from({ length: workerCount }, () => worker()));
116
+ return results;
117
+ }
118
+
119
+ // src/durable/spawn-journal.ts
22
120
  function contentAddress(artifact) {
23
121
  const hex = createHash("sha256").update(stableStringify(artifact), "utf-8").digest("hex");
24
122
  return `sha256:${hex}`;
@@ -376,18 +474,100 @@ function deterministicCompletion(check) {
376
474
  };
377
475
  }
378
476
 
379
- // src/runtime/dynamic.ts
380
- function createDynamicDriver(options) {
477
+ // src/runtime/personify/analyst.ts
478
+ var judgeEvidenceUri = /^(verdict|judge|score)\b/i;
479
+ var assertTraceDerivedFindings = (findings) => {
480
+ for (const f of findings) {
481
+ for (const ref of f.evidence_refs ?? []) {
482
+ if (ref.kind === "metric" && judgeEvidenceUri.test(ref.uri)) {
483
+ throw new PlannerError(
484
+ `steer-firewall: finding ${stringifySafe(f.finding_id)} cites judge-derived evidence (${stringifySafe(ref.uri)}); findings fed to a combinator's steer decision must be trace-derived, not judge-derived (selector \u2260 judge)`
485
+ );
486
+ }
487
+ }
488
+ }
489
+ };
490
+ function createScopeAnalyst(scope, options) {
491
+ if (!options.analyst || typeof options.analyst.act !== "function") {
492
+ throw new AnalystError("createScopeAnalyst: analyst must be an Agent with an act() method");
493
+ }
494
+ const label = options.label ?? "analyst";
495
+ return {
496
+ async analyze(input) {
497
+ const task = options.buildTask(input);
498
+ const spawned = scope.spawn(options.analyst, task, {
499
+ budget: options.budget,
500
+ label
501
+ });
502
+ if (!spawned.ok) {
503
+ throw new AnalystError(
504
+ `createScopeAnalyst: analyst spawn refused by the conserved pool (${spawned.reason}); cannot steer node ${stringifySafe(input.nodeId)} on an unrun analyst`
505
+ );
506
+ }
507
+ const settled = await drainAnalystSettlement(scope, spawned.handle.id);
508
+ const findings = readAnalystFindings(settled);
509
+ assertTraceDerivedFindings(findings);
510
+ return findings;
511
+ }
512
+ };
513
+ }
514
+ async function drainAnalystSettlement(scope, analystId) {
515
+ for (; ; ) {
516
+ const settled = await scope.next();
517
+ if (settled === null) {
518
+ throw new AnalystError(
519
+ `createScopeAnalyst: scope drained before analyst ${stringifySafe(analystId)} settled`
520
+ );
521
+ }
522
+ if (settled.handle.id === analystId) return settled;
523
+ }
524
+ }
525
+ function readAnalystFindings(settled) {
526
+ if (settled.kind === "down") {
527
+ throw new AnalystError(
528
+ `createScopeAnalyst: analyst ${stringifySafe(settled.handle.id)} settled down (${settled.infra ? "infra" : "result"}): ${stringifySafe(settled.reason)}`
529
+ );
530
+ }
531
+ const out = settled.out;
532
+ if (!Array.isArray(out)) {
533
+ throw new PlannerError(
534
+ `createScopeAnalyst: analyst ${stringifySafe(settled.handle.id)} must return AnalystFinding[], got ${stringifySafe(out)}`
535
+ );
536
+ }
537
+ return out;
538
+ }
539
+ function buildSteerContext(findings, settledSoFar) {
540
+ assertTraceDerivedFindings(findings);
541
+ const lastValidScore = observedBestScore(settledSoFar);
542
+ return {
543
+ findings,
544
+ settledSoFar,
545
+ ...lastValidScore !== void 0 ? { lastValidScore } : {}
546
+ };
547
+ }
548
+ function observedBestScore(settledSoFar) {
549
+ let best;
550
+ for (const s of settledSoFar) {
551
+ if (s.kind !== "done") continue;
552
+ const v = s.verdict;
553
+ if (!v || v.valid !== true || typeof v.score !== "number") continue;
554
+ if (best === void 0 || v.score > best) best = v.score;
555
+ }
556
+ return best;
557
+ }
558
+
559
+ // src/runtime/driver.ts
560
+ function createDriver(options) {
381
561
  if (typeof options.planner !== "function") {
382
- throw new ValidationError("createDynamicDriver: planner must be a function");
562
+ throw new ValidationError("createDriver: planner must be a function");
383
563
  }
384
564
  const maxIterations = options.maxIterations ?? 8;
385
565
  if (!Number.isFinite(maxIterations) || maxIterations <= 0) {
386
- throw new ValidationError("createDynamicDriver: maxIterations must be > 0");
566
+ throw new ValidationError("createDriver: maxIterations must be > 0");
387
567
  }
388
568
  const maxFanout = options.maxFanout ?? 4;
389
569
  if (!Number.isFinite(maxFanout) || maxFanout < 1) {
390
- throw new ValidationError("createDynamicDriver: maxFanout must be >= 1");
570
+ throw new ValidationError("createDriver: maxFanout must be >= 1");
391
571
  }
392
572
  let pending;
393
573
  return {
@@ -498,7 +678,7 @@ async function runAnalyze(analyze, task, history) {
498
678
  const findings = await analyze({ task, history });
499
679
  if (!Array.isArray(findings)) {
500
680
  throw new PlannerError(
501
- `createDynamicDriver: analyze hook must return AnalystFinding[], got ${stringifySafe(findings)}`
681
+ `createDriver: analyze hook must return AnalystFinding[], got ${stringifySafe(findings)}`
502
682
  );
503
683
  }
504
684
  assertTraceDerivedFindings(findings);
@@ -508,23 +688,11 @@ async function runComplete(complete, task, history) {
508
688
  const verdict = await complete.assess({ task, history });
509
689
  if (!verdict || typeof verdict.done !== "boolean" || verdict.determinism !== "deterministic" && verdict.determinism !== "probabilistic") {
510
690
  throw new PlannerError(
511
- `createDynamicDriver: complete.assess must return a CompletionVerdict {done, determinism}, got ${stringifySafe(verdict)}`
691
+ `createDriver: complete.assess must return a CompletionVerdict {done, determinism}, got ${stringifySafe(verdict)}`
512
692
  );
513
693
  }
514
694
  return verdict;
515
695
  }
516
- var JUDGE_EVIDENCE_URI = /^(verdict|judge|score)\b/i;
517
- function assertTraceDerivedFindings(findings) {
518
- for (const f of findings) {
519
- for (const ref of f.evidence_refs ?? []) {
520
- if (ref.kind === "metric" && JUDGE_EVIDENCE_URI.test(ref.uri)) {
521
- throw new PlannerError(
522
- `steer-firewall: finding ${stringifySafe(f.finding_id)} cites judge-derived evidence (${stringifySafe(ref.uri)}); analyses fed to the driver must be trace-derived, not judge-derived (selector \u2260 judge)`
523
- );
524
- }
525
- }
526
- }
527
- }
528
696
  function renderAnalyses(findings) {
529
697
  if (findings.length === 0) return "";
530
698
  const rows = findings.map((f) => {
@@ -535,6 +703,56 @@ function renderAnalyses(findings) {
535
703
  ${rows.join("\n")}`;
536
704
  }
537
705
 
706
+ // src/runtime/inline-sandbox-client.ts
707
+ function isAsyncIterable(v) {
708
+ return typeof v === "object" && v !== null && Symbol.asyncIterator in v;
709
+ }
710
+ async function settle(exec, task, signal) {
711
+ const r = exec.execute(task, signal);
712
+ if (isAsyncIterable(r)) {
713
+ for await (const _ of r) {
714
+ }
715
+ return exec.resultArtifact();
716
+ }
717
+ return r;
718
+ }
719
+ function inlineSandboxClient(factory) {
720
+ let seq = 0;
721
+ return {
722
+ async create(_options) {
723
+ const id = `inline-${seq++}`;
724
+ return {
725
+ id,
726
+ async *streamPrompt(message) {
727
+ const controller = new AbortController();
728
+ const spec = { profile: { name: id }, harness: null };
729
+ const exec = factory(spec, { signal: controller.signal, seams: {} });
730
+ try {
731
+ const artifact = await settle(exec, message, controller.signal);
732
+ const out = artifact.out;
733
+ yield {
734
+ type: "result",
735
+ data: {
736
+ finalText: out?.content ?? "",
737
+ tokenUsage: {
738
+ inputTokens: artifact.spent.tokens.input,
739
+ outputTokens: artifact.spent.tokens.output
740
+ },
741
+ costUsd: artifact.spent.usd
742
+ }
743
+ };
744
+ } finally {
745
+ await exec.teardown("brutalKill").catch(() => {
746
+ });
747
+ }
748
+ },
749
+ async delete() {
750
+ }
751
+ };
752
+ }
753
+ };
754
+ }
755
+
538
756
  // src/runtime/report-usage.ts
539
757
  function reportLoopUsage(cost, result, source = "loop") {
540
758
  cost.observe(result.costUsd, source);
@@ -648,6 +866,7 @@ async function acquireSandbox(client, options, acquire = {}) {
648
866
  const sleep2 = acquire.sleep ?? ((ms) => sleep(ms, acquire.signal));
649
867
  const pollMs = acquire.pollIntervalMs ?? 3e3;
650
868
  const deadline = now() + (acquire.readyTimeoutMs ?? 6e5);
869
+ const appearScans = 5;
651
870
  const name = options.name ?? acquire.name ?? `loop-sbx-${randomUuid()}`;
652
871
  const createOpts = { ...options, name };
653
872
  const c = client;
@@ -663,9 +882,12 @@ async function acquireSandbox(client, options, acquire = {}) {
663
882
  if (!isRetryable(err)) throw err;
664
883
  lastErr = err;
665
884
  if (typeof c.list === "function") {
666
- const found = (await c.list().catch(() => []))?.find((b) => b.name === name);
667
- if (found)
668
- return await waitReadyOrDestroy(found, deadline, pollMs, acquire.signal, now, sleep2);
885
+ for (let scan = 0; scan < appearScans && now() < deadline; scan += 1) {
886
+ const found = (await c.list().catch(() => []))?.find((b) => b.name === name);
887
+ if (found)
888
+ return await waitReadyOrDestroy(found, deadline, pollMs, acquire.signal, now, sleep2);
889
+ if (scan < appearScans - 1) await sleep2(pollMs);
890
+ }
669
891
  }
670
892
  attempt += 1;
671
893
  await sleep2(Math.min(pollMs * attempt, 15e3));
@@ -714,9 +936,13 @@ function isRetryable(err) {
714
936
  if (typeof status === "number" && RETRYABLE_HTTP.has(status)) return true;
715
937
  const name = e.name ?? "";
716
938
  if (name === "TimeoutError" || name === "ServerError" || name === "NetworkError") return true;
717
- return /\b(timed out|timeout|gateway|temporarily unavailable|ECONNRESET|ETIMEDOUT|EAI_AGAIN)\b/i.test(
718
- e.message ?? ""
719
- );
939
+ const msg = e.message ?? "";
940
+ if (/\b(timed out|timeout|gateway|temporarily unavailable|too many requests|ECONNRESET|ETIMEDOUT|EAI_AGAIN)\b/i.test(
941
+ msg
942
+ )) {
943
+ return true;
944
+ }
945
+ return /provision failed|edge data plane|not reachable|failed to create sandbox/i.test(msg);
720
946
  }
721
947
 
722
948
  // src/runtime/sandbox-backend.ts
@@ -764,10 +990,31 @@ async function resolveCapabilities(client) {
764
990
  // src/runtime/sandbox-lineage.ts
765
991
  var TEARDOWN_TIMEOUT_MS = 15e3;
766
992
  var DEFAULT_FORK_CONCURRENCY = 4;
993
+ async function* pollPromptEvents(box, prompt, sessionId, signal) {
994
+ if (signal.aborted) throwAbort();
995
+ const dispatched = await box.dispatchPrompt(prompt, { sessionId, signal });
996
+ const activeSessionId = dispatched.sessionId;
997
+ const result = await box.session(activeSessionId).result();
998
+ if (signal.aborted) throwAbort();
999
+ yield {
1000
+ type: "result",
1001
+ id: activeSessionId,
1002
+ data: {
1003
+ finalText: result.response ?? "",
1004
+ success: result.success,
1005
+ ...result.error ? { error: result.error } : {},
1006
+ ...result.usage ? { usage: result.usage } : {}
1007
+ }
1008
+ };
1009
+ }
1010
+ function promptEvents(streaming, box, prompt, sessionId, signal) {
1011
+ return streaming === "poll" ? pollPromptEvents(box, prompt, sessionId, signal) : box.streamPrompt(prompt, { sessionId, signal });
1012
+ }
767
1013
  function createSandboxLineage(client, capabilities, options = {}) {
768
1014
  if (!client || typeof client.create !== "function") {
769
1015
  throw new ValidationError("createSandboxLineage: client.create is required");
770
1016
  }
1017
+ const streaming = options.streaming ?? "sse";
771
1018
  const forkConcurrency = Math.max(
772
1019
  1,
773
1020
  Math.floor(options.maxConcurrency ?? DEFAULT_FORK_CONCURRENCY)
@@ -784,13 +1031,13 @@ function createSandboxLineage(client, capabilities, options = {}) {
784
1031
  async start(spec, prompt, signal) {
785
1032
  const box = await acquireFresh(spec, signal);
786
1033
  const sessionId = mintSessionId();
787
- const events = box.streamPrompt(prompt, { sessionId, signal });
1034
+ const events = promptEvents(streaming, box, prompt, sessionId, signal);
788
1035
  return { handle: { box, sessionId }, events };
789
1036
  },
790
1037
  async continue(handle, prompt, signal) {
791
1038
  if (signal.aborted) throwAbort();
792
1039
  await assertSessionLive(handle.box, handle.sessionId);
793
- return handle.box.streamPrompt(prompt, { sessionId: handle.sessionId, signal });
1040
+ return promptEvents(streaming, handle.box, prompt, handle.sessionId, signal);
794
1041
  },
795
1042
  async fork(parent, prompts, specs, signal) {
796
1043
  if (prompts.length === 0) {
@@ -808,14 +1055,14 @@ function createSandboxLineage(client, capabilities, options = {}) {
808
1055
  const sessionId2 = mintSessionId();
809
1056
  return {
810
1057
  handle: { box: box2, sessionId: sessionId2 },
811
- events: box2.streamPrompt(prompt, { sessionId: sessionId2, signal })
1058
+ events: promptEvents(streaming, box2, prompt, sessionId2, signal)
812
1059
  };
813
1060
  }
814
1061
  const box = await acquireFresh(spec, signal);
815
1062
  const sessionId = mintSessionId();
816
1063
  return {
817
1064
  handle: { box, sessionId },
818
- events: box.streamPrompt(prompt, { sessionId, signal })
1065
+ events: promptEvents(streaming, box, prompt, sessionId, signal)
819
1066
  };
820
1067
  });
821
1068
  },
@@ -884,6 +1131,7 @@ async function runLoop(options) {
884
1131
  if (!Number.isFinite(maxConcurrency) || maxConcurrency <= 0) {
885
1132
  throw new ValidationError("runLoop: maxConcurrency must be > 0");
886
1133
  }
1134
+ const sandboxStreaming = options.lineage?.streaming ?? "sse";
887
1135
  if (!options.ctx?.sandboxClient || typeof options.ctx.sandboxClient.create !== "function") {
888
1136
  throw new ValidationError("runLoop: ctx.sandboxClient.create is required");
889
1137
  }
@@ -1000,6 +1248,7 @@ async function runLoop(options) {
1000
1248
  output: options.output,
1001
1249
  validator: options.validator,
1002
1250
  maxConcurrency,
1251
+ streaming: sandboxStreaming,
1003
1252
  signal: controller.signal,
1004
1253
  ctx: options.ctx,
1005
1254
  runId,
@@ -1059,7 +1308,10 @@ async function setUpLineage(options, maxConcurrency) {
1059
1308
  }
1060
1309
  const capabilities = await probeSandboxCapabilities(options.ctx.sandboxClient);
1061
1310
  return {
1062
- lineage: createSandboxLineage(options.ctx.sandboxClient, capabilities, { maxConcurrency }),
1311
+ lineage: createSandboxLineage(options.ctx.sandboxClient, capabilities, {
1312
+ maxConcurrency,
1313
+ streaming: lineageOpts.streaming
1314
+ }),
1063
1315
  options: lineageOpts,
1064
1316
  handles: /* @__PURE__ */ new Map(),
1065
1317
  canPrune: typeof options.driver.describePlan !== "function"
@@ -1189,7 +1441,8 @@ async function executeIteration(args) {
1189
1441
  stream = acquired.events;
1190
1442
  } else {
1191
1443
  box = await createSandboxForSpec(args.ctx.sandboxClient, spec, args.signal);
1192
- stream = box.streamPrompt(spec.taskToPrompt(args.item.task), { signal: args.signal });
1444
+ const prompt = spec.taskToPrompt(args.item.task);
1445
+ stream = args.streaming === "poll" ? promptEvents("poll", box, prompt, `${args.runId}-i${args.item.index}`, args.signal) : box.streamPrompt(prompt, { signal: args.signal });
1193
1446
  }
1194
1447
  const placement = describeSandboxPlacement(args.ctx.sandboxClient, box);
1195
1448
  await emitTrace(args.ctx.traceEmitter, {
@@ -1479,88 +1732,6 @@ function loopDispatch(opts) {
1479
1732
  return (profile, scenario, ctx) => runLoopForCell(opts, scenario, profile, ctx);
1480
1733
  }
1481
1734
 
1482
- // src/runtime/personify/analyst.ts
1483
- var judgeEvidenceUri = /^(verdict|judge|score)\b/i;
1484
- var assertTraceDerivedFindings2 = (findings) => {
1485
- for (const f of findings) {
1486
- for (const ref of f.evidence_refs ?? []) {
1487
- if (ref.kind === "metric" && judgeEvidenceUri.test(ref.uri)) {
1488
- throw new PlannerError(
1489
- `steer-firewall: finding ${stringifySafe(f.finding_id)} cites judge-derived evidence (${stringifySafe(ref.uri)}); findings fed to a combinator's steer decision must be trace-derived, not judge-derived (selector \u2260 judge)`
1490
- );
1491
- }
1492
- }
1493
- }
1494
- };
1495
- function createScopeAnalyst(scope, options) {
1496
- if (!options.analyst || typeof options.analyst.act !== "function") {
1497
- throw new AnalystError("createScopeAnalyst: analyst must be an Agent with an act() method");
1498
- }
1499
- const label = options.label ?? "analyst";
1500
- return {
1501
- async analyze(input) {
1502
- const task = options.buildTask(input);
1503
- const spawned = scope.spawn(options.analyst, task, {
1504
- budget: options.budget,
1505
- label
1506
- });
1507
- if (!spawned.ok) {
1508
- throw new AnalystError(
1509
- `createScopeAnalyst: analyst spawn refused by the conserved pool (${spawned.reason}); cannot steer node ${stringifySafe(input.nodeId)} on an unrun analyst`
1510
- );
1511
- }
1512
- const settled = await drainAnalystSettlement(scope, spawned.handle.id);
1513
- const findings = readAnalystFindings(settled);
1514
- assertTraceDerivedFindings2(findings);
1515
- return findings;
1516
- }
1517
- };
1518
- }
1519
- async function drainAnalystSettlement(scope, analystId) {
1520
- for (; ; ) {
1521
- const settled = await scope.next();
1522
- if (settled === null) {
1523
- throw new AnalystError(
1524
- `createScopeAnalyst: scope drained before analyst ${stringifySafe(analystId)} settled`
1525
- );
1526
- }
1527
- if (settled.handle.id === analystId) return settled;
1528
- }
1529
- }
1530
- function readAnalystFindings(settled) {
1531
- if (settled.kind === "down") {
1532
- throw new AnalystError(
1533
- `createScopeAnalyst: analyst ${stringifySafe(settled.handle.id)} settled down (${settled.infra ? "infra" : "result"}): ${stringifySafe(settled.reason)}`
1534
- );
1535
- }
1536
- const out = settled.out;
1537
- if (!Array.isArray(out)) {
1538
- throw new PlannerError(
1539
- `createScopeAnalyst: analyst ${stringifySafe(settled.handle.id)} must return AnalystFinding[], got ${stringifySafe(out)}`
1540
- );
1541
- }
1542
- return out;
1543
- }
1544
- function buildSteerContext(findings, settledSoFar) {
1545
- assertTraceDerivedFindings2(findings);
1546
- const lastValidScore = observedBestScore(settledSoFar);
1547
- return {
1548
- findings,
1549
- settledSoFar,
1550
- ...lastValidScore !== void 0 ? { lastValidScore } : {}
1551
- };
1552
- }
1553
- function observedBestScore(settledSoFar) {
1554
- let best;
1555
- for (const s of settledSoFar) {
1556
- if (s.kind !== "done") continue;
1557
- const v = s.verdict;
1558
- if (!v || v.valid !== true || typeof v.score !== "number") continue;
1559
- if (best === void 0 || v.score > best) best = v.score;
1560
- }
1561
- return best;
1562
- }
1563
-
1564
1735
  // src/runtime/supervise/scope.ts
1565
1736
  function createScope(args) {
1566
1737
  const children = /* @__PURE__ */ new Map();
@@ -1574,7 +1745,7 @@ function createScope(args) {
1574
1745
  const spec = agent.executorSpec;
1575
1746
  if (!isAgentSpec(spec)) {
1576
1747
  throw new ValidationError(
1577
- `scope.spawn: agent "${agent.name}" exposes no \`executorSpec\` (AgentSpec) to resolve a LeafExecutor`
1748
+ `scope.spawn: agent "${agent.name}" exposes no \`executorSpec\` (AgentSpec) to resolve a Executor`
1578
1749
  );
1579
1750
  }
1580
1751
  const resolved = args.executors.resolve(spec);
@@ -1802,7 +1973,7 @@ async function runChild(live, executor, childAbort, task, opts, pool, ticket, bl
1802
1973
  live.status = "running";
1803
1974
  const ran = executor.execute(task, childAbort.signal);
1804
1975
  let artifact;
1805
- if (isAsyncIterable(ran)) {
1976
+ if (isAsyncIterable2(ran)) {
1806
1977
  const spend = await foldStream(ran);
1807
1978
  live.spent = spend;
1808
1979
  artifact = executor.resultArtifact();
@@ -1924,7 +2095,7 @@ function downRecord(reason, infra) {
1924
2095
  function zeroSpend2() {
1925
2096
  return { iterations: 0, tokens: { input: 0, output: 0 }, usd: 0, ms: 0 };
1926
2097
  }
1927
- function isAsyncIterable(value) {
2098
+ function isAsyncIterable2(value) {
1928
2099
  return typeof value === "object" && value !== null && typeof value[Symbol.asyncIterator] === "function";
1929
2100
  }
1930
2101
  function isAgentSpec(value) {
@@ -2463,6 +2634,7 @@ import { estimateCost, isModelPriced } from "@tangle-network/agent-eval";
2463
2634
  var routerSeamKey = "router";
2464
2635
  var sandboxSeamKey = "sandbox";
2465
2636
  var cliSeamKey = "cli";
2637
+ var bridgeSeamKey = "bridge";
2466
2638
  function contentRef(prefix, value) {
2467
2639
  let str;
2468
2640
  try {
@@ -2756,6 +2928,96 @@ function killWithGrace(proc, grace) {
2756
2928
  }, grace);
2757
2929
  });
2758
2930
  }
2931
+ var bridgeExecutor = (spec, ctx) => {
2932
+ const seam = readSeam(ctx, bridgeSeamKey, "bridge");
2933
+ if (!seam.bridgeUrl || !seam.bridgeBearer || !seam.model) {
2934
+ throw new ValidationError(
2935
+ "bridgeExecutor: BridgeSeam.bridgeUrl + bridgeBearer + model required"
2936
+ );
2937
+ }
2938
+ const controller = new AbortController();
2939
+ const abortIfSignalled = () => {
2940
+ if (ctx.signal.aborted) controller.abort();
2941
+ };
2942
+ abortIfSignalled();
2943
+ if (!ctx.signal.aborted) ctx.signal.addEventListener("abort", abortIfSignalled, { once: true });
2944
+ let artifact;
2945
+ return {
2946
+ runtime: "cli",
2947
+ async execute(task, signal) {
2948
+ const messages = taskToMessages(task, spec);
2949
+ const started = Date.now();
2950
+ const linked = linkSignals(signal, controller.signal);
2951
+ const timer = seam.timeoutMs ? setTimeout(() => controller.abort(), seam.timeoutMs) : void 0;
2952
+ try {
2953
+ const res = await fetch(`${seam.bridgeUrl.replace(/\/$/, "")}/v1/chat/completions`, {
2954
+ method: "POST",
2955
+ headers: {
2956
+ "content-type": "application/json",
2957
+ authorization: `Bearer ${seam.bridgeBearer}`
2958
+ },
2959
+ body: JSON.stringify({
2960
+ model: seam.model,
2961
+ stream: false,
2962
+ ...seam.agentProfile ? { agent_profile: seam.agentProfile } : {},
2963
+ messages
2964
+ }),
2965
+ ...linked ? { signal: linked } : {}
2966
+ });
2967
+ if (!res.ok) {
2968
+ throw new ValidationError(
2969
+ `bridgeExecutor: bridge ${res.status}: ${(await res.text()).slice(0, 300)}`
2970
+ );
2971
+ }
2972
+ const data = await res.json();
2973
+ const u = data.usage;
2974
+ const usage = u && typeof u.prompt_tokens === "number" && typeof u.completion_tokens === "number" ? { input: u.prompt_tokens, output: u.completion_tokens } : void 0;
2975
+ const msg = data.choices?.[0]?.message;
2976
+ const content = msg?.content ?? "";
2977
+ const toolCalls = (msg?.tool_calls ?? []).map((t) => t.function?.name ?? "unknown");
2978
+ const spent = {
2979
+ iterations: 1,
2980
+ tokens: usage ? { input: usage.input, output: usage.output } : zeroTokenUsage(),
2981
+ usd: typeof u?.cost === "number" ? u.cost : 0,
2982
+ ms: Date.now() - started
2983
+ };
2984
+ const out = { content, toolCalls };
2985
+ artifact = { outRef: contentRef("bridge", { model: seam.model, content }), out, spent };
2986
+ return artifact;
2987
+ } finally {
2988
+ if (timer) clearTimeout(timer);
2989
+ }
2990
+ },
2991
+ teardown(_grace) {
2992
+ controller.abort();
2993
+ return Promise.resolve({ destroyed: true });
2994
+ },
2995
+ resultArtifact() {
2996
+ if (!artifact) {
2997
+ throw new ValidationError("bridgeExecutor: resultArtifact() read before execute()");
2998
+ }
2999
+ return { ...artifact, spent: artifact.spent };
3000
+ }
3001
+ };
3002
+ };
3003
+ function createExecutor(config) {
3004
+ return (spec, ctx) => {
3005
+ const { backend, ...seam } = config;
3006
+ const seamed = { ...ctx, seams: { ...ctx.seams, [backend]: seam } };
3007
+ switch (config.backend) {
3008
+ case "router":
3009
+ return routerInlineExecutor(spec, seamed);
3010
+ case "bridge":
3011
+ return bridgeExecutor(spec, seamed);
3012
+ case "cli":
3013
+ return cliExecutor(spec, seamed);
3014
+ case "sandbox": {
3015
+ const harness = spec.harness ?? config.harness ?? null;
3016
+ return sandboxExecutor({ ...spec, harness }, seamed);
3017
+ }
3018
+ }
3019
+ };
3020
+ }
2759
3021
  function createExecutorRegistry() {
2760
3022
  const factories = /* @__PURE__ */ new Map();
2761
3023
  factories.set("router", routerInlineExecutor);
@@ -3538,6 +3800,234 @@ function requireSpend(rolled, id, root) {
3538
3800
  return spend;
3539
3801
  }
3540
3802
 
3803
+ // src/runtime/sandbox-run.ts
3804
+ async function openSandboxRun(client, options, deliverable) {
3805
+ const runId = options.runId ?? `sandbox-run-${randomSuffix()}`;
3806
+ const now = options.now ?? Date.now;
3807
+ const capabilities = await probeSandboxCapabilities(client);
3808
+ const lineage = createSandboxLineage(client, capabilities, {
3809
+ ...options.maxConcurrency !== void 0 ? { maxConcurrency: options.maxConcurrency } : {}
3810
+ });
3811
+ let handle;
3812
+ let started = false;
3813
+ let runStartedAt;
3814
+ let failed = false;
3815
+ let turnCount = 0;
3816
+ function emit(event) {
3817
+ notifyRuntimeHookEvent(
3818
+ options.hooks,
3819
+ {
3820
+ id: `${runId}:${event.target}:${event.phase}${event.stepIndex === void 0 ? "" : `:${event.stepIndex}`}`,
3821
+ runId,
3822
+ scenarioId: options.scenarioId,
3823
+ target: event.target,
3824
+ phase: event.phase,
3825
+ timestamp: event.timestamp,
3826
+ stepIndex: event.stepIndex,
3827
+ payload: event.payload,
3828
+ metadata: { producer: "openSandboxRun" }
3829
+ },
3830
+ { signal: options.signal }
3831
+ );
3832
+ }
3833
+ const runPayload = () => ({
3834
+ agentName: options.agentRun.name ?? options.agentRun.profile.name ?? "agent",
3835
+ profileName: options.agentRun.profile.name,
3836
+ backendType: backendType(options.agentRun),
3837
+ deliverableKind: deliverable.kind,
3838
+ ...deliverable.kind === "artifact" ? { deliverablePath: deliverable.path } : {},
3839
+ ...handle ? { sessionId: handle.sessionId, sandboxId: handle.box.id } : {}
3840
+ });
3841
+ const turnPayload = (prompt, turnKind, startedAt, result, error) => ({
3842
+ ...runPayload(),
3843
+ turnKind,
3844
+ promptChars: prompt.length,
3845
+ promptHash: hashText(prompt),
3846
+ ...result !== void 0 || error !== void 0 ? { durationMs: Math.max(0, now() - startedAt) } : {},
3847
+ ...result ? {
3848
+ eventCount: result.events.length,
3849
+ eventTypes: eventTypeCounts(result.events),
3850
+ ...result.readError !== void 0 ? { readError: result.readError } : {}
3851
+ } : {},
3852
+ ...error !== void 0 ? { error: errorMessage(error) } : {}
3853
+ });
3854
+ async function settle2(box, events) {
3855
+ const collected = [];
3856
+ for await (const ev of events) collected.push(ev);
3857
+ if (deliverable.kind === "events") {
3858
+ return { out: deliverable.fromEvents(collected), events: collected };
3859
+ }
3860
+ throwIfAborted(options.signal);
3861
+ let raw = "";
3862
+ let readError;
3863
+ const readAttempts = 4;
3864
+ const readDelayMs = options.readRetryDelayMs ?? 1e3;
3865
+ for (let attempt = 0; attempt < readAttempts; attempt += 1) {
3866
+ throwIfAborted(options.signal);
3867
+ try {
3868
+ raw = await box.fs.read(deliverable.path);
3869
+ readError = void 0;
3870
+ break;
3871
+ } catch (err) {
3872
+ readError = err instanceof Error ? err.message : String(err);
3873
+ if (attempt < readAttempts - 1 && readDelayMs > 0)
3874
+ await sleep(readDelayMs * (attempt + 1), options.signal);
3875
+ }
3876
+ }
3877
+ return {
3878
+ out: deliverable.fromArtifact(raw, collected),
3879
+ events: collected,
3880
+ ...readError !== void 0 ? { readError } : {}
3881
+ };
3882
+ }
3883
+ return {
3884
+ get box() {
3885
+ if (!handle) throw new Error("openSandboxRun: box unavailable before start()");
3886
+ return handle.box;
3887
+ },
3888
+ get sessionId() {
3889
+ if (!handle) throw new Error("openSandboxRun: sessionId unavailable before start()");
3890
+ return handle.sessionId;
3891
+ },
3892
+ async start(prompt) {
3893
+ if (started)
3894
+ throw new Error(
3895
+ "openSandboxRun: start() already called \u2014 use resume() to continue the session"
3896
+ );
3897
+ started = true;
3898
+ runStartedAt = now();
3899
+ emit({
3900
+ target: "agent.run",
3901
+ phase: "before",
3902
+ timestamp: runStartedAt,
3903
+ payload: { ...runPayload(), turnCount: 0 }
3904
+ });
3905
+ const stepIndex = turnCount;
3906
+ const turnStartedAt = now();
3907
+ emit({
3908
+ target: "agent.turn",
3909
+ phase: "before",
3910
+ timestamp: turnStartedAt,
3911
+ stepIndex,
3912
+ payload: turnPayload(prompt, "start", turnStartedAt)
3913
+ });
3914
+ try {
3915
+ const r = await lineage.start(
3916
+ options.agentRun,
3917
+ prompt,
3918
+ options.signal
3919
+ );
3920
+ handle = r.handle;
3921
+ const result = await settle2(handle.box, r.events);
3922
+ turnCount += 1;
3923
+ emit({
3924
+ target: "agent.turn",
3925
+ phase: "after",
3926
+ timestamp: now(),
3927
+ stepIndex,
3928
+ payload: turnPayload(prompt, "start", turnStartedAt, result)
3929
+ });
3930
+ return result;
3931
+ } catch (error) {
3932
+ failed = true;
3933
+ emit({
3934
+ target: "agent.turn",
3935
+ phase: "error",
3936
+ timestamp: now(),
3937
+ stepIndex,
3938
+ payload: turnPayload(prompt, "start", turnStartedAt, void 0, error)
3939
+ });
3940
+ emit({
3941
+ target: "agent.run",
3942
+ phase: "error",
3943
+ timestamp: now(),
3944
+ payload: { ...runPayload(), turnCount, error: errorMessage(error) }
3945
+ });
3946
+ throw error;
3947
+ }
3948
+ },
3949
+ async resume(prompt) {
3950
+ if (!handle) throw new Error("openSandboxRun: resume() called before start()");
3951
+ const stepIndex = turnCount;
3952
+ const turnStartedAt = now();
3953
+ emit({
3954
+ target: "agent.turn",
3955
+ phase: "before",
3956
+ timestamp: turnStartedAt,
3957
+ stepIndex,
3958
+ payload: turnPayload(prompt, "resume", turnStartedAt)
3959
+ });
3960
+ try {
3961
+ const result = await settle2(
3962
+ handle.box,
3963
+ await lineage.continue(handle, prompt, options.signal)
3964
+ );
3965
+ turnCount += 1;
3966
+ emit({
3967
+ target: "agent.turn",
3968
+ phase: "after",
3969
+ timestamp: now(),
3970
+ stepIndex,
3971
+ payload: turnPayload(prompt, "resume", turnStartedAt, result)
3972
+ });
3973
+ return result;
3974
+ } catch (error) {
3975
+ failed = true;
3976
+ emit({
3977
+ target: "agent.turn",
3978
+ phase: "error",
3979
+ timestamp: now(),
3980
+ stepIndex,
3981
+ payload: turnPayload(prompt, "resume", turnStartedAt, void 0, error)
3982
+ });
3983
+ emit({
3984
+ target: "agent.run",
3985
+ phase: "error",
3986
+ timestamp: now(),
3987
+ payload: { ...runPayload(), turnCount, error: errorMessage(error) }
3988
+ });
3989
+ throw error;
3990
+ }
3991
+ },
3992
+ async close() {
3993
+ await lineage.teardown();
3994
+ if (runStartedAt !== void 0) {
3995
+ emit({
3996
+ target: "agent.run",
3997
+ phase: "after",
3998
+ timestamp: now(),
3999
+ payload: {
4000
+ ...runPayload(),
4001
+ turnCount,
4002
+ status: failed ? "error" : "completed",
4003
+ durationMs: Math.max(0, now() - runStartedAt)
4004
+ }
4005
+ });
4006
+ }
4007
+ }
4008
+ };
4009
+ }
4010
+ function backendType(spec) {
4011
+ const backend = spec.sandboxOverrides?.backend;
4012
+ return backend?.type;
4013
+ }
4014
+ function eventTypeCounts(events) {
4015
+ const counts = {};
4016
+ for (const event of events) counts[event.type] = (counts[event.type] ?? 0) + 1;
4017
+ return counts;
4018
+ }
4019
+ function hashText(value) {
4020
+ let hash = 2166136261;
4021
+ for (let i = 0; i < value.length; i += 1) {
4022
+ hash ^= value.charCodeAt(i);
4023
+ hash = Math.imul(hash, 16777619);
4024
+ }
4025
+ return (hash >>> 0).toString(16).padStart(8, "0");
4026
+ }
4027
+ function errorMessage(error) {
4028
+ return error instanceof Error ? error.message : String(error);
4029
+ }
4030
+
3541
4031
  export {
3542
4032
  contentAddress,
3543
4033
  InMemoryResultBlobStore,
@@ -3550,8 +4040,12 @@ export {
3550
4040
  stopSentinel,
3551
4041
  sentinelCompletion,
3552
4042
  deterministicCompletion,
3553
- createDynamicDriver,
4043
+ assertTraceDerivedFindings,
4044
+ createScopeAnalyst,
4045
+ buildSteerContext,
4046
+ createDriver,
3554
4047
  renderAnalyses,
4048
+ inlineSandboxClient,
3555
4049
  reportLoopUsage,
3556
4050
  defineRuntimeHooks,
3557
4051
  composeRuntimeHooks,
@@ -3565,9 +4059,6 @@ export {
3565
4059
  createSandboxForSpec,
3566
4060
  defaultSelectWinner,
3567
4061
  loopDispatch,
3568
- assertTraceDerivedFindings2 as assertTraceDerivedFindings,
3569
- createScopeAnalyst,
3570
- buildSteerContext,
3571
4062
  createScope,
3572
4063
  settledToIteration,
3573
4064
  pipeline,
@@ -3580,9 +4071,7 @@ export {
3580
4071
  InMemoryCorpus,
3581
4072
  FileCorpus,
3582
4073
  renderCorpusToInstructions,
3583
- routerInlineExecutor,
3584
- sandboxExecutor,
3585
- cliExecutor,
4074
+ createExecutor,
3586
4075
  createExecutorRegistry,
3587
4076
  spendFromUsageEvents,
3588
4077
  createBudgetPool,
@@ -3594,6 +4083,7 @@ export {
3594
4083
  definePersona,
3595
4084
  runPersonified,
3596
4085
  trajectoryReport,
3597
- equalKOnCost
4086
+ equalKOnCost,
4087
+ openSandboxRun
3598
4088
  };
3599
- //# sourceMappingURL=chunk-KEWO4KI6.js.map
4089
+ //# sourceMappingURL=chunk-65FQLI4V.js.map