@tangle-network/agent-runtime 6.0.8 → 8.0.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 (119) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/README.md +23 -12
  3. package/dist/{activation-Cwy3_Qn_.js → activation-Ce4zUcu8.js} +4 -4
  4. package/dist/{activation-Cwy3_Qn_.js.map → activation-Ce4zUcu8.js.map} +1 -1
  5. package/dist/{activation-CWx7I1PU.d.ts → activation-xxvLF1-1.d.ts} +2 -2
  6. package/dist/agent.d.ts +1 -1
  7. package/dist/agent.js +3 -3
  8. package/dist/{bundle-Cy5igJdv.js → bundle-CcpL2lfr.js} +2 -2
  9. package/dist/{bundle-Cy5igJdv.js.map → bundle-CcpL2lfr.js.map} +1 -1
  10. package/dist/candidate-execution/index.js +4 -4
  11. package/dist/continuation-CIyKnS1Q.js +451 -0
  12. package/dist/continuation-CIyKnS1Q.js.map +1 -0
  13. package/dist/{coordination-manager-D9z7To7p.js → coordination-manager-sa_PkISw.js} +247 -149
  14. package/dist/coordination-manager-sa_PkISw.js.map +1 -0
  15. package/dist/{coordination-map-routing-CKRNZSaV.js → coordination-map-routing-XZXTlCmn.js} +2 -4
  16. package/dist/coordination-map-routing-XZXTlCmn.js.map +1 -0
  17. package/dist/{delegate-ws-KBA2H.js → delegate-DhTkJIta.js} +3 -3
  18. package/dist/{delegate-ws-KBA2H.js.map → delegate-DhTkJIta.js.map} +1 -1
  19. package/dist/durable.d.ts +71 -4
  20. package/dist/durable.js +162 -13
  21. package/dist/durable.js.map +1 -1
  22. package/dist/{errors-AzSuGI23.js → errors-DG8yufqX.js} +8 -1
  23. package/dist/errors-DG8yufqX.js.map +1 -0
  24. package/dist/{failure-cause-BzjUUsRz.js → failure-cause-CVB-YE88.js} +17 -16
  25. package/dist/failure-cause-CVB-YE88.js.map +1 -0
  26. package/dist/{graph-registry-7X2nrreR.js → graph-registry-czAwYwNj.js} +133 -9
  27. package/dist/graph-registry-czAwYwNj.js.map +1 -0
  28. package/dist/{graph-registry-gYbq4L5Z.js → graph-registry-uTIyyy7A.js} +1 -1
  29. package/dist/graph-tSIT_eWK.js +1793 -0
  30. package/dist/graph-tSIT_eWK.js.map +1 -0
  31. package/dist/{improve-BxfqTsZy.js → improve-H08hiIw9.js} +19 -48
  32. package/dist/improve-H08hiIw9.js.map +1 -0
  33. package/dist/index.d.ts +3 -3
  34. package/dist/index.js +16 -16
  35. package/dist/intelligence.d.ts +2 -2
  36. package/dist/intelligence.js +8 -8
  37. package/dist/intelligence.js.map +1 -1
  38. package/dist/kernel.d.ts +2 -2
  39. package/dist/kernel.js +16 -15
  40. package/dist/{loop-runner-CUMypgRw.d.ts → loop-runner-BGwhcn1p.d.ts} +2 -2
  41. package/dist/{loop-runner-BmGZ4y1W.js → loop-runner-ChqK8kSz.js} +3 -3
  42. package/dist/{loop-runner-BmGZ4y1W.js.map → loop-runner-ChqK8kSz.js.map} +1 -1
  43. package/dist/loop-runner-bin.d.ts +1 -1
  44. package/dist/loop-runner-bin.js +1 -1
  45. package/dist/mcp/bin.js +7 -5
  46. package/dist/mcp/bin.js.map +1 -1
  47. package/dist/mcp/index.d.ts +1 -1
  48. package/dist/mcp/index.js +9 -9
  49. package/dist/mcp/memory-bin.js +2 -2
  50. package/dist/{model-policy-JOcg3NRs.js → model-policy-yxOrDTTj.js} +9 -9
  51. package/dist/model-policy-yxOrDTTj.js.map +1 -0
  52. package/dist/{prepare-Dtfk_Wi_.js → prepare-BnF8nGIg.js} +4 -4
  53. package/dist/{prepare-Dtfk_Wi_.js.map → prepare-BnF8nGIg.js.map} +1 -1
  54. package/dist/{profile-CNSQjOes.js → profile-CD25rTJF.js} +4 -4
  55. package/dist/{profile-CNSQjOes.js.map → profile-CD25rTJF.js.map} +1 -1
  56. package/dist/profiles.d.ts +1 -1
  57. package/dist/profiles.js +2 -2
  58. package/dist/{provision-supervisor-CeQTPHRr.js → provision-supervisor-Dx4TXTMM.js} +8 -8
  59. package/dist/{provision-supervisor-CeQTPHRr.js.map → provision-supervisor-Dx4TXTMM.js.map} +1 -1
  60. package/dist/{run-cancellation-D_4vJ522.js → run-cancellation-DYszFJtQ.js} +4 -4
  61. package/dist/{run-cancellation-D_4vJ522.js.map → run-cancellation-DYszFJtQ.js.map} +1 -1
  62. package/dist/{run-state-CTZVngI_.js → run-state-DHBoJjaF.js} +6 -6
  63. package/dist/{run-state-CTZVngI_.js.map → run-state-DHBoJjaF.js.map} +1 -1
  64. package/dist/{runtime-COm9uBBx.js → runtime-CaM5Gbbv.js} +76 -987
  65. package/dist/runtime-CaM5Gbbv.js.map +1 -0
  66. package/dist/{sandbox-profile-compat-oFGWESLn.js → sandbox-profile-compat-l-SLQnGb.js} +2 -2
  67. package/dist/{sandbox-profile-compat-oFGWESLn.js.map → sandbox-profile-compat-l-SLQnGb.js.map} +1 -1
  68. package/dist/{search-executor-DTEIl58w.js → search-executor-B9L8W_1O.js} +17 -46
  69. package/dist/search-executor-B9L8W_1O.js.map +1 -0
  70. package/dist/{server-zO9Nz9Nk.js → server-BlDV8sj_.js} +32 -8
  71. package/dist/{server-zO9Nz9Nk.js.map → server-BlDV8sj_.js.map} +1 -1
  72. package/dist/{settle-record-U7fkQEZa.js → settle-record-WWQasnDq.js} +12 -4
  73. package/dist/settle-record-WWQasnDq.js.map +1 -0
  74. package/dist/{snapshot-Cgj2Wzi6.js → snapshot-BKI_w3JD.js} +19 -5
  75. package/dist/snapshot-BKI_w3JD.js.map +1 -0
  76. package/dist/{structural-rollout-BwTwTUXF.js → structural-rollout-C1xxoWcN.js} +39 -57
  77. package/dist/structural-rollout-C1xxoWcN.js.map +1 -0
  78. package/dist/{supervise-tmqDU6YT.js → supervise-DWiSgPLB.js} +103 -111
  79. package/dist/supervise-DWiSgPLB.js.map +1 -0
  80. package/dist/{supervision-discovery-CGbXayGv.js → supervision-discovery-C9kfBLKy.js} +4 -4
  81. package/dist/{supervision-discovery-CGbXayGv.js.map → supervision-discovery-C9kfBLKy.js.map} +1 -1
  82. package/dist/{supervisor-1A27fE6k.js → supervisor-Dpeu7rnZ.js} +209 -999
  83. package/dist/supervisor-Dpeu7rnZ.js.map +1 -0
  84. package/dist/{scope-gIYQ5ZiL.js → supervisor-accounting-Bw4MJk-b.js} +755 -458
  85. package/dist/supervisor-accounting-Bw4MJk-b.js.map +1 -0
  86. package/dist/testing.d.ts +1 -1
  87. package/dist/testing.js +13 -13
  88. package/dist/{tool-server-B9q2dtnW.js → tool-server-DYwRbi0I.js} +3 -3
  89. package/dist/{tool-server-B9q2dtnW.js.map → tool-server-DYwRbi0I.js.map} +1 -1
  90. package/dist/{top-web-CS4PD4ck.js → top-web-B3HOAtrZ.js} +9 -7
  91. package/dist/{top-web-CS4PD4ck.js.map → top-web-B3HOAtrZ.js.map} +1 -1
  92. package/dist/tui/bin.js +6 -6
  93. package/dist/tui/bin.js.map +1 -1
  94. package/dist/tui/index.d.ts +1 -1
  95. package/dist/tui/index.js +2 -2
  96. package/dist/{types-w3Oo1uRJ.d.ts → types-C_qbnw9N.d.ts} +1263 -1497
  97. package/dist/{util-C_cdPNC4.js → util-fcckrkKp.js} +39 -113
  98. package/dist/util-fcckrkKp.js.map +1 -0
  99. package/dist/{workspace-streams-B7yNMahl.js → workspace-streams-DA9R3j-p.js} +2 -2
  100. package/dist/{workspace-streams-B7yNMahl.js.map → workspace-streams-DA9R3j-p.js.map} +1 -1
  101. package/package.json +1 -1
  102. package/dist/coordination-manager-D9z7To7p.js.map +0 -1
  103. package/dist/coordination-map-routing-CKRNZSaV.js.map +0 -1
  104. package/dist/errors-AzSuGI23.js.map +0 -1
  105. package/dist/failure-cause-BzjUUsRz.js.map +0 -1
  106. package/dist/graph-2_nX4ib4.js +0 -579
  107. package/dist/graph-2_nX4ib4.js.map +0 -1
  108. package/dist/graph-registry-7X2nrreR.js.map +0 -1
  109. package/dist/improve-BxfqTsZy.js.map +0 -1
  110. package/dist/model-policy-JOcg3NRs.js.map +0 -1
  111. package/dist/runtime-COm9uBBx.js.map +0 -1
  112. package/dist/scope-gIYQ5ZiL.js.map +0 -1
  113. package/dist/search-executor-DTEIl58w.js.map +0 -1
  114. package/dist/settle-record-U7fkQEZa.js.map +0 -1
  115. package/dist/snapshot-Cgj2Wzi6.js.map +0 -1
  116. package/dist/structural-rollout-BwTwTUXF.js.map +0 -1
  117. package/dist/supervise-tmqDU6YT.js.map +0 -1
  118. package/dist/supervisor-1A27fE6k.js.map +0 -1
  119. package/dist/util-C_cdPNC4.js.map +0 -1
@@ -1,3 +1,4 @@
1
+ import { W as FileSpawnJournal, n as terminalAccounting } from "./supervisor-accounting-Bw4MJk-b.js";
1
2
  import { t as isNoEntError } from "./jsonl-file-DsxVI0E_.js";
2
3
  import { a as writeAtomicDurableFile, r as publishExclusiveDurableFile } from "./durable-file-DstVeHcj.js";
3
4
  import { canonicalCandidateDigest, canonicalCandidateJson } from "@tangle-network/agent-interface";
@@ -88,10 +89,17 @@ async function writeFailureRecord(runDir, record) {
88
89
  }
89
90
  /**
90
91
  * Read the settle record a run directory holds, or `undefined` when it holds none. A file that
91
- * is present but is not a settle record is corruption and fails loud.
92
+ * is present but is not a settle record is corruption and fails loud. `usage` annotates legacy
93
+ * results by replay without changing their sealed fields; recorded usage always wins.
92
94
  */
93
- async function readSettleRecord(runDir) {
94
- return readTerminalFile(runDir, SETTLE_RECORD_FILE, parseSettleRecord);
95
+ async function readSettleRecord(runDir, options = {}) {
96
+ const recorded = await readTerminalFile(runDir, SETTLE_RECORD_FILE, parseSettleRecord);
97
+ if (!recorded || !options.usage || recorded.usage) return recorded;
98
+ const { usage } = await terminalAccounting(new FileSpawnJournal(resolve(runDir, "spawn-journal.jsonl")), recorded.tree.root, recorded.spentTotal.ms, options.requestedProfile);
99
+ return {
100
+ ...recorded,
101
+ usage
102
+ };
95
103
  }
96
104
  async function readTerminalFile(runDir, file, parse) {
97
105
  const path = resolve(runDir, file);
@@ -127,4 +135,4 @@ async function readFailureRecord(runDir) {
127
135
  }
128
136
  export { readFailureRecord as a, writeFailureRecord as c, parseSettleRecord as i, writeSettleRecord as l, SETTLE_RECORD_FILE as n, readSettleRecord as o, SettledRunDirectoryError as r, settleRecordDigest as s, FAILURE_RECORD_FILE as t };
129
137
 
130
- //# sourceMappingURL=settle-record-U7fkQEZa.js.map
138
+ //# sourceMappingURL=settle-record-WWQasnDq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settle-record-WWQasnDq.js","names":[],"sources":["../src/durable/settle-record.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport {\n type AgentProfile,\n canonicalCandidateDigest,\n canonicalCandidateJson,\n} from '@tangle-network/agent-interface'\nimport {\n publishExclusiveDurableFile,\n writeAtomicDurableFile,\n} from '../runtime/supervise/durable-file'\nimport { terminalAccounting } from '../runtime/supervise/supervisor-accounting'\nimport type { RootStreamReceipt, SupervisedResult } from '../runtime/supervise/types'\nimport { isNoEntError } from './jsonl-file'\nimport { FileSpawnJournal } from './spawn-journal/journal-store'\n\n/** Terminal evidence has one result per segment. Reopen archives that result byte for byte;\n * a failed attempt may resume because failure.json records only the latest throw.\n * Serialization, exclusive publication and validation stay with the record operations below.\n */\n\n/** The settle record: the returned `SupervisedResult` as canonical JSON, written once. */\nexport const SETTLE_RECORD_FILE = 'result.json'\n/** The failure record: the most recent throw, replaced by a later throw. */\nexport const FAILURE_RECORD_FILE = 'failure.json'\n\n/** What `failure.json` records about the most recent throw. */\nexport interface DurableFailureRecord {\n readonly runId: string\n readonly pursuitId: string\n /** ISO instant the throw was recorded. */\n readonly at: string\n readonly error: { readonly name: string; readonly message: string }\n /** The root's retained provider stream at the time of the throw, when the directory holds one:\n * a root that died mid-turn keeps what it had streamed, and this names it. */\n readonly rootStream?: RootStreamReceipt\n}\n\n/** The directory already holds a settle record, so the run it records must not be re-entered. */\nexport class SettledRunDirectoryError extends Error {\n readonly path: string\n /** The root of the recorded run, which is its `runId`. */\n readonly recordedRunId: string\n\n constructor(path: string, recordedRunId: string, requestedRunId: string) {\n super(\n recordedRunId === requestedRunId\n ? `supervisePursuit: ${path} records that run '${recordedRunId}' already settled; a settled run is not re-entered unless the call passes reopen: { operator, reason, operationId }`\n : `supervisePursuit: ${path} records that run '${recordedRunId}' already settled in this directory; a directory holds one settle record, so run '${requestedRunId}' needs its own runDir`,\n )\n this.name = 'SettledRunDirectoryError'\n this.path = path\n this.recordedRunId = recordedRunId\n }\n}\n\n/** A result member whose JSON form would misstate it. */\nclass UnrecordableSettleValueError extends TypeError {\n readonly path: string\n\n constructor(path: string, kind: string) {\n super(\n `supervisePursuit: result${path} is a ${kind}, which JSON cannot record faithfully; a settle record holds plain data only`,\n )\n this.name = 'UnrecordableSettleValueError'\n this.path = path\n }\n}\n\nconst PLAIN_PROTOTYPES = new Set<unknown>([Object.prototype, Array.prototype, null])\n\n/**\n * The JSON value of a result, or a throw naming the first member JSON would misstate. An\n * `undefined` member and a function are dropped, exactly as any JSON consumer drops them; a Map,\n * a Set, a Date, a typed array, or a class instance would be rewritten to `{}` or a string and\n * so is refused.\n */\nfunction jsonValue(result: unknown): unknown {\n const seen: unknown[] = []\n const visit = (value: unknown, path: string): void => {\n if (value === null || typeof value !== 'object') return\n if (value instanceof Map) throw new UnrecordableSettleValueError(path, 'Map')\n if (value instanceof Set) throw new UnrecordableSettleValueError(path, 'Set')\n if (value instanceof Date) throw new UnrecordableSettleValueError(path, 'Date')\n if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {\n throw new UnrecordableSettleValueError(path, 'binary buffer')\n }\n if (!PLAIN_PROTOTYPES.has(Object.getPrototypeOf(value))) {\n throw new UnrecordableSettleValueError(path, 'class instance')\n }\n if (seen.includes(value)) throw new UnrecordableSettleValueError(path, 'cycle')\n seen.push(value)\n if (Array.isArray(value)) {\n for (const [index, item] of value.entries()) visit(item, `${path}[${index}]`)\n } else {\n for (const [key, item] of Object.entries(value)) visit(item, `${path}.${key}`)\n }\n seen.pop()\n }\n visit(result, '')\n return JSON.parse(JSON.stringify(result))\n}\n\n/**\n * The exact bytes `result.json` holds for a result: its JSON value serialized as RFC 8785\n * canonical JSON. Throws `UnrecordableSettleValueError` before any byte is written when the\n * result carries a value JSON would misstate.\n */\nexport function settleRecordJson(result: unknown): string {\n return canonicalCandidateJson(jsonValue(result))\n}\n\n/** The digest the settle record's bytes hash to: the candidate digest of the result's JSON value. */\nexport function settleRecordDigest(result: unknown): string {\n return canonicalCandidateDigest(jsonValue(result))\n}\n\n/** Publish `result.json` in the run directory once. Throws when a record is already there. */\nexport async function writeSettleRecord(runDir: string, result: unknown): Promise<string> {\n const path = resolve(runDir, SETTLE_RECORD_FILE)\n if (!publishExclusiveDurableFile(path, settleRecordJson(result))) {\n throw new Error(`supervisePursuit: ${path} already exists; a settle record is written once`)\n }\n return path\n}\n\n/** Replace `failure.json` in the run directory with the most recent throw. */\nexport async function writeFailureRecord(\n runDir: string,\n record: DurableFailureRecord,\n): Promise<string> {\n const path = resolve(runDir, FAILURE_RECORD_FILE)\n writeAtomicDurableFile(path, `${JSON.stringify(record, null, 2)}\\n`)\n return path\n}\n\n/**\n * Read the settle record a run directory holds, or `undefined` when it holds none. A file that\n * is present but is not a settle record is corruption and fails loud. `usage` annotates legacy\n * results by replay without changing their sealed fields; recorded usage always wins.\n */\nexport async function readSettleRecord(\n runDir: string,\n options: { readonly usage?: boolean; readonly requestedProfile?: AgentProfile } = {},\n): Promise<SupervisedResult<unknown> | undefined> {\n const recorded = await readTerminalFile(runDir, SETTLE_RECORD_FILE, parseSettleRecord)\n if (!recorded || !options.usage || recorded.usage) return recorded\n const { usage } = await terminalAccounting(\n new FileSpawnJournal(resolve(runDir, 'spawn-journal.jsonl')),\n recorded.tree.root,\n recorded.spentTotal.ms,\n options.requestedProfile,\n )\n return { ...recorded, usage }\n}\n\nasync function readTerminalFile<T>(\n runDir: string,\n file: string,\n parse: (text: string, path: string) => T,\n): Promise<T | undefined> {\n const path = resolve(runDir, file)\n try {\n return parse(await readFile(path, 'utf8'), path)\n } catch (error) {\n if (isNoEntError(error)) return undefined\n throw error\n }\n}\n\nfunction parseTerminalJson(text: string, path: string): unknown {\n try {\n return JSON.parse(text)\n } catch (cause) {\n throw new Error(`supervisePursuit: ${path} is not valid JSON`, { cause })\n }\n}\n\n/** Parse settle-record bytes already read, so a caller hashes and parses the same bytes. */\nexport function parseSettleRecord(text: string, path: string): SupervisedResult<unknown> {\n const parsed = parseTerminalJson(text, path)\n const record = parsed as { kind?: unknown; tree?: { root?: unknown } }\n if (\n typeof record !== 'object' ||\n record === null ||\n typeof record.kind !== 'string' ||\n typeof record.tree !== 'object' ||\n record.tree === null ||\n typeof record.tree.root !== 'string'\n ) {\n throw new Error(`supervisePursuit: ${path} is not a settle record (no kind or tree.root)`)\n }\n return parsed as SupervisedResult<unknown>\n}\n\n/** Read the most recent failure record, or `undefined` when the directory holds none. */\nexport async function readFailureRecord(runDir: string): Promise<DurableFailureRecord | undefined> {\n return readTerminalFile(runDir, FAILURE_RECORD_FILE, (text, path) => {\n const parsed = parseTerminalJson(text, path)\n const record = parsed as Partial<DurableFailureRecord>\n if (\n typeof record !== 'object' ||\n record === null ||\n typeof record.runId !== 'string' ||\n typeof record.pursuitId !== 'string' ||\n typeof record.at !== 'string' ||\n typeof record.error?.name !== 'string' ||\n typeof record.error.message !== 'string' ||\n (record.rootStream !== undefined &&\n (typeof record.rootStream.ref !== 'string' || typeof record.rootStream.events !== 'number'))\n ) {\n throw new Error(`supervisePursuit: ${path} is not a failure record`)\n }\n return parsed as DurableFailureRecord\n })\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { m as ValidationError } from "./errors-AzSuGI23.js";
1
+ import { m as ValidationError } from "./errors-DG8yufqX.js";
2
2
  import { REDACTION_VERSION, redact } from "@tangle-network/agent-eval/traces";
3
3
  // src/redact.ts
4
4
  /**
@@ -45,7 +45,8 @@ function resolveRedactor(redact) {
45
45
  const maxCauseDepth = 4;
46
46
  const maxMessageLength = 32768;
47
47
  const maxPartLength = 2048;
48
- /** A persisted failure must explain its wrappers without exporting credentials or unbounded data. */
48
+ /** A persisted failure must explain its wrappers without exporting credentials or unbounded data.
49
+ * Redaction runs per line so one credential cannot erase the lines around it. */
49
50
  function errorText(value) {
50
51
  let text;
51
52
  try {
@@ -53,7 +54,7 @@ function errorText(value) {
53
54
  } catch {
54
55
  text = "[unprintable rejection]";
55
56
  }
56
- return String(defaultRedactor(text)).slice(0, maxMessageLength);
57
+ return text.split("\n").map((line) => String(defaultRedactor(line))).join("\n").slice(0, maxMessageLength);
57
58
  }
58
59
  function errorProperty(error, field) {
59
60
  try {
@@ -120,6 +121,19 @@ function causeChain(error) {
120
121
  }
121
122
  return chain;
122
123
  }
124
+ const maxStackFrames = 40;
125
+ /** The deepest cause's stack that has one, redacted and bounded to {@link maxStackFrames} frames,
126
+ * so a failure the messages alone cannot place still names its throw site (#2347). Outer
127
+ * wrappers' stacks are skipped: they restate the wrap site the record's own fields name. */
128
+ function errorStack(error) {
129
+ let found;
130
+ for (const value of causeChain(error)) {
131
+ if (!(value instanceof Error)) continue;
132
+ const stack = errorProperty(value, "stack");
133
+ if (stack !== void 0 && stack !== "[unreadable error stack]") found = stack;
134
+ }
135
+ return found === void 0 ? void 0 : found.split("\n").slice(0, maxStackFrames).join("\n");
136
+ }
123
137
  // src/runtime/supervise/snapshot.ts
124
138
  /** Deeply detach and freeze untrusted data at a runtime decision boundary. The clone prevents the
125
139
  * caller from mutating it later; the freeze prevents downstream code from mutating the snapshot.
@@ -205,6 +219,6 @@ function deepFreeze(value, seen = /* @__PURE__ */ new Set()) {
205
219
  for (const child of Object.values(value)) deepFreeze(child, seen);
206
220
  return Object.freeze(value);
207
221
  }
208
- export { errMessage as a, errorText as c, resolveRedactor as d, causeChain as i, defaultRedactor as l, detachedSnapshot as n, errorHttpStatus as o, shareParsedStrings as r, errorProperty as s, detachedFrozen as t, defaultRedactorIdentityMaterial as u };
222
+ export { errMessage as a, errorStack as c, defaultRedactorIdentityMaterial as d, resolveRedactor as f, causeChain as i, errorText as l, detachedSnapshot as n, errorHttpStatus as o, shareParsedStrings as r, errorProperty as s, detachedFrozen as t, defaultRedactor as u };
209
223
 
210
- //# sourceMappingURL=snapshot-Cgj2Wzi6.js.map
224
+ //# sourceMappingURL=snapshot-BKI_w3JD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-BKI_w3JD.js","names":[],"sources":["../src/redact.ts","../src/runtime/supervise/error-message.ts","../src/runtime/supervise/snapshot.ts"],"sourcesContent":["/**\n * Redaction for values that may leave the Runtime process. The built-in\n * redactor is agent-eval's redaction core (`@tangle-network/agent-eval/traces`,\n * default profile): credentials found by field name or value shape are\n * replaced whole, email, card, SSN and phone values in place, and token counts\n * such as `inputTokens` or `max_tokens` are kept. A customer with\n * domain-specific PII supplies their own `redact` hook.\n *\n * This is narrower than `src/sanitize.ts`, which drops fields of the runtime's\n * *event envelope* unless the caller opts in: here the value is opaque customer\n * payload, so the scrub is value-shaped, not schema-shaped.\n *\n * @experimental\n */\n\nimport { REDACTION_VERSION, redact } from '@tangle-network/agent-eval/traces'\n\n/** A redactor maps an arbitrary trace value to a safe-to-export value. Pure;\n * must not throw on cyclic input (the default tolerates cycles). */\nexport type Redactor = (value: unknown) => unknown\n\n/**\n * The built-in redactor. Cycle-safe, depth-bounded and total: it never throws\n * on customer input and never mutates it.\n */\nexport function defaultRedactor(value: unknown): unknown {\n return redact(value).value\n}\n\n/** Stable identity input for saved work that depends on built-in redaction behavior. */\nexport function defaultRedactorIdentityMaterial(): unknown {\n return {\n core: '@tangle-network/agent-eval/traces redact',\n profile: 'default',\n version: REDACTION_VERSION,\n }\n}\n\n/**\n * Resolve the redactor a client uses. A caller-supplied hook handles\n * domain-specific values first, then the built-in scrubber still removes\n * credentials and personal data. Returning `false` is the explicit opt-out for\n * already-reviewed public values.\n */\nexport function resolveRedactor(redact: Redactor | false | undefined): Redactor {\n if (redact === false) return (value) => value\n if (!redact) return defaultRedactor\n return (value) => defaultRedactor(redact(value))\n}\n","import { defaultRedactor } from '../../redact'\n\nconst maxCauseDepth = 4\nconst maxMessageLength = 32_768\nconst maxPartLength = 2_048\n\n/** A persisted failure must explain its wrappers without exporting credentials or unbounded data.\n * Redaction runs per line so one credential cannot erase the lines around it. */\nexport function errorText(value: unknown): string {\n let text: string\n try {\n text = typeof value === 'string' ? value : (JSON.stringify(value) ?? String(value))\n } catch {\n text = '[unprintable rejection]'\n }\n const lines = text.split('\\n').map((line) => String(defaultRedactor(line)))\n return lines.join('\\n').slice(0, maxMessageLength)\n}\n\nexport function errorProperty(\n error: Error,\n field: 'name' | 'message' | 'stack',\n): string | undefined {\n try {\n const value = error[field]\n return value === undefined\n ? undefined\n : errorText(value).slice(0, field === 'name' ? 256 : maxMessageLength)\n } catch {\n return `[unreadable error ${field}]`\n }\n}\n\n/** An HTTP status carried on a thrown error, read without trusting its getter. Provider SDKs put\n * one on their own error classes, so this is how a refusal is recognised outside the transport\n * taxonomy — for the persisted message here, and for the driver's retry verdict. */\nexport function errorHttpStatus(error: Error): number | undefined {\n try {\n const status: unknown = Reflect.get(error, 'status')\n return typeof status === 'number' && Number.isInteger(status) && status >= 100 && status <= 599\n ? status\n : undefined\n } catch {\n return undefined\n }\n}\n\n/** Shared by child settlements, driver attempts, and the final no-winner result. */\nexport function errMessage(error: unknown): string {\n const parts: string[] = []\n const seen = new Set<Error>()\n let current = error\n for (let depth = 0; depth <= maxCauseDepth; depth += 1) {\n try {\n if (!(current instanceof Error)) {\n parts.push(errorText(current).slice(0, maxPartLength))\n break\n }\n if (seen.has(current)) {\n parts.push('[circular]')\n break\n }\n seen.add(current)\n const status = errorHttpStatus(current)\n const message =\n (status === undefined ? '' : `HTTP ${status}: `) + (errorProperty(current, 'message') ?? '')\n // An AggregateError's members carry its evidence: name each, one level deep.\n const members: unknown = Reflect.get(current, 'errors')\n const named = Array.isArray(members)\n ? ` [${members.map((m) => (m instanceof Error ? `${errorProperty(m, 'name')}: ${errorProperty(m, 'message')}` : errorText(m))).join('; ')}]`\n : ''\n const part = depth === 0 ? message : `${errorProperty(current, 'name')}: ${message}`\n parts.push(`${part}${named}`.slice(0, maxPartLength))\n current = current.cause\n if (current === undefined || current === null) break\n if (depth === maxCauseDepth) parts.push('[cause chain truncated]')\n } catch {\n parts.push('[unreadable error cause]')\n break\n }\n }\n return parts.join(': caused by ').slice(0, maxMessageLength)\n}\n\n/** The error and its causes (`cause`, and `errors` members), bounded and cycle-safe. */\nexport function causeChain(error: unknown): object[] {\n const chain: object[] = []\n const queue: unknown[] = [error]\n while (queue.length > 0 && chain.length < 12) {\n const value = queue.shift()\n if (typeof value !== 'object' || value === null || chain.includes(value)) continue\n chain.push(value)\n try {\n const errors: unknown = Reflect.get(value, 'errors')\n if (Array.isArray(errors)) queue.push(...errors)\n queue.push(Reflect.get(value, 'cause'))\n } catch {\n // A cause that cannot be read ends this branch of the walk.\n }\n }\n return chain\n}\n\nconst maxStackFrames = 40\n\n/** The deepest cause's stack that has one, redacted and bounded to {@link maxStackFrames} frames,\n * so a failure the messages alone cannot place still names its throw site (#2347). Outer\n * wrappers' stacks are skipped: they restate the wrap site the record's own fields name. */\nexport function errorStack(error: unknown): string | undefined {\n let found: string | undefined\n for (const value of causeChain(error)) {\n if (!(value instanceof Error)) continue\n const stack = errorProperty(value, 'stack')\n if (stack !== undefined && stack !== '[unreadable error stack]') found = stack\n }\n return found === undefined ? undefined : found.split('\\n').slice(0, maxStackFrames).join('\\n')\n}\n","import { ValidationError } from '../../errors'\n\n/** Deeply detach and freeze untrusted data at a runtime decision boundary. The clone prevents the\n * caller from mutating it later; the freeze prevents downstream code from mutating the snapshot.\n * Strings are immutable, so the snapshot shares the caller's strings instead of copying them. */\nexport function detachedSnapshot<T>(value: T, context: string): T {\n let clone: T\n try {\n clone = structuredClone(value)\n } catch (error) {\n throw new ValidationError(`${context}: input must be structured-cloneable`, { cause: error })\n }\n return deepFreeze(shareSourceStrings(value, clone))\n}\n\n/** Detach a value from its caller and freeze it, without the `ValidationError` framing\n * {@link detachedSnapshot} adds. For a boundary that has already validated its input. */\nexport function detachedFrozen<T>(value: T): T {\n return deepFreeze(shareSourceStrings(value, structuredClone(value)))\n}\n\n/**\n * Point each string in a fresh structured clone at the equal string in its source.\n *\n * `structuredClone` copies every string, and a copied string buys no isolation: only objects and\n * arrays can change through a shared reference. A spawned profile passes several boundaries, and\n * each one kept its own copy: in a reproduction of Discovery's hosted coordinator, a child profile\n * that mounts a 5.3 MB file packet was held four times per spawned child. A scope keeps every\n * child it spawned, so the heap grew about 22 MB per spawn, and hosted coordinators died with V8\n * heap OOM after 37 spawns.\n *\n * The walk pairs only own data properties of plain objects and arrays. Accessors, Maps, Sets and\n * other cloned types keep the clone's values. A string is replaced only by a string equal to it,\n * so the snapshot holds exactly the clone's value. The snapshot keeps the source's strings alive.\n */\nfunction shareSourceStrings<T>(source: unknown, clone: T): T {\n const visited = new Set<object>()\n const visit = (from: unknown, to: unknown): void => {\n if (from === null || to === null || typeof from !== 'object' || typeof to !== 'object') return\n const array = Array.isArray(to)\n if (array !== Array.isArray(from)) return\n if (!array && Object.getPrototypeOf(to) !== Object.prototype) return\n if (visited.has(to)) return\n visited.add(to)\n const target = to as Record<string, unknown>\n for (const key of Object.keys(target)) {\n const own = Object.getOwnPropertyDescriptor(from, key)\n if (own === undefined || !('value' in own)) continue\n const cloned = target[key]\n if (typeof cloned === 'string') {\n if (own.value === cloned) target[key] = own.value\n } else visit(own.value, cloned)\n }\n }\n visit(source, clone)\n return clone\n}\n\n/**\n * Replace each string in a freshly parsed JSON value with an equal string already in `pool`, and\n * add the new ones. One recovery pass parses every interrupted child's profile from its own blob,\n * so children that carry the same file packet would otherwise hold one copy each. The value is\n * updated in place, so it must belong to the caller; frozen objects are left as they are.\n */\nexport function shareParsedStrings<T>(value: T, pool: Map<string, string>): T {\n const visit = (node: unknown): void => {\n if (node === null || typeof node !== 'object' || Object.isFrozen(node)) return\n if (!Array.isArray(node) && Object.getPrototypeOf(node) !== Object.prototype) return\n const target = node as Record<string, unknown>\n for (const key of Object.keys(target)) {\n const item = target[key]\n if (typeof item !== 'string') {\n visit(item)\n continue\n }\n const shared = pool.get(item)\n if (shared === undefined) pool.set(item, item)\n else target[key] = shared\n }\n }\n visit(value)\n return value\n}\n\nfunction deepFreeze<T>(value: T, seen = new Set<object>()): T {\n // `Object.freeze` throws `TypeError: Cannot freeze array buffer views with elements` on any\n // non-empty TypedArray or Buffer, so binary inside a payload must be handed back untouched\n // rather than frozen. Its bytes are already detached by the `structuredClone` above.\n if (value === null || typeof value !== 'object' || ArrayBuffer.isView(value) || seen.has(value)) {\n return value\n }\n seen.add(value)\n for (const child of Object.values(value as Record<string, unknown>)) deepFreeze(child, seen)\n return Object.freeze(value)\n}\n"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
- import { Br as executableAgentProfileSnapshot, Cr as knownMaterializationReceipt, Fr as runtimeOwnedPendingExecutorMaterialization, Mr as runtimeOwnedExecutorExecutionBinding, Nr as runtimeOwnedExecutorMaterialization, Rr as unknownExecutionBindingReceipt, Sr as knownExecutionBindingReceipt, ii as providerMessageText, ni as promptFromAgentTurnInput, qr as awaitAbortable, ri as promptOptionsFromAgentTurnInput, yr as authoredProfileDigest, zr as unknownMaterializationReceipt } from "./scope-gIYQ5ZiL.js";
2
- import { m as ValidationError, p as SessionMismatchError, r as BackendTransportError } from "./errors-AzSuGI23.js";
3
- import { I as armDeadlineTimer, c as errorMessage, f as isAsyncIterable } from "./util-C_cdPNC4.js";
4
- import { ct as canonicalStreamEventFromSandboxEvent, mt as createSandboxUsageLedger, n as runtimeFailureCause, nt as mapSandboxEvent, rt as mapSandboxToolEvent, st as terminalTextFromSandboxEvent, tt as createSandboxToolPartState } from "./failure-cause-BzjUUsRz.js";
5
- import { C as createExecutor, S as captureReusableExecutorConfig, _ as withDriverExecutor, an as readSandboxOutcome, b as createExecutorRegistry, in as projectSandboxOutcome, n as createSupervisor, v as InMemoryResultBlobStore, y as InMemorySpawnJournal } from "./supervisor-1A27fE6k.js";
6
- import { c as profileModelExecutionSettings, g as observedModelMatchesDeclared, i as concreteModelId, l as profileProviderModel, o as enforceTokenLimits, s as profileBridgeWireModel, t as assertExecutableAgentProfile } from "./model-policy-JOcg3NRs.js";
7
- import { z as sha256Bytes$1 } from "./workspace-streams-B7yNMahl.js";
1
+ import { $r as awaitAbortable, Br as runtimeOwnedPendingExecutorMaterialization, Dr as knownExecutionBindingReceipt, Gr as executableAgentProfileSnapshot, Lr as runtimeOwnedExecutorExecutionBinding, Or as knownMaterializationReceipt, Rr as runtimeOwnedExecutorMaterialization, Ur as unknownExecutionBindingReceipt, Wr as unknownMaterializationReceipt, di as providerMessageText, li as promptFromAgentTurnInput, ui as promptOptionsFromAgentTurnInput, wr as authoredProfileDigest } from "./supervisor-accounting-Bw4MJk-b.js";
2
+ import { m as ValidationError, p as SessionMismatchError, r as BackendTransportError } from "./errors-DG8yufqX.js";
3
+ import { I as armDeadlineTimer, c as errorMessage, f as isAsyncIterable } from "./util-fcckrkKp.js";
4
+ import { ct as terminalTextFromSandboxEvent, ht as createSandboxUsageLedger, it as mapSandboxToolEvent, lt as canonicalStreamEventFromSandboxEvent, n as runtimeFailureCause, nt as createSandboxToolPartState, rt as mapSandboxEvent } from "./failure-cause-CVB-YE88.js";
5
+ import { C as createExecutor, Qt as readSandboxOutcome, S as captureReusableExecutorConfig, Zt as projectSandboxOutcome, _ as withDriverExecutor, b as createExecutorRegistry, n as createSupervisor, v as InMemoryResultBlobStore, y as InMemorySpawnJournal } from "./supervisor-Dpeu7rnZ.js";
6
+ import { c as profileModelExecutionSettings, g as observedModelMatchesDeclared, i as concreteModelId, l as profileProviderModel, o as enforceTokenLimits, s as profileBridgeWireModel, t as assertExecutableAgentProfile } from "./model-policy-yxOrDTTj.js";
7
+ import { z as sha256Bytes$1 } from "./workspace-streams-DA9R3j-p.js";
8
8
  import { agentProfileSchema, canonicalAgentProfileDigest, canonicalCandidateDigest, renderInputPartsAsText } from "@tangle-network/agent-interface";
9
9
  import { costForTokenPricing, makeProposalFinding, scoreKnowledgeReadiness } from "@tangle-network/agent-eval";
10
10
  import { createAgentRunOutcomeTracker } from "@tangle-network/sandbox/runtime";
@@ -702,52 +702,16 @@ function deriveTurnSignal(callerSignal, timeoutMs) {
702
702
  }
703
703
  // src/runtime/stream-agent-turn.ts
704
704
  /**
705
- * `streamAgentTurn` — the ONE run-a-turn event-stream contract over every
706
- * execution substrate: a sandbox box (`SandboxInstance.streamPrompt`), a
707
- * one-shot Runtime-owned `Executor` (cli-bridge / router / sandbox, via
708
- * `ExecutorFactory`), and an in-process `AgentExecutionBackend`.
709
- *
710
- * One function, one vocabulary: every backend kind yields the existing
711
- * `RuntimeStreamEvent` union incrementally and ALWAYS terminates with a
712
- * `final` event whose `text` is the turn's final text and whose
713
- * `metadata.tokenUsage` / `metadata.costUsd` / `metadata.model` carry the
714
- * turn's metered usage. `collectAgentTurn` drains a stream into that terminal
715
- * summary plus the full event list.
716
- *
717
- * This is a UNIFICATION seam, not a new stream parser — each kind is a thin
718
- * adapter over code that already exists and is already hardened:
719
- * - `box` — `mapSandboxEvent` projects the sandbox event stream and one
720
- * `SandboxUsageLedger` (sandbox-events.ts) meters it, so a harness
721
- * that reports usage only in its own event is counted once per turn;
722
- * its requested profile is explicitly recorded as unverified because
723
- * the box already exists.
724
- * - `executor` — Runtime materializes the exact `AgentProfile`, records its
725
- * identity receipts, drives the executor once, and tears it
726
- * down after capturing the terminal artifact.
727
- * - `chat` — the backend's own `stream()` surface, normalized by
728
- * `normalizeBackendStreamEvent`; its requested profile is likewise
729
- * unverified because an arbitrary backend cannot attest its setup.
730
- *
731
- * Distinct from `openSandboxRun` (box-only, session resume over one persistent
732
- * artifact, raw `SandboxEvent` deliverables) and from `runAgentTaskStream`
733
- * (full task lifecycle: knowledge preflight, session store, resume). This is
734
- * the minimal turn primitive underneath both worlds: prompt in, one normalized
735
- * event stream out, terminal result+usage guaranteed on every non-thrown path.
736
- *
737
- * Stream envelope: `backend_start` → incremental events → (`backend_error` on
738
- * failure) → `final`. A caller-initiated abort terminates with
739
- * `final.status: 'aborted'`; an expired `timeoutMs` deadline with
740
- * `final.status: 'failed'` — so cancellation stays distinguishable from a
741
- * blown deadline.
742
- *
743
- * Mid-stream lifecycle work needs NO extra API: the generator is pull-based,
744
- * so the producer is suspended between yields and resumes only when the caller
745
- * pulls again. A consumer can therefore run arbitrary async work between
746
- * events — sync state on each `tool_result`, decide a no-op retry after
747
- * draining, run a pre-`done` flush when it receives `final` and BEFORE it
748
- * forwards its own terminal event downstream. The interleaving is guaranteed
749
- * (and locked by test): nothing is produced past the event the caller is
750
- * holding.
705
+ * `streamAgentTurn` is the one run-a-turn event stream for a sandbox box, a one-shot `Executor`,
706
+ * and an in-process `AgentExecutionBackend`. Every kind yields `RuntimeStreamEvent` and ends with
707
+ * `final` (`text`, `metadata.tokenUsage`, `metadata.costUsd`, `metadata.model`). `collectAgentTurn`
708
+ * drains that. `box` meters with one `SandboxUsageLedger` and records the requested profile
709
+ * unverified. `executor` materializes the `AgentProfile`, drives once, and tears down after the
710
+ * terminal artifact. `chat` normalizes `stream()` and is likewise unverified. This is not
711
+ * `openSandboxRun` or `runAgentTaskStream`. Envelope: `backend_start`, incremental events,
712
+ * `backend_error` on failure, then `final`. Abort ends `final.status: 'aborted'`; `timeoutMs`
713
+ * ends `final.status: 'failed'`. The generator is pull-based, so a consumer can work between events
714
+ * and nothing is produced past the event it holds.
751
715
  *
752
716
  * @stable
753
717
  */
@@ -904,6 +868,7 @@ async function* streamAgentTurnInternal(backend, input, opts) {
904
868
  }, {
905
869
  signal: deadline.signal,
906
870
  seams: {},
871
+ ...opts.propagatedHeaders ? { propagatedHeaders: opts.propagatedHeaders } : {},
907
872
  node: {
908
873
  rootId: nodeId,
909
874
  parentId: nodeId,
@@ -1104,7 +1069,9 @@ function materializedModel(receipt, profile) {
1104
1069
  // src/runtime/profile-chat-client.ts
1105
1070
  /** Profile-exact adapter for packages that consume agent-eval's ChatClient contract.
1106
1071
  * Every call still enters Runtime through createExecutor -> streamAgentTurn, and every
1107
- * behavioral field is checked against the exact AgentProfile before any transport runs. */
1072
+ * behavioral field is checked against the exact AgentProfile before any transport runs.
1073
+ * Optional `headers` are forwarded on every Router request. Runtime's own content-type,
1074
+ * authorization, idempotency-key, and x-correlation-id keep precedence. */
1108
1075
  function profileChatClient(args) {
1109
1076
  const binding = bindProfileChat(args);
1110
1077
  return {
@@ -1190,12 +1157,14 @@ function bindProfileChat(args) {
1190
1157
  const profile = executableAgentProfileSnapshot(args.profile, args.context);
1191
1158
  const model = concreteModelId(profile.model?.default);
1192
1159
  if (!model) throw new Error(`${args.context}: AgentProfile.model.default must be concrete`);
1160
+ const headers = callerRequestHeaders(args.headers, args.context);
1193
1161
  return {
1194
1162
  profile,
1195
1163
  executor: captureReusableExecutorConfig(args.executor, args.context),
1196
1164
  context: args.context,
1197
1165
  model,
1198
- settings: profileModelExecutionSettings(profile, args.context, args.executor.backend === "provider" ? "provider" : "router")
1166
+ settings: profileModelExecutionSettings(profile, args.context, args.executor.backend === "provider" ? "provider" : "router"),
1167
+ ...headers ? { headers } : {}
1199
1168
  };
1200
1169
  }
1201
1170
  async function runBoundProfileChat(binding, req, callOpts) {
@@ -1212,7 +1181,8 @@ async function runBoundProfileChat(binding, req, callOpts) {
1212
1181
  ...req.timeoutMs !== void 0 ? { timeoutMs: req.timeoutMs } : {},
1213
1182
  ...callOpts?.signal ? { signal: callOpts.signal } : {},
1214
1183
  ...callOpts?.idempotencyKey ? { callId: callOpts.idempotencyKey } : {},
1215
- ...callOpts?.correlationId ? { correlationId: callOpts.correlationId } : {}
1184
+ ...callOpts?.correlationId ? { correlationId: callOpts.correlationId } : {},
1185
+ ...binding.headers ? { propagatedHeaders: binding.headers } : {}
1216
1186
  }));
1217
1187
  if (turn.status !== "completed") return {
1218
1188
  succeeded: false,
@@ -1305,6 +1275,18 @@ function toolCarryingExecutor(binding, req) {
1305
1275
  tools
1306
1276
  }, binding.context);
1307
1277
  }
1278
+ /** Caller headers are a lowercase token map. Runtime overwrites its own connection headers later. */
1279
+ function callerRequestHeaders(headers, context) {
1280
+ if (headers === void 0) return void 0;
1281
+ if (headers === null || typeof headers !== "object" || Array.isArray(headers)) throw new Error(`${context}: headers must be an object of lowercase header names to strings`);
1282
+ const normalized = {};
1283
+ for (const [name, value] of Object.entries(headers)) {
1284
+ if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) throw new Error(`${context}: header name ${JSON.stringify(name)} must be a lowercase token such as x-tangle-client`);
1285
+ if (typeof value !== "string" || value.length === 0 || /[\r\n\0]/.test(value)) throw new Error(`${context}: header ${JSON.stringify(name)} must be one non-empty line`);
1286
+ normalized[name] = value;
1287
+ }
1288
+ return normalized;
1289
+ }
1308
1290
  function assertSupportedChatCallOptions(opts, context) {
1309
1291
  if (opts?.maxCostUsd !== void 0) throw new Error(`${context}: maxCostUsd is not enforced by Runtime's exact turn path; refusing to treat it as a limit`);
1310
1292
  }
@@ -3070,4 +3052,4 @@ function structuralRollout(config = {}) {
3070
3052
  }
3071
3053
  export { defaultAnalystInstruction as A, InMemoryRuntimeSessionStore as B, optimizerMethod as C, runAgentic as D, refine as E, collectAgentTurn as F, nowIso as H, streamAgentTurn as I, createIterableBackend as L, renderReport as M, profileChatClient as N, sample as O, profileOptimizerModelCall as P, createSandboxPromptBackend as R, strategyAuthorSystemPrompt as S, depthStrategy as T, startOrResumeRuntimeSession as U, newRuntimeSession as V, touchSession as W, defineStrategy as _, defaultStructuralRolloutPolicy as a, sampleThenRefine as b, officialChecksFromMeta as c, selectBestIndex as d, structuralRollout as f, authorStrategy as g, assertStrategyContract as h, defaultExtractCandidate as i, observe as j, ObservationError as k, resolveEntrySymbol as l, adaptiveRefine as m, compareCheckOutcomes as n, filterAuthoredAsserts as o, visibleCheckScore as p, composeCheckSources as r, modelAuthoredChecks as s, canDisplace as t, sandboxCheckRunner as u, loadAuthoredStrategy as v, breadthStrategy as w, strategyAuthorContract as x, requestStrategySource as y, normalizeBackendStreamEvent as z };
3072
3054
 
3073
- //# sourceMappingURL=structural-rollout-BwTwTUXF.js.map
3055
+ //# sourceMappingURL=structural-rollout-C1xxoWcN.js.map