@yielded/agent 0.1.0-beta.173 → 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-B943ebI_.d.mts → MessageDelivery-BGDm-c46.d.mts} +42 -42
  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-DpHxjBrA.d.mts → ThreadImport-CMgzttvr.d.mts} +5 -5
  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
@@ -228,6 +228,10 @@ export class SubmissionSnapshot extends Schema.Class<SubmissionSnapshot>(
228
228
  inputPayload: PersistedJson,
229
229
  inputDigest: Digest,
230
230
  settledOutcome: Schema.optionalKey(SettlementOutcome),
231
+ /** First committed finalization time; paired with settledRecordId by native adapters. */
232
+ settledAt: Schema.optionalKey(Schema.DateTimeUtcFromString),
233
+ /** Exact canonical settlement behind the finalized projection; not a substitute for reading it. */
234
+ settledRecordId: Schema.optionalKey(RecordId),
231
235
  createdAt: Schema.DateTimeUtcFromString,
232
236
  readyAt: Schema.optionalKey(Schema.DateTimeUtcFromString),
233
237
  admissionGroup: Schema.optionalKey(AdmissionGroup),
@@ -122,8 +122,8 @@ export const makeSubscriptionInputBinding = Effect.fnUntraced(function* <
122
122
  Effect.scoped,
123
123
  Effect.provideContext(services),
124
124
  ),
125
- prepare: (event, subscription) =>
126
- Effect.gen(function* () {
125
+ prepare: Effect.fnUntraced(
126
+ function* (event, subscription) {
127
127
  const e = yield* Schema.decodeEffect(options.event)(event.payload).pipe(
128
128
  Effect.mapError(invalid),
129
129
  );
@@ -137,6 +137,8 @@ export const makeSubscriptionInputBinding = Effect.fnUntraced(function* <
137
137
  ).pipe(Effect.mapError(invalid));
138
138
 
139
139
  return yield* encode(options.input, yield* options.prepare(e, p, c));
140
- }).pipe(Effect.scoped, Effect.provideContext(services)),
140
+ },
141
+ (effect) => effect.pipe(Effect.scoped, Effect.provideContext(services)),
142
+ ),
141
143
  };
142
144
  });
@@ -860,21 +860,20 @@ const lifetimeCapacity = conformanceCase(
860
860
  );
861
861
  }
862
862
 
863
- const assertHostGuard = <A>(
863
+ const assertHostGuard = Effect.fnUntraced(function* <A>(
864
864
  effect: Effect.Effect<A, SubscriptionStoreFailure>,
865
865
  code: string,
866
- ) =>
867
- Effect.gen(function* () {
868
- const result = yield* Effect.result(effect);
869
-
870
- yield* ensure(
871
- Result.isFailure(result) &&
872
- result.failure._tag === "SubscriptionError" &&
873
- result.failure.reason === "capacity" &&
874
- result.failure.code === code,
875
- `host ${code} guard ignored live work`,
876
- );
877
- });
866
+ ) {
867
+ const result = yield* Effect.result(effect);
868
+
869
+ yield* ensure(
870
+ Result.isFailure(result) &&
871
+ result.failure._tag === "SubscriptionError" &&
872
+ result.failure.reason === "capacity" &&
873
+ result.failure.code === code,
874
+ `host ${code} guard ignored live work`,
875
+ );
876
+ });
878
877
 
879
878
  const active = yield* store.register(record("host-active"), limits);
880
879
  const activeEvent = yield* store.accept(event("host-active"), limits);
@@ -934,17 +933,18 @@ const capacityReactivation = conformanceCase(
934
933
  maxDeliveriesPerOwner: 1,
935
934
  };
936
935
 
937
- const expectCapacity = <A>(effect: Effect.Effect<A, SubscriptionStoreFailure>) =>
938
- Effect.gen(function* () {
939
- const result = yield* Effect.result(effect);
936
+ const expectCapacity = Effect.fnUntraced(function* <A>(
937
+ effect: Effect.Effect<A, SubscriptionStoreFailure>,
938
+ ) {
939
+ const result = yield* Effect.result(effect);
940
940
 
941
- yield* ensure(
942
- Result.isFailure(result) &&
943
- result.failure._tag === "SubscriptionError" &&
944
- result.failure.reason === "capacity",
945
- "live work did not reserve capacity",
946
- );
947
- });
941
+ yield* ensure(
942
+ Result.isFailure(result) &&
943
+ result.failure._tag === "SubscriptionError" &&
944
+ result.failure.reason === "capacity",
945
+ "live work did not reserve capacity",
946
+ );
947
+ });
948
948
 
949
949
  const expiring = record("expiring");
950
950
 
@@ -584,25 +584,24 @@ const makeManagement = Effect.fnUntraced(function* (requested: SubscriptionLimit
584
584
 
585
585
  return Subscriptions.of({
586
586
  getSubscription,
587
- recoverSubscription: (scopeValue, key, expectedRevision) =>
588
- Effect.gen(function* () {
589
- const owner = yield* scope(scopeValue);
590
-
591
- yield* authorizer.manage("recover", owner);
592
-
593
- return snapshot(
594
- yield* store.change(
595
- yield* ownedKey(owner, key),
596
- expectedRevision,
597
- {
598
- _tag: "Recover",
599
- nowMillis: yield* now,
600
- },
601
- limits,
602
- ),
603
- yield* now,
604
- );
605
- }),
587
+ recoverSubscription: Effect.fnUntraced(function* (scopeValue, key, expectedRevision) {
588
+ const owner = yield* scope(scopeValue);
589
+
590
+ yield* authorizer.manage("recover", owner);
591
+
592
+ return snapshot(
593
+ yield* store.change(
594
+ yield* ownedKey(owner, key),
595
+ expectedRevision,
596
+ {
597
+ _tag: "Recover",
598
+ nowMillis: yield* now,
599
+ },
600
+ limits,
601
+ ),
602
+ yield* now,
603
+ );
604
+ }),
606
605
  recoverDelivery,
607
606
  subscribe,
608
607
  updateSubscription,
@@ -701,28 +701,27 @@ export const prepareImportPage = Effect.fnUntraced(function* (
701
701
  return { archive, records, batches: prepared } satisfies PreparedImportPage;
702
702
  });
703
703
 
704
- export const finishThreadImport = (state: ThreadImportProgress) =>
705
- Effect.gen(function* () {
706
- const page = state.manifest;
704
+ export const finishThreadImport = Effect.fnUntraced(function* (state: ThreadImportProgress) {
705
+ const page = state.manifest;
707
706
 
708
- if (
709
- page === undefined ||
710
- !state.ended ||
711
- state.sequence !== page.tailSequence ||
712
- transferSections.some((section) => state.counts[section] !== page.snapshot[section])
713
- )
714
- return yield* invalid(
715
- "Transfer stream ended before its complete canonical sequence and fact sections",
716
- );
707
+ if (
708
+ page === undefined ||
709
+ !state.ended ||
710
+ state.sequence !== page.tailSequence ||
711
+ transferSections.some((section) => state.counts[section] !== page.snapshot[section])
712
+ )
713
+ return yield* invalid(
714
+ "Transfer stream ended before its complete canonical sequence and fact sections",
715
+ );
717
716
 
718
- return ThreadImportResult.make({
719
- threadId: page.threadId,
720
- format: page.format,
721
- tailSequence: page.tailSequence,
722
- recordCount: state.sequence,
723
- submissionCount: state.counts.admissions,
724
- });
717
+ return ThreadImportResult.make({
718
+ threadId: page.threadId,
719
+ format: page.format,
720
+ tailSequence: page.tailSequence,
721
+ recordCount: state.sequence,
722
+ submissionCount: state.counts.admissions,
725
723
  });
724
+ });
726
725
 
727
726
  /** An executed receipt must settle strictly after its own input. FIFO inputs are checked in one pass. */
728
727
  export const verifyImportedInputOrder = Effect.fnUntraced(function* (
@@ -130,7 +130,8 @@ export const verifyThreadInvariants = Effect.fnUntraced(function* <E, R>(
130
130
  selected === undefined ||
131
131
  selected.sequence !== entry.sequence ||
132
132
  selected.batchId !== entry.batchId ||
133
- recordEncoding(selected.record).json !== recordEncoding(entry.record).json
133
+ (yield* Effect.fromResult(recordEncoding(selected.record))).json !==
134
+ (yield* Effect.fromResult(recordEncoding(entry.record))).json
134
135
  )
135
136
  fail(
136
137
  "continuation-evidence",
@@ -1,4 +1,4 @@
1
- import { Context, Effect, Layer, Option, Predicate, Result, Schema, Stream, Struct } from "effect";
1
+ import { Context, Effect, Layer, Option, Result, Schema, Stream, Struct } from "effect";
2
2
 
3
3
  import { ReceiptId, RunId, SubmissionId, ThreadId, ToolCallId } from "../core/Identifiers.ts";
4
4
  import { utf8ByteLength } from "../core/internal/utf8.ts";
@@ -189,10 +189,10 @@ const selectedRecords = Effect.fnUntraced(function* (
189
189
  )
190
190
  return yield* incomplete("read selection identity");
191
191
  afterSequence = entry.sequence;
192
- bytes += yield* Effect.try({
193
- try: () => recordEncoding(entry.record).bytes,
194
- catch: () => incomplete("read selection bytes"),
195
- });
192
+ bytes += yield* Effect.fromResult(recordEncoding(entry.record)).pipe(
193
+ Effect.map((record) => record.bytes),
194
+ Effect.mapError(() => incomplete("read selection bytes")),
195
+ );
196
196
  if (bytes > MAX_THREAD_EXPORT_PAGE_BYTES)
197
197
  return yield* incomplete("read selection byte limit");
198
198
  records.push(entry);
@@ -356,11 +356,101 @@ const validateRecordCount = Schema.decodeUnknownSync(
356
356
  Schema.Array(Schema.Unknown).check(Schema.isMaxLength(256)),
357
357
  );
358
358
 
359
- const executionJson = Schema.fromJsonString(ExecutionUpdate);
360
- const encodeExecution = Schema.encodeSync(executionJson);
361
- const decodeExecution = Schema.decodeUnknownSync(ExecutionUpdate);
359
+ const validateExecutionHeader = Schema.decodeUnknownSync(
360
+ Schema.Struct({
361
+ previousRevision: ExecutionUpdate.fields.previousRevision,
362
+ retire: ExecutionUpdate.fields.retire,
363
+ checkpoint: Schema.Struct({
364
+ version: ExecutionCheckpoint.fields.version,
365
+ canonicalRecords: ExecutionCheckpoint.fields.canonicalRecords,
366
+ originalSequence: ExecutionCheckpoint.fields.originalSequence,
367
+ throughSequence: ExecutionCheckpoint.fields.throughSequence,
368
+ batchId: ExecutionCheckpoint.fields.batchId,
369
+ }),
370
+ }),
371
+ );
372
+
373
+ const validateExecutionRecordCount = Schema.decodeUnknownSync(
374
+ Schema.Array(Schema.Unknown).check(Schema.isMaxLength(8)),
375
+ );
376
+
377
+ /** Capture records once; wrapper fields retain their owning Schema's constraints. */
378
+ const captureExecution = (input: ExecutionUpdate) => {
379
+ const header = validateExecutionHeader(input);
380
+ const operationalInput = input.checkpoint.operational;
381
+ const factsInput = input.facts;
382
+
383
+ const operationalLength = validateExecutionRecordCount(operationalInput).length;
384
+ const factsLength = validateExecutionRecordCount(factsInput).length;
362
385
 
363
- const capturedAppends = new WeakMap<AppendRequest, PreparedAppend>();
386
+ const progress = captureRecord(input.checkpoint.progressRecord);
387
+
388
+ if (Result.isFailure(progress)) return Result.fail(progress.failure);
389
+ const progressRecord = progress.success.canonical;
390
+
391
+ if (!isExecutionProgressRecord(progressRecord))
392
+ return Result.fail(
393
+ ThreadStoreError.make({
394
+ operation: "prepare durable commit",
395
+ message: "Expected a Run continuation record",
396
+ }),
397
+ );
398
+
399
+ // Use the Schema-validated indexed lengths, never a caller's iterator. Sparse slots
400
+ // still visit the record boundary, where undefined is refused.
401
+ const operational = [];
402
+
403
+ for (let index = 0; index < operationalLength; index++) {
404
+ const record = captureRecord(operationalInput[index]!);
405
+
406
+ if (Result.isFailure(record)) return Result.fail(record.failure);
407
+ operational.push(record.success);
408
+ }
409
+ const facts = [];
410
+
411
+ for (let index = 0; index < factsLength; index++) {
412
+ const record = captureRecord(factsInput[index]!);
413
+
414
+ if (Result.isFailure(record)) return Result.fail(record.failure);
415
+ facts.push(record.success);
416
+ }
417
+
418
+ // Keep the actual owned arrays within the persisted bounds as well.
419
+ validateExecutionRecordCount(operational);
420
+ validateExecutionRecordCount(facts);
421
+
422
+ const checkpoint = Object.freeze(
423
+ ExecutionCheckpoint.make(
424
+ {
425
+ ...header.checkpoint,
426
+ progressRecord,
427
+ operational: Object.freeze(operational.map(({ canonical }) => canonical)),
428
+ },
429
+ { disableChecks: true },
430
+ ),
431
+ );
432
+
433
+ const update = Object.freeze(
434
+ ExecutionUpdate.make(
435
+ {
436
+ previousRevision: header.previousRevision,
437
+ retire: header.retire,
438
+ checkpoint,
439
+ facts: Object.freeze(facts.map(({ canonical }) => canonical)),
440
+ },
441
+ { disableChecks: true },
442
+ ),
443
+ );
444
+
445
+ const checkpointJson = `{"version":${checkpoint.version},"progressRecord":${progress.success.json},"operational":[${operational.map(({ json }) => json).join(",")}],"canonicalRecords":${checkpoint.canonicalRecords},"originalSequence":${checkpoint.originalSequence},"throughSequence":${checkpoint.throughSequence},"batchId":${JSON.stringify(checkpoint.batchId)}}`;
446
+ const json = `{"previousRevision":${update.previousRevision},"checkpoint":${checkpointJson},"facts":[${facts.map(({ json }) => json).join(",")}],"retire":${update.retire}}`;
447
+
448
+ return Result.succeed(
449
+ Object.freeze({ update, json, checkpointJson, bytes: utf8ByteLength(json) }),
450
+ );
451
+ };
452
+
453
+ const capturedAppends = new WeakMap<AppendRequest, CapturedAppend>();
364
454
 
365
455
  /**
366
456
  * Admission reserves one complete batch's envelope, references, snapshot and continuation cursor.
@@ -418,122 +508,125 @@ export interface PreparedAppend extends AppendRequest {
418
508
  }>;
419
509
  }
420
510
 
511
+ interface CapturedAppend extends PreparedAppend {
512
+ readonly records: ReadonlyArray<
513
+ Omit<PreparedAppend["records"][number], "wire"> & {
514
+ readonly wire: typeof RecordEnvelope.Encoded;
515
+ }
516
+ >;
517
+ }
518
+
421
519
  export const PreparedAppend = {
422
- capture: (input: AppendRequest): Effect.Effect<PreparedAppend, ThreadStoreError> =>
520
+ capture: (input: AppendRequest): Effect.Effect<CapturedAppend, ThreadStoreError> =>
423
521
  Effect.suspend(() => {
424
522
  const existing = capturedAppends.get(input);
425
523
 
426
524
  if (existing !== undefined) return Effect.succeed(existing);
427
525
 
428
526
  return Effect.try({
429
- try: () => {
430
- const header = validateHeader({
431
- ...input,
432
- batchId: input.batch.batchId,
433
- producerId: input.batch.producerId,
434
- });
435
-
436
- validateRecordCount(input.batch.records);
437
- validateRecordCount(input.executions ?? []);
438
-
439
- const executionWrites = Object.freeze(
440
- (input.executions ?? []).map((update) => {
441
- const json = encodeExecution(update);
442
- const wire: unknown = JSON.parse(json);
443
- const decoded = decodeExecution(wire);
444
-
445
- if (!Predicate.hasProperty(wire, "checkpoint"))
446
- throw ThreadStoreError.make({
447
- operation: "prepare durable commit",
448
- message: "Captured execution has no checkpoint wire",
449
- });
450
-
451
- return Object.freeze({
452
- update: decoded,
453
- json,
454
- checkpointJson: JSON.stringify(wire.checkpoint),
455
- bytes: utf8ByteLength(json),
456
- });
457
- }),
458
- );
459
-
460
- if (input.batch.records.length === 0 && executionWrites.length === 0)
461
- throw ThreadStoreError.make({
462
- operation: "prepare durable commit",
463
- message: "A commit must contain history facts or an active execution transition",
464
- });
465
- if (executionWrites.some(({ bytes }) => !transferPageFits(header.threadId, bytes)))
466
- throw ThreadStoreError.make({
467
- operation: "prepare durable commit",
468
- message: "Active state exceeds its bounded transfer representation",
469
- });
470
- // Visit sparse slots too: capture owns each record's validation boundary.
471
- const encodings = Array.from(input.batch.records, captureRecord);
472
- const prefix = `{"batchId":${JSON.stringify(header.batchId)},"producerId":${JSON.stringify(header.producerId)},"records":[`;
473
- const batchJson = `${prefix}${encodings.map(({ json }) => json).join(",")}]}`;
474
-
475
- const batchBytes = encodings.reduce(
476
- (total, record) => total + record.bytes,
477
- utf8ByteLength(prefix) + (encodings.length === 0 ? 2 : encodings.length + 1),
478
- );
479
-
480
- if (batchBytes > MAX_CANONICAL_BATCH_BYTES)
481
- throw ThreadStoreError.make({
482
- operation: "prepare canonical append",
483
- message: `Canonical batch exceeds ${MAX_CANONICAL_BATCH_BYTES} bytes`,
527
+ try: () =>
528
+ Result.gen(function* () {
529
+ const header = validateHeader({
530
+ ...input,
531
+ batchId: input.batch.batchId,
532
+ producerId: input.batch.producerId,
484
533
  });
485
534
 
486
- const batch = Object.freeze(
487
- new CommitBatch(
535
+ validateRecordCount(input.batch.records);
536
+ const executions = input.executions ?? [];
537
+ const executionLength = validateRecordCount(executions).length;
538
+
539
+ const executionWrites: Array<PreparedAppend["executionWrites"][number]> = [];
540
+
541
+ for (let index = 0; index < executionLength; index++)
542
+ executionWrites.push(yield* captureExecution(executions[index]!));
543
+ Object.freeze(executionWrites);
544
+
545
+ validateRecordCount(executionWrites);
546
+
547
+ if (input.batch.records.length === 0 && executionWrites.length === 0)
548
+ return yield* Result.fail(
549
+ ThreadStoreError.make({
550
+ operation: "prepare durable commit",
551
+ message: "A commit must contain history facts or an active execution transition",
552
+ }),
553
+ );
554
+ if (executionWrites.some(({ bytes }) => !transferPageFits(header.threadId, bytes)))
555
+ return yield* Result.fail(
556
+ ThreadStoreError.make({
557
+ operation: "prepare durable commit",
558
+ message: "Active state exceeds its bounded transfer representation",
559
+ }),
560
+ );
561
+ // Visit sparse slots too: capture owns each record's validation boundary.
562
+ const encodings = yield* Result.all(Array.from(input.batch.records, captureRecord));
563
+ const prefix = `{"batchId":${JSON.stringify(header.batchId)},"producerId":${JSON.stringify(header.producerId)},"records":[`;
564
+ const batchJson = `${prefix}${encodings.map(({ json }) => json).join(",")}]}`;
565
+
566
+ const batchBytes = encodings.reduce(
567
+ (total, record) => total + record.bytes,
568
+ utf8ByteLength(prefix) + (encodings.length === 0 ? 2 : encodings.length + 1),
569
+ );
570
+
571
+ if (batchBytes > MAX_CANONICAL_BATCH_BYTES)
572
+ return yield* Result.fail(
573
+ ThreadStoreError.make({
574
+ operation: "prepare canonical append",
575
+ message: `Canonical batch exceeds ${MAX_CANONICAL_BATCH_BYTES} bytes`,
576
+ }),
577
+ );
578
+
579
+ const batch = Object.freeze(
580
+ CommitBatch.make(
581
+ {
582
+ batchId: header.batchId,
583
+ producerId: header.producerId,
584
+ records: Object.freeze(encodings.map(({ canonical }) => canonical)),
585
+ },
586
+ { disableChecks: true },
587
+ ),
588
+ );
589
+
590
+ const request = AppendRequest.make(
488
591
  {
489
- batchId: header.batchId,
490
- producerId: header.producerId,
491
- records: Object.freeze(encodings.map(({ canonical }) => canonical)),
592
+ threadId: header.threadId,
593
+ expectedTailSequence: header.expectedTailSequence,
594
+ batch,
595
+ ...(executionWrites.length === 0
596
+ ? {}
597
+ : { executions: Object.freeze(executionWrites.map(({ update }) => update)) }),
492
598
  },
493
599
  { disableChecks: true },
494
- ),
495
- );
496
-
497
- const request = new AppendRequest(
498
- {
499
- threadId: header.threadId,
500
- expectedTailSequence: header.expectedTailSequence,
501
- batch,
502
- ...(executionWrites.length === 0
503
- ? {}
504
- : { executions: Object.freeze(executionWrites.map(({ update }) => update)) }),
505
- },
506
- { disableChecks: true },
507
- );
508
-
509
- const records = Object.freeze(
510
- encodings.map(({ canonical, json, wire, bytes }) =>
511
- Object.freeze({
512
- recordId: canonical.recordId,
513
- recordJson: json,
514
- recordBytes: bytes,
515
- wire,
516
- canonical,
600
+ );
601
+
602
+ const records = Object.freeze(
603
+ encodings.map(({ canonical, json, wire, bytes }) =>
604
+ Object.freeze({
605
+ recordId: canonical.recordId,
606
+ recordJson: json,
607
+ recordBytes: bytes,
608
+ wire,
609
+ canonical,
610
+ }),
611
+ ),
612
+ );
613
+
614
+ const progress = Object.freeze(encodings.map(({ progress }) => progress));
615
+
616
+ const captured = Object.freeze(
617
+ Object.assign(request, {
618
+ batchJson,
619
+ batchBytes,
620
+ records,
621
+ progress,
622
+ executionWrites,
517
623
  }),
518
- ),
519
- );
520
-
521
- const progress = Object.freeze(encodings.map(({ progress }) => progress));
624
+ );
522
625
 
523
- const captured = Object.freeze(
524
- Object.assign(request, {
525
- batchJson,
526
- batchBytes,
527
- records,
528
- progress,
529
- executionWrites,
530
- }),
531
- );
626
+ capturedAppends.set(captured, captured);
532
627
 
533
- capturedAppends.set(captured, captured);
534
-
535
- return captured;
536
- },
628
+ return captured;
629
+ }),
537
630
  catch: (cause) =>
538
631
  Schema.is(ThreadStoreError)(cause)
539
632
  ? cause
@@ -544,7 +637,18 @@ export const PreparedAppend = {
544
637
  : "Canonical append capture failed",
545
638
  cause,
546
639
  }),
547
- });
640
+ }).pipe(
641
+ Effect.flatMap(Effect.fromResult),
642
+ Effect.mapError((cause) =>
643
+ Schema.is(ThreadStoreError)(cause)
644
+ ? cause
645
+ : ThreadStoreError.make({
646
+ operation: "prepare canonical append",
647
+ message: cause.message,
648
+ cause,
649
+ }),
650
+ ),
651
+ );
548
652
  }),
549
653
  };
550
654
 
@@ -1,4 +1,3 @@
1
- import type { Crypto } from "effect";
2
1
  import { Context, Effect, Layer, Option, Schema, Stream } from "effect";
3
2
 
4
3
  import { ReceiptId, RunId, SubmissionId, ThreadId, ToolCallId } from "../core/Identifiers.ts";
@@ -487,7 +486,7 @@ export type WorkIndexChange =
487
486
  export const workIndexChanges = Effect.fnUntraced(function* (
488
487
  envelope: CanonicalRecordEnvelope,
489
488
  reporting: WorkerReportingMode,
490
- ): Effect.fn.Return<ReadonlyArray<WorkIndexChange>, ThreadStoreError, Crypto.Crypto> {
489
+ ): Effect.fn.Return<ReadonlyArray<WorkIndexChange>, ThreadStoreError> {
491
490
  const { record, sequence } = envelope;
492
491
  const payload = record.payload;
493
492
 
@@ -52,9 +52,13 @@ export const makeStorageOwner = Effect.fnUntraced(function* (gate: MutationGate)
52
52
  const active = new Map<string, { readonly claim: Claim; closed: boolean }>();
53
53
 
54
54
  const withMutation: MutationGate = (effect) =>
55
- Effect.flatMap(ActiveOwner, (current) =>
56
- current === identity ? effect : gate(Effect.provideService(effect, ActiveOwner, identity)),
57
- );
55
+ Effect.withFiber((fiber) => {
56
+ const current = fiber.getRef(ActiveOwner);
57
+
58
+ return current === identity
59
+ ? effect
60
+ : gate(Effect.provideService(effect, ActiveOwner, identity));
61
+ });
58
62
 
59
63
  yield* Effect.addFinalizer(() =>
60
64
  withMutation(
@@ -70,7 +74,9 @@ export const makeStorageOwner = Effect.fnUntraced(function* (gate: MutationGate)
70
74
  identity,
71
75
  withMutation,
72
76
  withProgress: (threadId, effect) =>
73
- Effect.flatMap(ActiveProgress, (current) => {
77
+ Effect.withFiber((fiber) => {
78
+ const current = fiber.getRef(ActiveProgress);
79
+
74
80
  if (current?.owner === identity && current.threadId === threadId) return effect;
75
81
 
76
82
  return Effect.suspend(() => {