@yielded/agent 0.1.0-beta.172 → 0.1.0-beta.174

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 (226) hide show
  1. package/dist/{Admin-BX9ns28E.d.mts → Admin-BHmp2V9p.d.mts} +25 -16
  2. package/dist/{Agent-9aBoIi74.d.mts → Agent-B39jRnFv.d.mts} +2 -2
  3. package/dist/{Agent-0WvBWWbM.mjs → Agent-BiRbr73L.mjs} +7 -6
  4. package/dist/Agent-BiRbr73L.mjs.map +1 -0
  5. package/dist/{AgentRuntime-CQ-qcETl.mjs → AgentRuntime-B6qZlD3f.mjs} +199 -191
  6. package/dist/AgentRuntime-B6qZlD3f.mjs.map +1 -0
  7. package/dist/{AgentRuntime-BfP14534.d.mts → AgentRuntime-BD3ZHAMq.d.mts} +10 -10
  8. package/dist/{Digest-DCuPlhNk.mjs → Digest-EpeqWEdv.mjs} +41 -14
  9. package/dist/Digest-EpeqWEdv.mjs.map +1 -0
  10. package/dist/{DurableAgentRuntime-BAmSkWYr.mjs → DurableAgentRuntime-CBBjRNJN.mjs} +1447 -1424
  11. package/dist/DurableAgentRuntime-CBBjRNJN.mjs.map +1 -0
  12. package/dist/{EventSource-BwliwQz9.d.mts → EventSource-C9aaJaXT.d.mts} +2 -2
  13. package/dist/{MessageDelivery-CeSDfHZa.d.mts → MessageDelivery-BGDm-c46.d.mts} +4 -4
  14. package/dist/{Messaging-C_6OOg_s.d.mts → Messaging-SVu6rWV8.d.mts} +12 -6
  15. package/dist/{MessagingHost-B8oKM7AC.d.mts → MessagingHost-C6SOAcoG.d.mts} +2 -2
  16. package/dist/{Output-Dsx6k52t.d.mts → Output-CRamN1Fy.d.mts} +2 -2
  17. package/dist/{PreparedInputAdmission-CxSJSiTl.d.mts → PreparedInputAdmission-BvDqlgiP.d.mts} +3 -3
  18. package/dist/{RunContinuation-DHYNAQFi.mjs → RunContinuation-4ZATcVLB.mjs} +113 -56
  19. package/dist/RunContinuation-4ZATcVLB.mjs.map +1 -0
  20. package/dist/{RunContinuation-FHM7XPjq.d.mts → RunContinuation-CTJ1jGrO.d.mts} +6 -6
  21. package/dist/{RunJournal-kfKVxJj7.mjs → RunJournal-CNZqA3Ge.mjs} +33 -5
  22. package/dist/RunJournal-CNZqA3Ge.mjs.map +1 -0
  23. package/dist/{RunOptions-D8zxFIrZ.d.mts → RunOptions-Be77lKVZ.d.mts} +2 -2
  24. package/dist/{RunStorage-uqPxps09.mjs → RunStorage-BHjuuERI.mjs} +9 -6
  25. package/dist/RunStorage-BHjuuERI.mjs.map +1 -0
  26. package/dist/{Scheduling-CVyfXlBR.mjs → Scheduling-NG8slKdI.mjs} +11 -11
  27. package/dist/Scheduling-NG8slKdI.mjs.map +1 -0
  28. package/dist/{Subagent-vpffemql.mjs → Subagent-CTIpnzlB.mjs} +53 -40
  29. package/dist/Subagent-CTIpnzlB.mjs.map +1 -0
  30. package/dist/{Subagent-E6tvd7-k.d.mts → Subagent-DKhZA72u.d.mts} +19 -8
  31. package/dist/{SubagentHost-B6w2m-SI.d.mts → SubagentHost-D1xBgn9g.d.mts} +2 -2
  32. package/dist/{Subscription-DONig54Q.d.mts → Subscription-BNg9VCRl.d.mts} +2 -2
  33. package/dist/{SubscriptionInput-mJIRxWJM.d.mts → SubscriptionInput-BUoXv-_K.d.mts} +2 -2
  34. package/dist/{ThreadImport-CoQTZywm.d.mts → ThreadImport-CMgzttvr.d.mts} +43 -43
  35. package/dist/{ThreadImport-DckUMEqJ.mjs → ThreadImport-CodYoJoa.mjs} +7 -7
  36. package/dist/ThreadImport-CodYoJoa.mjs.map +1 -0
  37. package/dist/{ThreadStore-CEekRa80.mjs → ThreadStore-59uDGXul.mjs} +163 -84
  38. package/dist/ThreadStore-59uDGXul.mjs.map +1 -0
  39. package/dist/{ThreadTransfer-B4gTQLIl.mjs → ThreadTransfer-3jigUl3g.mjs} +3 -3
  40. package/dist/{ThreadTransfer-B4gTQLIl.mjs.map → ThreadTransfer-3jigUl3g.mjs.map} +1 -1
  41. package/dist/{WorkerAdmission-DFVbbVh2.mjs → WorkerAdmission-DDYJdOsU.mjs} +4 -4
  42. package/dist/{WorkerAdmission-DFVbbVh2.mjs.map → WorkerAdmission-DDYJdOsU.mjs.map} +1 -1
  43. package/dist/{agent-registration-ByMZ_cK5.mjs → agent-registration-DRbyhAu-.mjs} +69 -56
  44. package/dist/agent-registration-DRbyhAu-.mjs.map +1 -0
  45. package/dist/capabilities/Approval.mjs +2 -2
  46. package/dist/capabilities/Approval.mjs.map +1 -1
  47. package/dist/capabilities/BrowserUse.d.mts +102 -1867
  48. package/dist/capabilities/BrowserUse.mjs +74 -798
  49. package/dist/capabilities/BrowserUse.mjs.map +1 -1
  50. package/dist/capabilities/Budget.mjs +3 -1
  51. package/dist/capabilities/Budget.mjs.map +1 -1
  52. package/dist/capabilities/CodeMode.d.mts +1 -1
  53. package/dist/capabilities/CodeMode.mjs +16 -9
  54. package/dist/capabilities/CodeMode.mjs.map +1 -1
  55. package/dist/capabilities/Commands.d.mts +1 -1
  56. package/dist/capabilities/McpClient.mjs +1 -1
  57. package/dist/capabilities/McpClient.mjs.map +1 -1
  58. package/dist/capabilities/Messaging.d.mts +1 -1
  59. package/dist/capabilities/Messaging.mjs +4 -4
  60. package/dist/capabilities/Messaging.mjs.map +1 -1
  61. package/dist/capabilities/ModelContext.mjs +7 -5
  62. package/dist/capabilities/ModelContext.mjs.map +1 -1
  63. package/dist/capabilities/Redaction.mjs +49 -19
  64. package/dist/capabilities/Redaction.mjs.map +1 -1
  65. package/dist/capabilities/RunHooks.d.mts +1 -1
  66. package/dist/capabilities/RunHooks.mjs +1 -1
  67. package/dist/capabilities/RunHooks.mjs.map +1 -1
  68. package/dist/capabilities/Subagent.d.mts +1 -1
  69. package/dist/capabilities/Subagent.mjs +1 -1
  70. package/dist/capabilities/SubagentReservations.mjs +3 -1
  71. package/dist/capabilities/SubagentReservations.mjs.map +1 -1
  72. package/dist/capabilities/WebCapture.mjs.map +1 -1
  73. package/dist/capabilities/WebSearch.mjs +7 -7
  74. package/dist/capabilities/WebSearch.mjs.map +1 -1
  75. package/dist/core/Agent.d.mts +1 -1
  76. package/dist/core/Agent.mjs +1 -1
  77. package/dist/core/AgentUpdates.mjs +8 -8
  78. package/dist/core/AgentUpdates.mjs.map +1 -1
  79. package/dist/core/Thread.mjs +1 -1
  80. package/dist/core/Thread.mjs.map +1 -1
  81. package/dist/core/Usage.mjs +2 -2
  82. package/dist/core/Usage.mjs.map +1 -1
  83. package/dist/durable/Admin.d.mts +1 -1
  84. package/dist/durable/AgentRegistration.d.mts +1 -1
  85. package/dist/durable/AgentRegistration.mjs +1 -1
  86. package/dist/durable/Certification.d.mts +1 -1
  87. package/dist/durable/CommittedActivity.d.mts +1 -1
  88. package/dist/durable/CommittedActivity.mjs +2 -2
  89. package/dist/durable/Digest.mjs +1 -1
  90. package/dist/durable/DurableAgentRuntime.d.mts +1 -1
  91. package/dist/durable/DurableAgentRuntime.mjs +2 -2
  92. package/dist/durable/EventSource.d.mts +1 -1
  93. package/dist/durable/EventSource.mjs +6 -6
  94. package/dist/durable/EventSource.mjs.map +1 -1
  95. package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
  96. package/dist/durable/LifecyclePublication.d.mts +1 -1
  97. package/dist/durable/LifecyclePublication.mjs +1 -1
  98. package/dist/durable/MessageDelivery.d.mts +1 -1
  99. package/dist/durable/MessageDelivery.mjs +1 -1
  100. package/dist/durable/MessageDeliveryStoreConformance.d.mts +2 -2
  101. package/dist/durable/MessageDeliveryStoreConformance.mjs +1 -1
  102. package/dist/durable/PersistentHistory.d.mts +1 -1
  103. package/dist/durable/PersistentHistory.mjs +3 -3
  104. package/dist/durable/PreparedInputAdmission.d.mts +1 -1
  105. package/dist/durable/RecordFormat.mjs +2 -2
  106. package/dist/durable/RecordFormat.mjs.map +1 -1
  107. package/dist/durable/Recovery.d.mts +1 -1
  108. package/dist/durable/RunContinuation.d.mts +2 -2
  109. package/dist/durable/RunContinuation.mjs +2 -2
  110. package/dist/durable/RunJournal.d.mts +1 -1
  111. package/dist/durable/RunJournal.mjs +1 -1
  112. package/dist/durable/RunStorage.d.mts +1 -1
  113. package/dist/durable/RunStorage.mjs +1 -1
  114. package/dist/durable/Scheduling.d.mts +1 -1
  115. package/dist/durable/Scheduling.mjs +1 -1
  116. package/dist/durable/SettlementPublisher.d.mts +1 -1
  117. package/dist/durable/SettlementPublisher.mjs +2 -2
  118. package/dist/durable/SubmissionLedger.d.mts +1 -1
  119. package/dist/durable/SubmissionLedger.mjs +5 -1
  120. package/dist/durable/SubmissionLedger.mjs.map +1 -1
  121. package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
  122. package/dist/durable/SubmissionLedgerConformance.mjs +4 -4
  123. package/dist/durable/SubmissionStatus.d.mts +1 -1
  124. package/dist/durable/Subscription.d.mts +1 -1
  125. package/dist/durable/SubscriptionInput.d.mts +1 -1
  126. package/dist/durable/SubscriptionInput.mjs +3 -3
  127. package/dist/durable/SubscriptionInput.mjs.map +1 -1
  128. package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
  129. package/dist/durable/SubscriptionStoreConformance.mjs +2 -2
  130. package/dist/durable/SubscriptionStoreConformance.mjs.map +1 -1
  131. package/dist/durable/SubscriptionTools.d.mts +2 -2
  132. package/dist/durable/SubscriptionTransition.d.mts +1 -1
  133. package/dist/durable/Subscriptions.d.mts +5 -5
  134. package/dist/durable/Subscriptions.mjs +2 -2
  135. package/dist/durable/Subscriptions.mjs.map +1 -1
  136. package/dist/durable/ThreadArchiveRange.d.mts +1 -1
  137. package/dist/durable/ThreadContextHistory.d.mts +1 -1
  138. package/dist/durable/ThreadContextHistory.mjs +1 -1
  139. package/dist/durable/ThreadImport.d.mts +1 -1
  140. package/dist/durable/ThreadImport.mjs +1 -1
  141. package/dist/durable/ThreadInvariants.d.mts +3 -3
  142. package/dist/durable/ThreadInvariants.mjs +4 -4
  143. package/dist/durable/ThreadInvariants.mjs.map +1 -1
  144. package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
  145. package/dist/durable/ThreadReader.d.mts +1 -1
  146. package/dist/durable/ThreadReader.mjs +1 -1
  147. package/dist/durable/ThreadStore.d.mts +1 -1
  148. package/dist/durable/ThreadStore.mjs +1 -1
  149. package/dist/durable/ThreadStoreConformance.d.mts +1 -1
  150. package/dist/durable/ThreadStoreConformance.mjs +3 -3
  151. package/dist/durable/ThreadTransfer.d.mts +1 -1
  152. package/dist/durable/ThreadTransfer.mjs +1 -1
  153. package/dist/durable/ThreadWork.d.mts +1 -1
  154. package/dist/durable/ThreadWork.mjs +4 -4
  155. package/dist/durable/ThreadWork.mjs.map +1 -1
  156. package/dist/durable/WorkerAdmission.d.mts +1 -1
  157. package/dist/durable/WorkerAdmission.mjs +1 -1
  158. package/dist/durable/WorkerHost.d.mts +2 -2
  159. package/dist/engine/AgentRuntime.d.mts +1 -1
  160. package/dist/engine/AgentRuntime.mjs +1 -1
  161. package/dist/engine/MessagingHost.d.mts +1 -1
  162. package/dist/engine/Output.d.mts +1 -1
  163. package/dist/engine/RunOptions.d.mts +1 -1
  164. package/dist/engine/SubagentHost.d.mts +1 -1
  165. package/dist/index.d.mts +19 -19
  166. package/dist/index.mjs +14 -14
  167. package/dist/{run-context-reader-OcsZr4bk.d.mts → run-context-reader-CC7ZD95F.d.mts} +2 -2
  168. package/package.json +1 -1
  169. package/src/capabilities/Approval.ts +58 -60
  170. package/src/capabilities/BrowserUse.ts +89 -944
  171. package/src/capabilities/Budget.ts +8 -1
  172. package/src/capabilities/CodeMode.ts +57 -33
  173. package/src/capabilities/McpClient.ts +2 -2
  174. package/src/capabilities/Messaging.ts +51 -55
  175. package/src/capabilities/ModelContext.ts +5 -2
  176. package/src/capabilities/Redaction.ts +64 -34
  177. package/src/capabilities/RunHooks.ts +52 -55
  178. package/src/capabilities/Subagent.ts +33 -33
  179. package/src/capabilities/SubagentReservations.ts +9 -1
  180. package/src/capabilities/WebCapture.ts +6 -0
  181. package/src/capabilities/WebSearch.ts +10 -7
  182. package/src/capabilities/internal/subagent-background.ts +202 -158
  183. package/src/core/Agent.ts +11 -6
  184. package/src/core/AgentUpdates.ts +8 -8
  185. package/src/core/Thread.ts +9 -10
  186. package/src/core/Usage.ts +7 -8
  187. package/src/core/internal/agent-updates.ts +1 -0
  188. package/src/durable/DurableAgentRuntime.ts +645 -625
  189. package/src/durable/EventSource.ts +15 -9
  190. package/src/durable/RecordFormat.ts +5 -3
  191. package/src/durable/RunContinuation.ts +233 -81
  192. package/src/durable/RunJournal.ts +10 -9
  193. package/src/durable/RunStorage.ts +122 -124
  194. package/src/durable/Scheduling.ts +639 -651
  195. package/src/durable/SubmissionLedger.ts +4 -0
  196. package/src/durable/SubscriptionInput.ts +5 -3
  197. package/src/durable/SubscriptionStoreConformance.ts +23 -23
  198. package/src/durable/Subscriptions.ts +18 -19
  199. package/src/durable/ThreadImport.ts +18 -19
  200. package/src/durable/ThreadInvariants.ts +2 -1
  201. package/src/durable/ThreadStore.ts +215 -111
  202. package/src/durable/ThreadWork.ts +1 -2
  203. package/src/durable/internal/StorageOwner.ts +10 -4
  204. package/src/durable/internal/agent-registration.ts +96 -89
  205. package/src/durable/internal/canonical-json.ts +61 -20
  206. package/src/durable/internal/prompt-history-cache.ts +13 -4
  207. package/src/durable/internal/record-encoding.ts +120 -64
  208. package/src/durable/internal/schedule-time.ts +6 -6
  209. package/src/durable/internal/usage-totals.ts +38 -0
  210. package/src/durable/internal/worker-host.ts +69 -74
  211. package/src/engine/internal/agent-runtime.ts +1067 -1018
  212. package/src/engine/internal/provisional-text.ts +12 -10
  213. package/src/engine/internal/tool-exposure.ts +22 -18
  214. package/src/engine/internal/tool-telemetry.ts +12 -7
  215. package/dist/Agent-0WvBWWbM.mjs.map +0 -1
  216. package/dist/AgentRuntime-CQ-qcETl.mjs.map +0 -1
  217. package/dist/Digest-DCuPlhNk.mjs.map +0 -1
  218. package/dist/DurableAgentRuntime-BAmSkWYr.mjs.map +0 -1
  219. package/dist/RunContinuation-DHYNAQFi.mjs.map +0 -1
  220. package/dist/RunJournal-kfKVxJj7.mjs.map +0 -1
  221. package/dist/RunStorage-uqPxps09.mjs.map +0 -1
  222. package/dist/Scheduling-CVyfXlBR.mjs.map +0 -1
  223. package/dist/Subagent-vpffemql.mjs.map +0 -1
  224. package/dist/ThreadImport-DckUMEqJ.mjs.map +0 -1
  225. package/dist/ThreadStore-CEekRa80.mjs.map +0 -1
  226. package/dist/agent-registration-ByMZ_cK5.mjs.map +0 -1
@@ -262,6 +262,11 @@ const pruneRetiredHierarchy = (
262
262
  return nodes;
263
263
  };
264
264
 
265
+ /** Internal lifetime misuse remains a defect, with an Error message and stack. */
266
+ class RetiredBudgetHandle extends Schema.TaggedError<RetiredBudgetHandle>()("RetiredBudgetHandle", {
267
+ message: Schema.String,
268
+ }) {}
269
+
265
270
  const makeNode = (
266
271
  ledger: Ref.Ref<BudgetLedger>,
267
272
  key: string,
@@ -273,7 +278,9 @@ const makeNode = (
273
278
 
274
279
  const retiredDefect = () =>
275
280
  Effect.die(
276
- new Error(`Usage budget handle ${config.level}:${config.id} was used after retirement`),
281
+ RetiredBudgetHandle.make({
282
+ message: `Usage budget handle ${config.level}:${config.id} was used after retirement`,
283
+ }),
277
284
  );
278
285
 
279
286
  const liveHierarchy = (state: BudgetLedger): ReadonlyArray<LedgerNode> | undefined => {
@@ -300,11 +300,16 @@ const renderJsonSchemaType = (
300
300
  indent: string,
301
301
  ): string => {
302
302
  if (depth > MAX_RENDER_DEPTH) {
303
+ // oxlint-disable-next-line effect/no-untyped-throw, effect/no-native-error -- CodeMode.make synchronously bounds recursive Schema declaration rendering before creating the Tool.
303
304
  throw new Error("Code Mode declaration rendering exceeded its depth bound");
304
305
  }
305
306
  if (!isJsonSchemaRecord(schema)) {
307
+ // oxlint-disable-next-line effect/no-untyped-throw, effect/no-native-error -- CodeMode.make synchronously rejects unsupported JSON Schema declaration fragments.
306
308
  throw new Error(`Code Mode cannot render the JSON schema fragment ${JSON.stringify(schema)}`);
307
309
  }
310
+ // An empty schema is explicitly unconstrained, including Schema.Json's array items.
311
+ // This is a faithful declaration; unrecognized nonempty fragments still fail below.
312
+ if (Object.keys(schema).length === 0) return "unknown";
308
313
  const reference = schema.$ref;
309
314
 
310
315
  if (typeof reference === "string") {
@@ -314,6 +319,7 @@ const renderJsonSchemaType = (
314
319
  const resolved = key === undefined ? undefined : defs[key];
315
320
 
316
321
  if (resolved === undefined) {
322
+ // oxlint-disable-next-line effect/no-untyped-throw, effect/no-native-error -- CodeMode.make synchronously rejects unresolved declaration references.
317
323
  throw new Error(`Code Mode cannot resolve the JSON schema reference ${reference}`);
318
324
  }
319
325
 
@@ -353,6 +359,7 @@ const renderJsonSchemaType = (
353
359
  }
354
360
  case "array": {
355
361
  if (!("items" in schema)) {
362
+ // oxlint-disable-next-line effect/no-untyped-throw, effect/no-native-error -- CodeMode.make synchronously requires item schemas for array declarations.
356
363
  throw new Error("Code Mode cannot render an array schema without items");
357
364
  }
358
365
 
@@ -398,6 +405,7 @@ const renderJsonSchemaType = (
398
405
  break;
399
406
  }
400
407
  }
408
+ // oxlint-disable-next-line effect/no-untyped-throw, effect/no-native-error -- CodeMode.make synchronously rejects declaration schemas it cannot faithfully render.
401
409
  throw new Error(
402
410
  `Code Mode cannot render the JSON schema fragment ${JSON.stringify(schema).slice(0, 200)}; fix or simplify the Tool's Schema`,
403
411
  );
@@ -420,8 +428,26 @@ interface ResolvedMethod {
420
428
  readonly tool: Tool.Any;
421
429
  }
422
430
 
423
- const renderDeclarations = (methods: ReadonlyArray<ResolvedMethod>): string => {
424
- const namespaces = new Map<string, Array<ResolvedMethod>>();
431
+ interface RenderedMethod extends ResolvedMethod {
432
+ readonly declaration: string;
433
+ }
434
+
435
+ /** Render once at the synchronous construction boundary; describe only selects frozen declarations. */
436
+ const renderMethodDeclaration = (method: string, tool: Tool.Any): string => {
437
+ const parameters = renderTopLevel(Tool.getJsonSchema(tool), " ");
438
+ const success = renderTopLevel(Tool.getJsonSchemaFromSchema(tool.successSchema), " ");
439
+
440
+ // A description is arbitrary text: newlines and comment terminators
441
+ // must not be able to break out of the documentation comment.
442
+ const safeDescription = tool.description?.replaceAll("*/", "*\\/").replaceAll(/\s*\n\s*/g, " ");
443
+
444
+ const description = safeDescription === undefined ? "" : ` /** ${safeDescription} */\n`;
445
+
446
+ return `${description} ${method}(input: ${parameters}): Promise<${success}>;`;
447
+ };
448
+
449
+ const renderDeclarations = (methods: ReadonlyArray<RenderedMethod>): string => {
450
+ const namespaces = new Map<string, Array<RenderedMethod>>();
425
451
 
426
452
  for (const method of methods) {
427
453
  const existing = namespaces.get(method.namespace) ?? [];
@@ -431,20 +457,7 @@ const renderDeclarations = (methods: ReadonlyArray<ResolvedMethod>): string => {
431
457
  }
432
458
 
433
459
  const blocks = [...namespaces.entries()].map(([namespace, members]) => {
434
- const lines = members.map((member) => {
435
- const parameters = renderTopLevel(Tool.getJsonSchema(member.tool), " ");
436
- const success = renderTopLevel(Tool.getJsonSchemaFromSchema(member.tool.successSchema), " ");
437
-
438
- // A description is arbitrary text: newlines and comment terminators
439
- // must not be able to break out of the documentation comment.
440
- const safeDescription = member.tool.description
441
- ?.replaceAll("*/", "*\\/")
442
- .replaceAll(/\s*\n\s*/g, " ");
443
-
444
- const description = safeDescription === undefined ? "" : ` /** ${safeDescription} */\n`;
445
-
446
- return `${description} ${member.method}(input: ${parameters}): Promise<${success}>;`;
447
- });
460
+ const lines = members.map((member) => member.declaration);
448
461
 
449
462
  return `declare const ${namespace}: {\n${lines.join("\n")}\n};`;
450
463
  });
@@ -581,6 +594,7 @@ const make = <
581
594
  maxEgressBytes < 256 ||
582
595
  maxEgressBytes > 4 * 1024 * 1024
583
596
  ) {
597
+ // oxlint-disable-next-line effect/no-untyped-throw, effect/no-native-error -- CodeMode.make synchronously rejects invalid egress bounds before creating the Tool.
584
598
  throw new Error(
585
599
  `Code Mode maxEgressBytes must be an integer between 256 and ${4 * 1024 * 1024}; received ${String(maxEgressBytes)}`,
586
600
  );
@@ -593,15 +607,18 @@ const make = <
593
607
 
594
608
  for (const [namespace, namespaceMethods] of Object.entries(options.tools)) {
595
609
  if (Option.isNone(decodeIdentifier(namespace))) {
610
+ // oxlint-disable-next-line effect/no-untyped-throw, effect/no-native-error -- CodeMode.make synchronously requires valid JavaScript namespace identifiers.
596
611
  throw new Error(`Code Mode namespace ${namespace} is not a valid JavaScript identifier`);
597
612
  }
598
613
  const entries = Object.entries(namespaceMethods);
599
614
 
600
615
  if (entries.length === 0) {
616
+ // oxlint-disable-next-line effect/no-untyped-throw, effect/no-native-error -- CodeMode.make synchronously rejects namespaces without callable methods.
601
617
  throw new Error(`Code Mode namespace ${namespace} declares no methods`);
602
618
  }
603
619
  for (const [method, tool] of entries) {
604
620
  if (Option.isNone(decodeIdentifier(method))) {
621
+ // oxlint-disable-next-line effect/no-untyped-throw, effect/no-native-error -- CodeMode.make synchronously requires valid JavaScript method identifiers.
605
622
  throw new Error(
606
623
  `Code Mode method ${namespace}.${method} is not a valid JavaScript identifier`,
607
624
  );
@@ -609,6 +626,7 @@ const make = <
609
626
  const approval = tool.needsApproval;
610
627
 
611
628
  if (approval !== undefined && approval !== false) {
629
+ // oxlint-disable-next-line effect/no-untyped-throw, effect/no-native-error -- CodeMode.make synchronously rejects approval-requiring Tools from its programmatic allowlist.
612
630
  throw new Error(
613
631
  `Code Mode rejects Tool ${tool.name} (${namespace}.${method}): approval-requiring Tools cannot be invoked programmatically in the ephemeral slice`,
614
632
  );
@@ -616,6 +634,7 @@ const make = <
616
634
  const existing = toolsByName.get(tool.name);
617
635
 
618
636
  if (existing !== undefined && existing !== tool) {
637
+ // oxlint-disable-next-line effect/no-untyped-throw, effect/no-native-error -- CodeMode.make synchronously rejects conflicting Tools sharing one name.
619
638
  throw new Error(
620
639
  `Code Mode selected two different Tools named ${tool.name}; Tool names must identify one Tool`,
621
640
  );
@@ -626,15 +645,21 @@ const make = <
626
645
  }
627
646
  }
628
647
  if (methods.length === 0) {
648
+ // oxlint-disable-next-line effect/no-untyped-throw, effect/no-native-error -- CodeMode.make synchronously requires a nonempty Tool allowlist.
629
649
  throw new Error("Code Mode requires at least one allowlisted Tool");
630
650
  }
631
651
 
632
652
  // Declarations derive from the encoded Schemas and fail construction closed
633
653
  // on anything the renderer cannot express.
634
- const declarations = renderDeclarations(methods);
654
+ const renderedMethods = methods.map((method): RenderedMethod => ({
655
+ ...method,
656
+ declaration: renderMethodDeclaration(method.method, method.tool),
657
+ }));
658
+
659
+ const declarations = renderDeclarations(renderedMethods);
635
660
 
636
661
  const methodsByPath = new Map(
637
- methods.map((method) => [`${method.namespace}.${method.method}`, method]),
662
+ renderedMethods.map((method) => [`${method.namespace}.${method.method}`, method]),
638
663
  );
639
664
 
640
665
  const describe = Effect.fnUntraced(function* (
@@ -662,7 +687,7 @@ const make = <
662
687
  ),
663
688
  );
664
689
 
665
- const selectedMethods: Array<ResolvedMethod> = [];
690
+ const selectedMethods: Array<RenderedMethod> = [];
666
691
 
667
692
  for (const path of paths) {
668
693
  const method = methodsByPath.get(path);
@@ -799,7 +824,13 @@ const make = <
799
824
  });
800
825
 
801
826
  const build = Effect.gen(function* () {
802
- const captured = yield* Effect.context<never>();
827
+ const captured =
828
+ yield* Effect.context<
829
+ Tool.HandlerServices<
830
+ CodeModeSelectedRecord<Namespaces>[keyof CodeModeSelectedRecord<Namespaces>]
831
+ >
832
+ >();
833
+
803
834
  const redactionServices = yield* Effect.context<Exclude<RedactionRequirements, Scope.Scope>>();
804
835
  const configuredRedactor = options.redactEgress;
805
836
 
@@ -975,20 +1006,10 @@ const make = <
975
1006
  );
976
1007
  }).pipe(
977
1008
  Effect.scoped,
978
- // The live engine broker is re-provided innermost so a Layer built
979
- // inside another Run can never shadow it; the captured construction
980
- // context supplies the selected handlers' services (same idiom as
981
- // Subagent.layer). TypeScript cannot reduce the deferred Exclude
982
- // over the generic namespace record, so the same private-assertion
983
- // contract as the engine's provideHookServices pins the identity
984
- // that providing the captured Context leaves no requirements; it
985
- // never bypasses validation.
1009
+ // Keep invocation authority innermost while restoring the declared handler services.
986
1010
  Effect.provideService(ToolBroker, broker),
987
- Effect.provideContext(captured),
988
- ) as Effect.Effect<
989
- CodeExecutionResult,
990
- CodeExecutionError | ToolBrokerUnavailableError | ToolBrokerConfigurationError
991
- >;
1011
+ Effect.updateContext((current: Context.Context<never>) => Context.merge(current, captured)),
1012
+ );
992
1013
 
993
1014
  return yield* execution.pipe(
994
1015
  Effect.catch((error) => failureEgress(error).pipe(Effect.flatMap(Effect.fail))),
@@ -1052,6 +1073,9 @@ const make = <
1052
1073
  never,
1053
1074
  | CodeExecutor
1054
1075
  | Tool.HandlersFor<CodeModeSelectedRecord<Namespaces>>
1076
+ | Tool.HandlerServices<
1077
+ CodeModeSelectedRecord<Namespaces>[keyof CodeModeSelectedRecord<Namespaces>]
1078
+ >
1055
1079
  | Exclude<RedactionRequirements, Scope.Scope>
1056
1080
  >,
1057
1081
  ) as unknown as Layer.Layer<
@@ -141,8 +141,8 @@ const isNotificationTag = (tag: string): boolean => tag.startsWith("notification
141
141
  const isRpcClientError = Schema.is(RpcClientError.RpcClientError);
142
142
 
143
143
  const protocolDefect = (message: string, cause?: unknown): RpcClientError.RpcClientError =>
144
- new RpcClientError.RpcClientError({
145
- reason: new RpcClientError.RpcClientDefect({ message, cause }),
144
+ RpcClientError.RpcClientError.make({
145
+ reason: RpcClientError.RpcClientDefect.make({ message, cause }),
146
146
  });
147
147
 
148
148
  const InitializeProtocolVersion = Schema.Struct({ protocolVersion: Schema.String });
@@ -41,47 +41,46 @@ const host: Effect.Effect<MessagingHost["Service"], MessagingError, MessagingHos
41
41
  ),
42
42
  );
43
43
 
44
- const dispatch = <Name extends string, Input extends Schema.Top>(
44
+ const dispatch = Effect.fnUntraced(function* <Name extends string, Input extends Schema.Top>(
45
45
  declaration: Peer<Name, Input>,
46
46
  input: Input["Type"],
47
47
  options: { readonly idempotencyKey: IdempotencyKey; readonly inReplyTo?: MessageRef },
48
48
  operation: "send" | "reply",
49
- ) =>
50
- Effect.gen(function* () {
51
- const service = yield* host;
52
- const invalid = () => MessagingError.make({ operation, reason: "invalid-input" });
53
-
54
- const idempotencyKey = yield* Schema.decodeEffect(IdempotencyKey)(options.idempotencyKey).pipe(
55
- Effect.mapError(invalid),
56
- );
57
-
58
- const encodedInput = yield* Schema.encodeEffect(declaration.target.input)(input).pipe(
59
- Effect.mapError(invalid),
60
- );
61
-
62
- const inReplyTo =
63
- options.inReplyTo === undefined
64
- ? undefined
65
- : yield* Schema.decodeEffect(MessageRef)(options.inReplyTo).pipe(Effect.mapError(invalid));
66
-
67
- const request = {
68
- ...declaration,
69
- encodedInput,
70
- idempotencyKey,
71
- ...(inReplyTo === undefined ? {} : { inReplyTo }),
72
- };
73
-
74
- const result =
75
- operation === "reply"
76
- ? inReplyTo === undefined
77
- ? yield* invalid()
78
- : yield* service.reply({ ...request, inReplyTo })
79
- : yield* service.send(request);
80
-
81
- return yield* Schema.decodeEffect(MessageStatus)(result).pipe(
82
- Effect.mapError(() => MessagingError.make({ operation, reason: "corrupt" })),
83
- );
84
- });
49
+ ) {
50
+ const service = yield* host;
51
+ const invalid = () => MessagingError.make({ operation, reason: "invalid-input" });
52
+
53
+ const idempotencyKey = yield* Schema.decodeEffect(IdempotencyKey)(options.idempotencyKey).pipe(
54
+ Effect.mapError(invalid),
55
+ );
56
+
57
+ const encodedInput = yield* Schema.encodeEffect(declaration.target.input)(input).pipe(
58
+ Effect.mapError(invalid),
59
+ );
60
+
61
+ const inReplyTo =
62
+ options.inReplyTo === undefined
63
+ ? undefined
64
+ : yield* Schema.decodeEffect(MessageRef)(options.inReplyTo).pipe(Effect.mapError(invalid));
65
+
66
+ const request = {
67
+ ...declaration,
68
+ encodedInput,
69
+ idempotencyKey,
70
+ ...(inReplyTo === undefined ? {} : { inReplyTo }),
71
+ };
72
+
73
+ const result =
74
+ operation === "reply"
75
+ ? inReplyTo === undefined
76
+ ? yield* invalid()
77
+ : yield* service.reply({ ...request, inReplyTo })
78
+ : yield* service.send(request);
79
+
80
+ return yield* Schema.decodeEffect(MessageStatus)(result).pipe(
81
+ Effect.mapError(() => MessagingError.make({ operation, reason: "corrupt" })),
82
+ );
83
+ });
85
84
 
86
85
  /** Retain a durable message. Its status distinguishes outbound retention from destination acceptance. */
87
86
  export const send = <Name extends string, Input extends Schema.Top>(
@@ -99,36 +98,33 @@ export const reply = <Name extends string, Input extends Schema.Top>(
99
98
  ) => dispatch(declaration, input, { ...options, inReplyTo }, "reply");
100
99
 
101
100
  /** Return bounded provenance for messages from this peer, without granting permission to reply. */
102
- export const inbox = <Name extends string, Input extends Schema.Top>(
101
+ export const inbox = Effect.fnUntraced(function* <Name extends string, Input extends Schema.Top>(
103
102
  declaration: Peer<Name, Input>,
104
103
  options: { readonly after?: number; readonly limit?: number } = {},
105
- ) =>
106
- Effect.gen(function* () {
107
- const service = yield* host;
104
+ ) {
105
+ const service = yield* host;
108
106
 
109
- return yield* service.inbox({ ...declaration, ...options, limit: options.limit ?? 20 });
110
- });
107
+ return yield* service.inbox({ ...declaration, ...options, limit: options.limit ?? 20 });
108
+ });
111
109
 
112
- export const inspect = <Name extends string, Input extends Schema.Top>(
110
+ export const inspect = Effect.fnUntraced(function* <Name extends string, Input extends Schema.Top>(
113
111
  declaration: Peer<Name, Input>,
114
112
  message: MessageRef,
115
- ) =>
116
- Effect.gen(function* () {
117
- const service = yield* host;
113
+ ) {
114
+ const service = yield* host;
118
115
 
119
- return yield* service.inspect({ ...declaration, message });
120
- });
116
+ return yield* service.inspect({ ...declaration, message });
117
+ });
121
118
 
122
119
  /** Explicitly renew a parked delivery's bounded retry budget, retaining its complete frozen envelope. */
123
- export const retry = <Name extends string, Input extends Schema.Top>(
120
+ export const retry = Effect.fnUntraced(function* <Name extends string, Input extends Schema.Top>(
124
121
  declaration: Peer<Name, Input>,
125
122
  message: MessageRef,
126
- ) =>
127
- Effect.gen(function* () {
128
- const service = yield* host;
123
+ ) {
124
+ const service = yield* host;
129
125
 
130
- return yield* service.retry({ ...declaration, message });
131
- });
126
+ return yield* service.retry({ ...declaration, message });
127
+ });
132
128
 
133
129
  const modelKey = Effect.fnUntraced(function* () {
134
130
  const source = yield* (yield* host).context;
@@ -177,8 +177,10 @@ export const prepareModelContext = <
177
177
  >(
178
178
  snapshot: ThreadSnapshot,
179
179
  transforms?: { readonly [Index in keyof Requirements]: ContextTransform<Requirements[Index]> },
180
- ): Effect.Effect<PreparedModelContext, ContextTransformError, Requirements[number]> =>
181
- (transforms ?? [])
180
+ ): Effect.Effect<PreparedModelContext, ContextTransformError, Requirements[number]> => {
181
+ const declared: ReadonlyArray<ContextTransform<Requirements[number]>> = transforms ?? [];
182
+
183
+ return declared
182
184
  .reduce<
183
185
  Effect.Effect<ReadonlyArray<ModelContextMessage>, ContextTransformError, Requirements[number]>
184
186
  >(
@@ -198,6 +200,7 @@ export const prepareModelContext = <
198
200
  }),
199
201
  ),
200
202
  );
203
+ };
201
204
 
202
205
  const exactSourceRange = (
203
206
  snapshot: ThreadSnapshot,
@@ -35,28 +35,67 @@ interface RedactionCounter {
35
35
  nodes: number;
36
36
  }
37
37
 
38
- const redactValue = (value: unknown, depth: number, counter: RedactionCounter): Schema.Json => {
38
+ const encodingFailure = () =>
39
+ RedactionError.make({
40
+ reason: "encoding-failed",
41
+ message: "Could not encode the structurally redacted preview",
42
+ });
43
+
44
+ const redactValue = Effect.fnUntraced(function* (
45
+ value: unknown,
46
+ depth: number,
47
+ counter: RedactionCounter,
48
+ ): Effect.fn.Return<Schema.Json, RedactionError> {
39
49
  if (depth > MAX_REDACTION_DEPTH) {
40
- throw RedactionError.make({
50
+ return yield* RedactionError.make({
41
51
  reason: "input-too-deep",
42
52
  message: `Decoded value exceeds redaction depth ${MAX_REDACTION_DEPTH}`,
43
53
  });
44
54
  }
45
55
  counter.nodes += 1;
46
56
  if (counter.nodes > MAX_REDACTION_NODES) {
47
- throw RedactionError.make({
57
+ return yield* RedactionError.make({
48
58
  reason: "input-too-large",
49
59
  message: `Decoded value exceeds redaction node count ${MAX_REDACTION_NODES}`,
50
60
  });
51
61
  }
52
- if (Array.isArray(value)) {
53
- return value.map((item) => redactValue(item, depth + 1, counter));
62
+
63
+ const collection = yield* Effect.try({
64
+ try: () => {
65
+ if (Array.isArray(value)) {
66
+ const redacted: Array<Schema.Json> = [];
67
+
68
+ redacted.length = value.length;
69
+
70
+ return { _tag: "Array" as const, values: value, redacted };
71
+ }
72
+
73
+ return value !== null && typeof value === "object"
74
+ ? { _tag: "Object" as const, entries: Object.entries(value) }
75
+ : undefined;
76
+ },
77
+ catch: encodingFailure,
78
+ });
79
+
80
+ if (collection?._tag === "Array") {
81
+ const { redacted } = collection;
82
+
83
+ for (let index = 0; index < redacted.length; index += 1) {
84
+ const item = yield* Effect.try({
85
+ try: () => (index in collection.values ? { value: collection.values[index] } : undefined),
86
+ catch: encodingFailure,
87
+ });
88
+
89
+ if (item !== undefined) redacted[index] = yield* redactValue(item.value, depth + 1, counter);
90
+ }
91
+
92
+ return redacted;
54
93
  }
55
- if (value !== null && typeof value === "object") {
94
+ if (collection?._tag === "Object") {
56
95
  const redacted: Record<string, Schema.Json> = {};
57
96
 
58
- for (const [key, item] of Object.entries(value)) {
59
- redacted[key] = redactValue(item, depth + 1, counter);
97
+ for (const [key, item] of collection.entries) {
98
+ redacted[key] = yield* redactValue(item, depth + 1, counter);
60
99
  }
61
100
 
62
101
  return redacted;
@@ -72,7 +111,7 @@ const redactValue = (value: unknown, depth: number, counter: RedactionCounter):
72
111
  if (typeof value === "boolean") return "[REDACTED:boolean]";
73
112
 
74
113
  return "[REDACTED:unsupported]";
75
- };
114
+ });
76
115
 
77
116
  const truncateUtf8 = (value: string, maxBytes: number): string => {
78
117
  if (utf8ByteLength(value) <= maxBytes) {
@@ -128,30 +167,21 @@ export const redactedTranscript = (
128
167
  * Tool-specific Layers may expose explicitly reviewed fields instead.
129
168
  */
130
169
  export const StructuralRedactorLive = Layer.succeed(Redactor)({
131
- redact: (decodedValue) =>
132
- Effect.try({
133
- try: () => {
134
- const structurallyRedacted = redactValue(decodedValue, 0, { nodes: 0 });
135
-
136
- return truncateUtf8(JSON.stringify(structurallyRedacted), MAX_REDACTED_PREVIEW_BYTES);
137
- },
138
- catch: (cause) =>
139
- Schema.is(RedactionError)(cause)
140
- ? cause
141
- : RedactionError.make({
142
- reason: "encoding-failed",
143
- message: "Could not encode the structurally redacted preview",
144
- }),
145
- }).pipe(
146
- Effect.flatMap((preview) =>
147
- Schema.decodeEffect(RedactedPreview)(preview).pipe(
148
- Effect.mapError(() =>
149
- RedactionError.make({
150
- reason: "encoding-failed",
151
- message: "Redacted preview did not satisfy its bounded schema",
152
- }),
153
- ),
154
- ),
170
+ redact: Effect.fnUntraced(function* (decodedValue) {
171
+ const structurallyRedacted = yield* redactValue(decodedValue, 0, { nodes: 0 });
172
+
173
+ const preview = yield* Effect.try({
174
+ try: () => truncateUtf8(JSON.stringify(structurallyRedacted), MAX_REDACTED_PREVIEW_BYTES),
175
+ catch: encodingFailure,
176
+ });
177
+
178
+ return yield* Schema.decodeEffect(RedactedPreview)(preview).pipe(
179
+ Effect.mapError(() =>
180
+ RedactionError.make({
181
+ reason: "encoding-failed",
182
+ message: "Redacted preview did not satisfy its bounded schema",
183
+ }),
155
184
  ),
156
- ),
185
+ );
186
+ }),
157
187
  });
@@ -82,70 +82,67 @@ export const toRunApprovalHook = (
82
82
  | RedactionError,
83
83
  ApprovalResolver | ApprovalAudit | Redactor
84
84
  > => ({
85
- request: (engineRequest) =>
86
- Effect.gen(function* () {
87
- const validatedPolicy = yield* Schema.decodeEffect(RunApprovalAdapterPolicySchema)(
88
- policy,
89
- ).pipe(
90
- Effect.mapError((error) =>
91
- ApprovalAdapterError.make({
92
- message: `Approval adapter policy is invalid: ${error.message}`,
93
- }),
94
- ),
95
- );
85
+ request: Effect.fnUntraced(function* (engineRequest) {
86
+ const validatedPolicy = yield* Schema.decodeEffect(RunApprovalAdapterPolicySchema)(policy).pipe(
87
+ Effect.mapError((error) =>
88
+ ApprovalAdapterError.make({
89
+ message: `Approval adapter policy is invalid: ${error.message}`,
90
+ }),
91
+ ),
92
+ );
96
93
 
97
- const now = yield* Clock.currentTimeMillis;
94
+ const now = yield* Clock.currentTimeMillis;
98
95
 
99
- const metadata = yield* Effect.try({
100
- try: () => ({
101
- actionSummary: policy.actionSummary(engineRequest),
102
- resourceTargets: policy.resourceTargets(engineRequest),
96
+ const metadata = yield* Effect.try({
97
+ try: () => ({
98
+ actionSummary: policy.actionSummary(engineRequest),
99
+ resourceTargets: policy.resourceTargets(engineRequest),
100
+ }),
101
+ catch: () =>
102
+ ApprovalAdapterError.make({
103
+ message: "Approval policy failed while describing the native Tool request",
103
104
  }),
104
- catch: () =>
105
- ApprovalAdapterError.make({
106
- message: "Approval policy failed while describing the native Tool request",
107
- }),
108
- });
109
-
110
- const draft = yield* Schema.decodeEffect(ApprovalRequestDraft)({
111
- requestId: engineRequest.request.approvalId,
112
- runId: engineRequest.runId,
113
- threadId: engineRequest.threadId,
114
- toolCallId: engineRequest.toolCallId,
115
- toolName: engineRequest.toolName,
116
- actionSummary: metadata.actionSummary,
117
- resourceTargets: metadata.resourceTargets,
118
- risk: validatedPolicy.risk,
119
- expiresAt: DateTime.formatIso(
120
- DateTime.toUtc(DateTime.makeUnsafe(now + validatedPolicy.expiresInMillis)),
121
- ),
122
- denial: validatedPolicy.denial,
123
- }).pipe(
124
- Effect.mapError((error) =>
125
- ApprovalAdapterError.make({
126
- message: `Approval adapter policy is invalid: ${error.message}`,
127
- }),
128
- ),
129
- );
105
+ });
130
106
 
131
- const request = yield* makeApprovalRequest(draft, engineRequest.parameters);
132
- const decision = yield* requestApproval(request);
107
+ const draft = yield* Schema.decodeEffect(ApprovalRequestDraft)({
108
+ requestId: engineRequest.request.approvalId,
109
+ runId: engineRequest.runId,
110
+ threadId: engineRequest.threadId,
111
+ toolCallId: engineRequest.toolCallId,
112
+ toolName: engineRequest.toolName,
113
+ actionSummary: metadata.actionSummary,
114
+ resourceTargets: metadata.resourceTargets,
115
+ risk: validatedPolicy.risk,
116
+ expiresAt: DateTime.formatIso(
117
+ DateTime.toUtc(DateTime.makeUnsafe(now + validatedPolicy.expiresInMillis)),
118
+ ),
119
+ denial: validatedPolicy.denial,
120
+ }).pipe(
121
+ Effect.mapError((error) =>
122
+ ApprovalAdapterError.make({
123
+ message: `Approval adapter policy is invalid: ${error.message}`,
124
+ }),
125
+ ),
126
+ );
133
127
 
134
- if (decision._tag === "ApprovalApproved") {
135
- return { _tag: "approved" as const };
136
- }
137
- if (decision.timedOut && request.denial === "recoverable") {
138
- return {
139
- _tag: "unresolved" as const,
140
- reason: decision.reason,
141
- };
142
- }
128
+ const request = yield* makeApprovalRequest(draft, engineRequest.parameters);
129
+ const decision = yield* requestApproval(request);
143
130
 
131
+ if (decision._tag === "ApprovalApproved") {
132
+ return { _tag: "approved" as const };
133
+ }
134
+ if (decision.timedOut && request.denial === "recoverable") {
144
135
  return {
145
- _tag: "denied" as const,
136
+ _tag: "unresolved" as const,
146
137
  reason: decision.reason,
147
138
  };
148
- }),
139
+ }
140
+
141
+ return {
142
+ _tag: "denied" as const,
143
+ reason: decision.reason,
144
+ };
145
+ }),
149
146
  });
150
147
 
151
148
  /**