@sixb/core 0.1.2 → 0.1.3

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 (264) hide show
  1. package/dist/actions/index.js +16 -13
  2. package/dist/actions/index.js.map +1 -1
  3. package/dist/agents/adapters.d.ts +11 -1
  4. package/dist/agents/adapters.d.ts.map +1 -1
  5. package/dist/agents/context.js +1 -1
  6. package/dist/agents/errors.d.ts +1 -1
  7. package/dist/agents/errors.d.ts.map +1 -1
  8. package/dist/agents/execution.d.ts +3 -0
  9. package/dist/agents/execution.d.ts.map +1 -1
  10. package/dist/agents/index.d.ts +6 -3
  11. package/dist/agents/index.d.ts.map +1 -1
  12. package/dist/agents/index.js +33 -22
  13. package/dist/agents/index.js.map +1 -1
  14. package/dist/agents/prompt.d.ts +8 -2
  15. package/dist/agents/prompt.d.ts.map +1 -1
  16. package/dist/agents/request.d.ts.map +1 -1
  17. package/dist/agents/streams.js +2 -2
  18. package/dist/agents/thread-context-projection.d.ts +19 -0
  19. package/dist/agents/thread-context-projection.d.ts.map +1 -0
  20. package/dist/agents/tool-definition.d.ts.map +1 -1
  21. package/dist/agents/tool-result.d.ts +6 -0
  22. package/dist/agents/tool-result.d.ts.map +1 -0
  23. package/dist/agents/types.d.ts +37 -1
  24. package/dist/agents/types.d.ts.map +1 -1
  25. package/dist/agents/validation.d.ts +1 -1
  26. package/dist/agents/validation.d.ts.map +1 -1
  27. package/dist/auth/index.js +7 -5
  28. package/dist/auth/index.js.map +1 -1
  29. package/dist/authorization/index.js +1 -1
  30. package/dist/bootstrap/index.js +27 -24
  31. package/dist/bootstrap/index.js.map +1 -1
  32. package/dist/{chunk-0mbx247x.js → chunk-177ed2mp.js} +241 -45
  33. package/dist/chunk-177ed2mp.js.map +46 -0
  34. package/dist/{chunk-sa4340y1.js → chunk-1ywq4hzk.js} +7 -7
  35. package/dist/{chunk-zg9yryhz.js → chunk-261ag4t4.js} +3 -3
  36. package/dist/{chunk-k9pts48t.js → chunk-3rsf30p4.js} +5 -5
  37. package/dist/{chunk-8ryen3p3.js → chunk-4aw0jwk0.js} +1 -1
  38. package/dist/{chunk-bh6k3nc6.js → chunk-4p9rh7jj.js} +1 -1
  39. package/dist/{chunk-34bqh420.js → chunk-4z3n1dzt.js} +59 -21
  40. package/dist/{chunk-34bqh420.js.map → chunk-4z3n1dzt.js.map} +4 -4
  41. package/dist/chunk-96swp2wd.js +47 -0
  42. package/dist/chunk-96swp2wd.js.map +10 -0
  43. package/dist/{chunk-n8herkry.js → chunk-bv41fmjn.js} +11 -11
  44. package/dist/{chunk-7pc8b818.js → chunk-c6cfqydk.js} +1 -1
  45. package/dist/{chunk-0k4avqr2.js → chunk-c8bw2b6c.js} +2 -2
  46. package/dist/{chunk-jaj13078.js → chunk-d2adj15j.js} +3 -33
  47. package/dist/{chunk-jaj13078.js.map → chunk-d2adj15j.js.map} +3 -4
  48. package/dist/{chunk-c6qd89g5.js → chunk-d6y2wsfg.js} +3 -3
  49. package/dist/chunk-dysw7nsm.js.map +1 -1
  50. package/dist/{chunk-st4xgxey.js → chunk-ettb0cy4.js} +150 -23
  51. package/dist/chunk-ettb0cy4.js.map +45 -0
  52. package/dist/{chunk-nnyp53zt.js → chunk-f1cyvnrk.js} +1 -1
  53. package/dist/chunk-fmx1sz2h.js.map +2 -2
  54. package/dist/{chunk-bct7hmfc.js → chunk-km4rkj4t.js} +3 -3
  55. package/dist/chunk-kqxgf6kv.js +898 -0
  56. package/dist/chunk-kqxgf6kv.js.map +15 -0
  57. package/dist/{chunk-qvybnnpe.js → chunk-n5x5y80a.js} +2 -2
  58. package/dist/{chunk-4x43bkbp.js → chunk-pxtrxm3p.js} +1 -1
  59. package/dist/chunk-qer6am8w.js +133 -0
  60. package/dist/chunk-qer6am8w.js.map +11 -0
  61. package/dist/{chunk-85j5ybfj.js → chunk-rdeagz6b.js} +2 -2
  62. package/dist/{chunk-85j5ybfj.js.map → chunk-rdeagz6b.js.map} +3 -3
  63. package/dist/chunk-rhrbz7d4.js +36 -0
  64. package/dist/chunk-rhrbz7d4.js.map +10 -0
  65. package/dist/{chunk-663csy96.js → chunk-t0jjkep3.js} +2 -1
  66. package/dist/chunk-t0jjkep3.js.map +10 -0
  67. package/dist/{chunk-5egfka8j.js → chunk-ttba8x6z.js} +2 -2
  68. package/dist/{chunk-nten49ta.js → chunk-wb4051cx.js} +3 -3
  69. package/dist/{chunk-nten49ta.js.map → chunk-wb4051cx.js.map} +1 -1
  70. package/dist/{chunk-57r1cpxx.js → chunk-xc7hq65b.js} +3 -2
  71. package/dist/{chunk-57r1cpxx.js.map → chunk-xc7hq65b.js.map} +3 -3
  72. package/dist/{chunk-ys1nse2v.js → chunk-xmggaxg4.js} +256 -231
  73. package/dist/{chunk-ys1nse2v.js.map → chunk-xmggaxg4.js.map} +8 -10
  74. package/dist/{chunk-g9t3kdtx.js → chunk-z8j83gzd.js} +1 -1
  75. package/dist/{chunk-57zpb99z.js → chunk-zpw39qhj.js} +1 -1
  76. package/dist/execution/agent.js +23 -20
  77. package/dist/execution/agent.js.map +1 -1
  78. package/dist/execution/primitive.js +23 -20
  79. package/dist/execution/primitive.js.map +2 -2
  80. package/dist/execution/request.js +24 -21
  81. package/dist/execution/request.js.map +2 -2
  82. package/dist/index.d.ts +3 -3
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +32 -29
  85. package/dist/index.js.map +1 -1
  86. package/dist/materialization/model.d.ts +4 -0
  87. package/dist/materialization/model.d.ts.map +1 -1
  88. package/dist/materializer/edits/apply.d.ts +6 -1
  89. package/dist/materializer/edits/apply.d.ts.map +1 -1
  90. package/dist/materializer/edits/working-state.d.ts +2 -0
  91. package/dist/materializer/edits/working-state.d.ts.map +1 -1
  92. package/dist/materializer/effective/resolve.d.ts +3 -1
  93. package/dist/materializer/effective/resolve.d.ts.map +1 -1
  94. package/dist/materializer/execution/work-records.d.ts.map +1 -1
  95. package/dist/materializer/index.js +14 -11
  96. package/dist/materializer/index.js.map +1 -1
  97. package/dist/materializer/projections/replacement-plan.d.ts.map +1 -1
  98. package/dist/materializer/shared/normalize.d.ts.map +1 -1
  99. package/dist/objects/index.js +17 -14
  100. package/dist/objects/index.js.map +1 -1
  101. package/dist/objects/query/index.js +2 -2
  102. package/dist/pipelines/index.js +14 -12
  103. package/dist/pipelines/index.js.map +1 -1
  104. package/dist/projections/builders.d.ts +19 -6
  105. package/dist/projections/builders.d.ts.map +1 -1
  106. package/dist/projections/index.d.ts +2 -1
  107. package/dist/projections/index.d.ts.map +1 -1
  108. package/dist/projections/internal.d.ts +4 -1
  109. package/dist/projections/internal.d.ts.map +1 -1
  110. package/dist/projections/internal.js +17 -11
  111. package/dist/projections/internal.js.map +1 -1
  112. package/dist/projections/timestamp.d.ts +3 -0
  113. package/dist/projections/timestamp.d.ts.map +1 -0
  114. package/dist/projections/types.d.ts +9 -0
  115. package/dist/projections/types.d.ts.map +1 -1
  116. package/dist/projections/validation.d.ts.map +1 -1
  117. package/dist/queues/index.d.ts +1 -1
  118. package/dist/queues/index.d.ts.map +1 -1
  119. package/dist/queues/types.d.ts +7 -0
  120. package/dist/queues/types.d.ts.map +1 -1
  121. package/dist/runtime/ai-cost.d.ts +8 -0
  122. package/dist/runtime/ai-cost.d.ts.map +1 -0
  123. package/dist/storage/agents/in-memory.d.ts +18 -4
  124. package/dist/storage/agents/in-memory.d.ts.map +1 -1
  125. package/dist/storage/agents/index.d.ts +1 -1
  126. package/dist/storage/agents/index.d.ts.map +1 -1
  127. package/dist/storage/agents/provider.d.ts +31 -0
  128. package/dist/storage/agents/provider.d.ts.map +1 -1
  129. package/dist/storage/agents/provider.js +18 -7
  130. package/dist/storage/agents/provider.js.map +1 -1
  131. package/dist/storage/agents/types.d.ts +70 -4
  132. package/dist/storage/agents/types.d.ts.map +1 -1
  133. package/dist/storage/ai-cost/analytics.d.ts +61 -0
  134. package/dist/storage/ai-cost/analytics.d.ts.map +1 -0
  135. package/dist/storage/ai-cost/codec.d.ts +14 -0
  136. package/dist/storage/ai-cost/codec.d.ts.map +1 -0
  137. package/dist/storage/ai-cost/errors.d.ts +7 -0
  138. package/dist/storage/ai-cost/errors.d.ts.map +1 -0
  139. package/dist/storage/ai-cost/in-memory.d.ts +32 -0
  140. package/dist/storage/ai-cost/in-memory.d.ts.map +1 -0
  141. package/dist/storage/ai-cost/index.d.ts +6 -0
  142. package/dist/storage/ai-cost/index.d.ts.map +1 -0
  143. package/dist/storage/ai-cost/provider.d.ts +7 -0
  144. package/dist/storage/ai-cost/provider.d.ts.map +1 -0
  145. package/dist/storage/ai-cost/provider.js +132 -0
  146. package/dist/storage/ai-cost/provider.js.map +10 -0
  147. package/dist/storage/ai-cost/types.d.ts +154 -0
  148. package/dist/storage/ai-cost/types.d.ts.map +1 -0
  149. package/dist/storage/ai-cost/validation.d.ts +7 -0
  150. package/dist/storage/ai-cost/validation.d.ts.map +1 -0
  151. package/dist/storage/in-memory/index.d.ts +5 -0
  152. package/dist/storage/in-memory/index.d.ts.map +1 -1
  153. package/dist/storage/index.d.ts +3 -1
  154. package/dist/storage/index.d.ts.map +1 -1
  155. package/dist/storage/index.js +22 -15
  156. package/dist/storage/index.js.map +1 -1
  157. package/dist/storage/ontology/in-memory/materializations.d.ts.map +1 -1
  158. package/dist/storage/ontology/materializations.d.ts +3 -0
  159. package/dist/storage/ontology/materializations.d.ts.map +1 -1
  160. package/dist/storage/operation-scope.d.ts.map +1 -1
  161. package/dist/storage/operation-scope.js +1 -1
  162. package/dist/storage/types.d.ts +2 -0
  163. package/dist/storage/types.d.ts.map +1 -1
  164. package/dist/storage/workflow-runs/provider.js +6 -5
  165. package/dist/storage/workflow-runs/provider.js.map +1 -1
  166. package/dist/syncs/index.js +14 -12
  167. package/dist/syncs/index.js.map +1 -1
  168. package/dist/testing/agent-storage-contract.d.ts +3 -2
  169. package/dist/testing/agent-storage-contract.d.ts.map +1 -1
  170. package/dist/testing/ai-cost-storage-contract.d.ts +12 -0
  171. package/dist/testing/ai-cost-storage-contract.d.ts.map +1 -0
  172. package/dist/testing/index.d.ts +1 -0
  173. package/dist/testing/index.d.ts.map +1 -1
  174. package/dist/testing/index.js +2098 -1468
  175. package/dist/testing/index.js.map +6 -5
  176. package/dist/testing/materializer-storage-contract.d.ts.map +1 -1
  177. package/dist/webhooks/internal.js +12 -10
  178. package/dist/webhooks/internal.js.map +2 -2
  179. package/dist/workers/index.js +12 -2
  180. package/dist/workers/index.js.map +3 -3
  181. package/dist/workers/queue-worker.d.ts +2 -0
  182. package/dist/workers/queue-worker.d.ts.map +1 -1
  183. package/dist/workflows/execution.d.ts +3 -0
  184. package/dist/workflows/execution.d.ts.map +1 -1
  185. package/dist/workflows/index.js +24 -21
  186. package/dist/workflows/index.js.map +1 -1
  187. package/package.json +7 -1
  188. package/src/agents/adapters.ts +64 -23
  189. package/src/agents/errors.ts +2 -2
  190. package/src/agents/execution.ts +14 -2
  191. package/src/agents/index.ts +18 -1
  192. package/src/agents/prompt.ts +33 -5
  193. package/src/agents/request.ts +5 -0
  194. package/src/agents/thread-context-projection.ts +93 -0
  195. package/src/agents/tool-definition.ts +17 -2
  196. package/src/agents/tool-result.ts +61 -0
  197. package/src/agents/types.ts +47 -1
  198. package/src/agents/validation.ts +1 -1
  199. package/src/index.ts +13 -0
  200. package/src/materialization/model.ts +4 -0
  201. package/src/materializer/edits/apply.ts +55 -2
  202. package/src/materializer/edits/operations.ts +8 -1
  203. package/src/materializer/edits/working-state.ts +7 -0
  204. package/src/materializer/effective/resolve.ts +78 -9
  205. package/src/materializer/execution/work-records.ts +3 -1
  206. package/src/materializer/projections/entry-validator.ts +23 -1
  207. package/src/materializer/projections/replacement-plan.ts +2 -0
  208. package/src/materializer/shared/normalize.ts +16 -0
  209. package/src/projections/builders.ts +100 -35
  210. package/src/projections/index.ts +6 -0
  211. package/src/projections/internal.ts +4 -1
  212. package/src/projections/registry.ts +7 -0
  213. package/src/projections/revision.ts +4 -0
  214. package/src/projections/timestamp.ts +66 -0
  215. package/src/projections/types.ts +7 -0
  216. package/src/projections/validation.ts +24 -0
  217. package/src/queues/index.ts +1 -0
  218. package/src/queues/types.ts +8 -0
  219. package/src/runtime/ai-cost.ts +15 -0
  220. package/src/storage/agents/in-memory.ts +171 -4
  221. package/src/storage/agents/index.ts +5 -0
  222. package/src/storage/agents/provider.ts +225 -0
  223. package/src/storage/agents/types.ts +77 -3
  224. package/src/storage/ai-cost/analytics.ts +602 -0
  225. package/src/storage/ai-cost/codec.ts +136 -0
  226. package/src/storage/ai-cost/errors.ts +12 -0
  227. package/src/storage/ai-cost/in-memory.ts +164 -0
  228. package/src/storage/ai-cost/index.ts +35 -0
  229. package/src/storage/ai-cost/provider.ts +20 -0
  230. package/src/storage/ai-cost/types.ts +193 -0
  231. package/src/storage/ai-cost/validation.ts +337 -0
  232. package/src/storage/in-memory/index.ts +50 -0
  233. package/src/storage/index.ts +37 -0
  234. package/src/storage/ontology/in-memory/materializations.ts +1 -0
  235. package/src/storage/ontology/materializations.ts +3 -0
  236. package/src/storage/operation-scope.ts +1 -0
  237. package/src/storage/types.ts +2 -0
  238. package/src/testing/agent-storage-contract.ts +341 -2
  239. package/src/testing/ai-cost-storage-contract.ts +320 -0
  240. package/src/testing/index.ts +5 -0
  241. package/src/testing/materializer-storage-contract.ts +120 -2
  242. package/src/workers/queue-worker.ts +14 -1
  243. package/src/workflows/execution.ts +31 -10
  244. package/dist/chunk-0mbx247x.js.map +0 -43
  245. package/dist/chunk-663csy96.js.map +0 -10
  246. package/dist/chunk-st4xgxey.js.map +0 -45
  247. package/dist/chunk-vp1vc6ee.js +0 -35
  248. package/dist/chunk-vp1vc6ee.js.map +0 -11
  249. /package/dist/{chunk-sa4340y1.js.map → chunk-1ywq4hzk.js.map} +0 -0
  250. /package/dist/{chunk-zg9yryhz.js.map → chunk-261ag4t4.js.map} +0 -0
  251. /package/dist/{chunk-k9pts48t.js.map → chunk-3rsf30p4.js.map} +0 -0
  252. /package/dist/{chunk-8ryen3p3.js.map → chunk-4aw0jwk0.js.map} +0 -0
  253. /package/dist/{chunk-bh6k3nc6.js.map → chunk-4p9rh7jj.js.map} +0 -0
  254. /package/dist/{chunk-n8herkry.js.map → chunk-bv41fmjn.js.map} +0 -0
  255. /package/dist/{chunk-7pc8b818.js.map → chunk-c6cfqydk.js.map} +0 -0
  256. /package/dist/{chunk-0k4avqr2.js.map → chunk-c8bw2b6c.js.map} +0 -0
  257. /package/dist/{chunk-c6qd89g5.js.map → chunk-d6y2wsfg.js.map} +0 -0
  258. /package/dist/{chunk-nnyp53zt.js.map → chunk-f1cyvnrk.js.map} +0 -0
  259. /package/dist/{chunk-bct7hmfc.js.map → chunk-km4rkj4t.js.map} +0 -0
  260. /package/dist/{chunk-qvybnnpe.js.map → chunk-n5x5y80a.js.map} +0 -0
  261. /package/dist/{chunk-4x43bkbp.js.map → chunk-pxtrxm3p.js.map} +0 -0
  262. /package/dist/{chunk-5egfka8j.js.map → chunk-ttba8x6z.js.map} +0 -0
  263. /package/dist/{chunk-g9t3kdtx.js.map → chunk-z8j83gzd.js.map} +0 -0
  264. /package/dist/{chunk-57zpb99z.js.map → chunk-zpw39qhj.js.map} +0 -0
@@ -4,6 +4,7 @@ import type { ProjectionRunFailureCode } from "../projections/types"
4
4
  import type { ProviderScope } from "../provider-scope"
5
5
  import type { ActionRunFailureCode } from "../storage/action-runs/types"
6
6
  import type { AgentRunFailureCode } from "../storage/agents/types"
7
+ import type { AiPricingContext } from "../storage/ai-cost/types"
7
8
  import type { RecordAiModelCallInput } from "../storage/ai-usage"
8
9
  import type { PipelineRunFailureCode } from "../storage/pipeline-runs/types"
9
10
  import type { SyncRunFailureCode } from "../storage/sync-runs/types"
@@ -209,11 +210,18 @@ export type AgentAiUsageRecordPayload = Omit<
209
210
  readonly occurredAt: string
210
211
  }
211
212
 
213
+ export interface AgentAiUsageAccountingPayload {
214
+ readonly pricingContext: AiPricingContext
215
+ readonly ratedAt: string
216
+ }
217
+
212
218
  export interface AgentAiUsageRecordRequestedQueueJob
213
219
  extends QueueJob<
214
220
  "agent.ai-usage.record.requested",
215
221
  {
216
222
  readonly record: AgentAiUsageRecordPayload
223
+ /** Absent on Phase 1 jobs; recovery then uses an empty pricing context. */
224
+ readonly accounting?: AgentAiUsageAccountingPayload
217
225
  }
218
226
  > {}
219
227
 
@@ -0,0 +1,15 @@
1
+ import type { AiCostStorage, AiCostSummary } from "../storage/ai-cost"
2
+
3
+ /** Resolve preferred cost summaries in input order without inventing unavailable accounting. */
4
+ export async function resolveExecutionCosts(input: {
5
+ readonly storage: AiCostStorage | undefined
6
+ readonly projectId: string
7
+ readonly executionIds: readonly string[]
8
+ }): Promise<readonly (AiCostSummary | undefined)[]> {
9
+ if (input.executionIds.length === 0) return []
10
+ if (!input.storage) return input.executionIds.map(() => undefined)
11
+ return input.storage.summarizeExecutions({
12
+ projectId: input.projectId,
13
+ executionIds: input.executionIds,
14
+ })
15
+ }
@@ -5,8 +5,17 @@ import { parseSixbFailure } from "../../errors/internal"
5
5
  import type { SixbFailure } from "../../errors/types"
6
6
  import type { ExecutionStorage } from "../executions"
7
7
  import { AgentStorageError } from "./errors"
8
- import { assertAgentRunExecution } from "./provider"
8
+ import {
9
+ agentContextCheckpointMatchesCreateInput,
10
+ assertAgentContextCheckpointAnchors,
11
+ assertAgentContextCheckpointAuthority,
12
+ assertAgentContextCheckpointReplayState,
13
+ assertAgentRunExecution,
14
+ assertCreateAgentContextCheckpointInput,
15
+ } from "./provider"
9
16
  import type {
17
+ AgentContextCheckpointRecord,
18
+ AgentContextCheckpointStore,
10
19
  AgentMessageRecord,
11
20
  AgentMessageStore,
12
21
  AgentRunFailureCode,
@@ -17,8 +26,10 @@ import type {
17
26
  AgentThreadStore,
18
27
  AppendAgentMessageInput,
19
28
  ConfirmAgentRunExecutionOwnershipInput,
29
+ CreateAgentContextCheckpointInput,
20
30
  CreateAgentRunInput,
21
31
  CreateAgentThreadInput,
32
+ DeleteAgentMessagesByRunInput,
22
33
  FinishAgentRunInput,
23
34
  FinishQueuedAgentRunInput,
24
35
  ListAgentMessagesInput,
@@ -77,21 +88,23 @@ function applyWindow<T>(rows: T[], offset = 0, limit?: number): Window<T> {
77
88
  }
78
89
 
79
90
  /**
80
- * Shared in-memory state behind the three sub-stores. They are tiered for ergonomics
91
+ * Shared in-memory state behind the four sub-stores. They are tiered for ergonomics
81
92
  * (`storage.runs.create(...)`), but several operations span tables — creating/finishing a run
82
- * updates the thread anchor, appending a message bumps thread stats — so they all read and write the
83
- * same maps through this object.
93
+ * updates the thread anchor, appending a message bumps thread stats, and checkpoint creation reads
94
+ * run/thread/message anchors — so they all read and write the same maps through this object.
84
95
  */
85
96
  interface AgentStoreState {
86
97
  readonly threads: Map<string, AgentThreadRecord>
87
98
  readonly runs: Map<string, AgentRunRecord>
88
99
  readonly messages: Map<string, AgentMessageRecord>
100
+ readonly checkpoints: Map<string, AgentContextCheckpointRecord>
89
101
  }
90
102
 
91
103
  export interface InMemoryAgentStorageSnapshot {
92
104
  readonly threads: Map<string, AgentThreadRecord>
93
105
  readonly runs: Map<string, AgentRunRecord>
94
106
  readonly messages: Map<string, AgentMessageRecord>
107
+ readonly checkpoints: Map<string, AgentContextCheckpointRecord>
95
108
  }
96
109
 
97
110
  // ── threads ───────────────────────────────────────────────────────────────────────────────────
@@ -466,6 +479,50 @@ class InMemoryAgentMessageStore implements AgentMessageStore {
466
479
  return clone(message)
467
480
  }
468
481
 
482
+ async deleteByRunId(input: DeleteAgentMessagesByRunInput): Promise<number> {
483
+ const threadKey = key(input.projectId, input.threadId)
484
+ const thread = this.state.threads.get(threadKey)
485
+ if (!thread) {
486
+ throw new AgentStorageError(
487
+ "thread_not_found",
488
+ `[Sixb] Agent thread '${input.threadId}' not found for project '${input.projectId}'.`
489
+ )
490
+ }
491
+
492
+ const messages = [...this.state.messages.entries()].filter(
493
+ ([, message]) =>
494
+ message.projectId === input.projectId &&
495
+ message.threadId === input.threadId &&
496
+ message.runId === input.runId
497
+ )
498
+ if (messages.length === 0) {
499
+ return 0
500
+ }
501
+
502
+ for (const [messageKey] of messages) {
503
+ this.state.messages.delete(messageKey)
504
+ }
505
+
506
+ const remainingMessages = [...this.state.messages.values()]
507
+ .filter(
508
+ (message) => message.projectId === input.projectId && message.threadId === input.threadId
509
+ )
510
+ .sort((left, right) => right.seq - left.seq)
511
+ const latestMessage = remainingMessages[0]
512
+ const updatedAt = new Date()
513
+ this.state.threads.set(
514
+ threadKey,
515
+ clone({
516
+ ...thread,
517
+ messageCount: remainingMessages.length,
518
+ lastMessageAt: latestMessage?.createdAt,
519
+ updatedAt,
520
+ })
521
+ )
522
+
523
+ return messages.length
524
+ }
525
+
469
526
  async getById(params: { projectId: string; id: string }): Promise<AgentMessageRecord | null> {
470
527
  const record = this.state.messages.get(key(params.projectId, params.id))
471
528
  return record ? clone(record) : null
@@ -478,6 +535,7 @@ class InMemoryAgentMessageStore implements AgentMessageStore {
478
535
  const filtered = [...this.state.messages.values()]
479
536
  .filter((message) => message.projectId === input.projectId)
480
537
  .filter((message) => message.threadId === input.threadId)
538
+ .filter((message) => (input.afterSeq === undefined ? true : message.seq > input.afterSeq))
481
539
  .filter((message) => (roles ? roles.has(message.role) : true))
482
540
  .sort((a, b) => (order === "asc" ? a.seq - b.seq : b.seq - a.seq))
483
541
 
@@ -496,21 +554,128 @@ class InMemoryAgentMessageStore implements AgentMessageStore {
496
554
  }
497
555
  }
498
556
 
557
+ // ── context checkpoints ──────────────────────────────────────────────────────────────────────
558
+
559
+ class InMemoryAgentContextCheckpointStore implements AgentContextCheckpointStore {
560
+ constructor(private readonly state: AgentStoreState) {}
561
+
562
+ async create(input: CreateAgentContextCheckpointInput): Promise<AgentContextCheckpointRecord> {
563
+ assertCreateAgentContextCheckpointInput(input)
564
+
565
+ // No `await` between authority checks and append: this is one in-memory critical section.
566
+ const run = this.state.runs.get(key(input.projectId, input.createdByRunId)) ?? null
567
+ const thread = this.state.threads.get(key(input.projectId, input.threadId)) ?? null
568
+ assertAgentContextCheckpointAuthority({ create: input, run, thread })
569
+
570
+ const messages = [...this.state.messages.values()].filter(
571
+ (message) => message.projectId === input.projectId && message.threadId === input.threadId
572
+ )
573
+ const headSeq = messages.reduce((head, message) => Math.max(head, message.seq), 0)
574
+ const latest = this.findLatest(input.projectId, input.threadId)
575
+
576
+ const existingForRun = [...this.state.checkpoints.values()].find(
577
+ (checkpoint) =>
578
+ checkpoint.projectId === input.projectId &&
579
+ checkpoint.createdByRunId === input.createdByRunId
580
+ )
581
+ if (existingForRun) {
582
+ if (agentContextCheckpointMatchesCreateInput(existingForRun, input)) {
583
+ assertAgentContextCheckpointReplayState({
584
+ create: input,
585
+ existing: existingForRun,
586
+ latest,
587
+ headSeq,
588
+ })
589
+ return clone(existingForRun)
590
+ }
591
+ throw new AgentStorageError(
592
+ "invalid_state",
593
+ `[Sixb] Agent run '${input.createdByRunId}' already created a different context checkpoint.`
594
+ )
595
+ }
596
+
597
+ if (this.state.checkpoints.has(key(input.projectId, input.id))) {
598
+ throw new AgentStorageError(
599
+ "duplicate_id",
600
+ `[Sixb] Agent context checkpoint '${input.id}' already exists for project '${input.projectId}'.`
601
+ )
602
+ }
603
+
604
+ const firstRetained =
605
+ messages
606
+ .filter((message) => message.seq > input.summarizedThroughSeq)
607
+ .sort((left, right) => left.seq - right.seq)[0] ?? null
608
+ assertAgentContextCheckpointAnchors({
609
+ create: input,
610
+ latest,
611
+ headSeq,
612
+ firstRetained,
613
+ })
614
+
615
+ const record: AgentContextCheckpointRecord = {
616
+ id: input.id,
617
+ projectId: input.projectId,
618
+ threadId: input.threadId,
619
+ createdByRunId: input.createdByRunId,
620
+ ...(input.expectedPreviousCheckpointId === null
621
+ ? {}
622
+ : { previousCheckpointId: input.expectedPreviousCheckpointId }),
623
+ reason: input.reason,
624
+ summary: input.summary,
625
+ summaryFormatVersion: input.summaryFormatVersion,
626
+ summarizedThroughSeq: input.summarizedThroughSeq,
627
+ observedHeadSeq: input.observedHeadSeq,
628
+ estimatedInputTokensBefore: input.estimatedInputTokensBefore,
629
+ estimatedInputTokensAfter: input.estimatedInputTokensAfter,
630
+ summaryModelId: input.summaryModelId,
631
+ createdAt: new Date(input.createdAt ?? new Date()),
632
+ }
633
+ this.state.checkpoints.set(key(input.projectId, input.id), clone(record))
634
+ return clone(record)
635
+ }
636
+
637
+ async getLatest(input: {
638
+ readonly projectId: string
639
+ readonly threadId: string
640
+ }): Promise<AgentContextCheckpointRecord | null> {
641
+ const record = this.findLatest(input.projectId, input.threadId)
642
+ return record ? clone(record) : null
643
+ }
644
+
645
+ private findLatest(projectId: string, threadId: string): AgentContextCheckpointRecord | null {
646
+ return (
647
+ [...this.state.checkpoints.values()]
648
+ .filter(
649
+ (checkpoint) => checkpoint.projectId === projectId && checkpoint.threadId === threadId
650
+ )
651
+ .sort(
652
+ (left, right) =>
653
+ right.summarizedThroughSeq - left.summarizedThroughSeq ||
654
+ right.createdAt.getTime() - left.createdAt.getTime() ||
655
+ right.id.localeCompare(left.id)
656
+ )[0] ?? null
657
+ )
658
+ }
659
+ }
660
+
499
661
  export class InMemoryAgentStorage implements AgentStorage {
500
662
  private readonly state: AgentStoreState = {
501
663
  threads: new Map(),
502
664
  runs: new Map(),
503
665
  messages: new Map(),
666
+ checkpoints: new Map(),
504
667
  }
505
668
 
506
669
  readonly threads: InMemoryAgentThreadStore
507
670
  readonly runs: InMemoryAgentRunStore
508
671
  readonly messages: InMemoryAgentMessageStore
672
+ readonly checkpoints: InMemoryAgentContextCheckpointStore
509
673
 
510
674
  constructor(executions: ExecutionStorage) {
511
675
  this.threads = new InMemoryAgentThreadStore(this.state)
512
676
  this.runs = new InMemoryAgentRunStore(this.state, executions)
513
677
  this.messages = new InMemoryAgentMessageStore(this.state)
678
+ this.checkpoints = new InMemoryAgentContextCheckpointStore(this.state)
514
679
  }
515
680
 
516
681
  snapshot(): InMemoryAgentStorageSnapshot {
@@ -518,6 +683,7 @@ export class InMemoryAgentStorage implements AgentStorage {
518
683
  threads: structuredClone(this.state.threads),
519
684
  runs: structuredClone(this.state.runs),
520
685
  messages: structuredClone(this.state.messages),
686
+ checkpoints: structuredClone(this.state.checkpoints),
521
687
  }
522
688
  }
523
689
 
@@ -525,6 +691,7 @@ export class InMemoryAgentStorage implements AgentStorage {
525
691
  replace(this.state.threads, snapshot.threads)
526
692
  replace(this.state.runs, snapshot.runs)
527
693
  replace(this.state.messages, snapshot.messages)
694
+ replace(this.state.checkpoints, snapshot.checkpoints)
528
695
  }
529
696
  }
530
697
 
@@ -3,6 +3,9 @@ export { AgentStorageError } from "./errors"
3
3
  export type { InMemoryAgentStorageSnapshot } from "./in-memory"
4
4
  export { InMemoryAgentStorage } from "./in-memory"
5
5
  export type {
6
+ AgentContextCheckpointReason,
7
+ AgentContextCheckpointRecord,
8
+ AgentContextCheckpointStore,
6
9
  AgentExecutionStatus,
7
10
  AgentMessageRecord,
8
11
  AgentMessageRole,
@@ -22,8 +25,10 @@ export type {
22
25
  AgentThreadStore,
23
26
  AppendAgentMessageInput,
24
27
  ConfirmAgentRunExecutionOwnershipInput,
28
+ CreateAgentContextCheckpointInput,
25
29
  CreateAgentRunInput,
26
30
  CreateAgentThreadInput,
31
+ DeleteAgentMessagesByRunInput,
27
32
  FinishAgentRunInput,
28
33
  FinishQueuedAgentRunInput,
29
34
  ListAgentMessagesInput,
@@ -2,6 +2,13 @@ import { agentServiceAccountId } from "../../agents/authority"
2
2
  import type { ExecutionStorage } from "../executions"
3
3
  import { findAgentRunExecution } from "../executions/run-link"
4
4
  import { AgentStorageError } from "./errors"
5
+ import type {
6
+ AgentContextCheckpointRecord,
7
+ AgentMessageRecord,
8
+ AgentRunRecord,
9
+ AgentThreadRecord,
10
+ CreateAgentContextCheckpointInput,
11
+ } from "./types"
5
12
 
6
13
  /** Validate the semantic link between a conversational Agent run and its immutable execution. */
7
14
  export async function assertAgentRunExecution(input: {
@@ -25,3 +32,221 @@ export async function assertAgentRunExecution(input: {
25
32
  )
26
33
  }
27
34
  }
35
+
36
+ /** Validate provider-independent checkpoint fields before entering a storage critical section. */
37
+ export function assertCreateAgentContextCheckpointInput(
38
+ input: CreateAgentContextCheckpointInput,
39
+ prefix = "Sixb"
40
+ ): void {
41
+ for (const [name, value] of [
42
+ ["id", input.id],
43
+ ["projectId", input.projectId],
44
+ ["threadId", input.threadId],
45
+ ["createdByRunId", input.createdByRunId],
46
+ ["executionToken", input.executionToken],
47
+ ["summary", input.summary],
48
+ ["summaryModelId", input.summaryModelId],
49
+ ] as const) {
50
+ if (value.trim().length === 0) {
51
+ throw new AgentStorageError(
52
+ "invalid_input",
53
+ `[${prefix}] Agent context checkpoint '${name}' must not be empty.`
54
+ )
55
+ }
56
+ }
57
+
58
+ if (input.summaryFormatVersion !== 1) {
59
+ throw new AgentStorageError(
60
+ "invalid_input",
61
+ `[${prefix}] Agent context checkpoint summary format version must be 1.`
62
+ )
63
+ }
64
+ if (input.reason !== "threshold" && input.reason !== "overflow") {
65
+ throw new AgentStorageError(
66
+ "invalid_input",
67
+ `[${prefix}] Agent context checkpoint reason must be 'threshold' or 'overflow'.`
68
+ )
69
+ }
70
+ if (
71
+ input.expectedPreviousCheckpointId !== null &&
72
+ input.expectedPreviousCheckpointId.trim().length === 0
73
+ ) {
74
+ throw new AgentStorageError(
75
+ "invalid_input",
76
+ `[${prefix}] Agent context checkpoint expected previous id must not be empty.`
77
+ )
78
+ }
79
+ if (input.createdAt && !Number.isFinite(input.createdAt.getTime())) {
80
+ throw new AgentStorageError(
81
+ "invalid_input",
82
+ `[${prefix}] Agent context checkpoint createdAt must be a valid date.`
83
+ )
84
+ }
85
+
86
+ for (const [name, value, minimum] of [
87
+ ["expectedHeadSeq", input.expectedHeadSeq, 1],
88
+ ["summarizedThroughSeq", input.summarizedThroughSeq, 1],
89
+ ["observedHeadSeq", input.observedHeadSeq, 1],
90
+ ["estimatedInputTokensBefore", input.estimatedInputTokensBefore, 0],
91
+ ["estimatedInputTokensAfter", input.estimatedInputTokensAfter, 0],
92
+ ] as const) {
93
+ if (!Number.isSafeInteger(value) || value < minimum) {
94
+ throw new AgentStorageError(
95
+ "invalid_input",
96
+ `[${prefix}] Agent context checkpoint '${name}' must be a safe integer greater than or equal to ${minimum}.`
97
+ )
98
+ }
99
+ }
100
+
101
+ if (input.observedHeadSeq !== input.expectedHeadSeq) {
102
+ throw new AgentStorageError(
103
+ "invalid_input",
104
+ `[${prefix}] Agent context checkpoint observed head must equal its expected message head.`
105
+ )
106
+ }
107
+ if (input.summarizedThroughSeq >= input.observedHeadSeq) {
108
+ throw new AgentStorageError(
109
+ "invalid_input",
110
+ `[${prefix}] Agent context checkpoint must retain the triggering head message.`
111
+ )
112
+ }
113
+ }
114
+
115
+ /** Assert that the current delivery still owns the active conversational run. */
116
+ export function assertAgentContextCheckpointAuthority(input: {
117
+ readonly create: CreateAgentContextCheckpointInput
118
+ readonly run: AgentRunRecord | null
119
+ readonly thread: AgentThreadRecord | null
120
+ readonly prefix?: string
121
+ }): asserts input is typeof input & {
122
+ readonly run: AgentRunRecord
123
+ readonly thread: AgentThreadRecord
124
+ } {
125
+ const { create, run, thread } = input
126
+ const prefix = input.prefix ?? "Sixb"
127
+ if (!run) {
128
+ throw new AgentStorageError(
129
+ "run_not_found",
130
+ `[${prefix}] Agent run '${create.createdByRunId}' not found for project '${create.projectId}'.`
131
+ )
132
+ }
133
+ if (!thread) {
134
+ throw new AgentStorageError(
135
+ "thread_not_found",
136
+ `[${prefix}] Agent thread '${create.threadId}' not found for project '${create.projectId}'.`
137
+ )
138
+ }
139
+ if (run.threadId !== create.threadId) {
140
+ throw new AgentStorageError(
141
+ "invalid_input",
142
+ `[${prefix}] Agent run '${run.id}' does not belong to thread '${create.threadId}'.`
143
+ )
144
+ }
145
+ if (run.status !== "running") {
146
+ throw new AgentStorageError(
147
+ "invalid_state",
148
+ `[${prefix}] Agent run '${run.id}' is not running (status '${run.status}').`
149
+ )
150
+ }
151
+ if (!run.execution || run.execution.token !== create.executionToken) {
152
+ throw new AgentStorageError(
153
+ "execution_lost",
154
+ `[${prefix}] Execution token is no longer current on agent run '${run.id}'.`
155
+ )
156
+ }
157
+ if (thread.activeRunId !== run.id) {
158
+ throw new AgentStorageError(
159
+ "invalid_state",
160
+ `[${prefix}] Agent run '${run.id}' no longer owns thread '${thread.id}'.`
161
+ )
162
+ }
163
+ }
164
+
165
+ /** Assert both compare-and-swap anchors and the retained-turn boundary. */
166
+ export function assertAgentContextCheckpointAnchors(input: {
167
+ readonly create: CreateAgentContextCheckpointInput
168
+ readonly latest: AgentContextCheckpointRecord | null
169
+ readonly headSeq: number
170
+ readonly firstRetained: AgentMessageRecord | null
171
+ readonly prefix?: string
172
+ }): void {
173
+ const { create, latest, headSeq, firstRetained } = input
174
+ const prefix = input.prefix ?? "Sixb"
175
+ if (headSeq !== create.expectedHeadSeq) {
176
+ throw new AgentStorageError(
177
+ "invalid_state",
178
+ `[${prefix}] Agent thread '${create.threadId}' message head changed from ${create.expectedHeadSeq} to ${headSeq}.`
179
+ )
180
+ }
181
+
182
+ const latestId = latest?.id ?? null
183
+ if (latestId !== create.expectedPreviousCheckpointId) {
184
+ throw new AgentStorageError(
185
+ "invalid_state",
186
+ `[${prefix}] Agent thread '${create.threadId}' checkpoint head changed.`
187
+ )
188
+ }
189
+ if (latest && create.summarizedThroughSeq <= latest.summarizedThroughSeq) {
190
+ throw new AgentStorageError(
191
+ "invalid_input",
192
+ `[${prefix}] Agent context checkpoint boundary must advance beyond sequence ${latest.summarizedThroughSeq}.`
193
+ )
194
+ }
195
+ if (!firstRetained || firstRetained.seq !== create.summarizedThroughSeq + 1) {
196
+ throw new AgentStorageError(
197
+ "invalid_state",
198
+ `[${prefix}] Agent context checkpoint boundary does not align with stored thread messages.`
199
+ )
200
+ }
201
+ if (firstRetained.role !== "user") {
202
+ throw new AgentStorageError(
203
+ "invalid_input",
204
+ `[${prefix}] Agent context checkpoint must retain a complete turn beginning with a user message.`
205
+ )
206
+ }
207
+ }
208
+
209
+ /** Validate the mutable anchors again before returning an idempotently created checkpoint. */
210
+ export function assertAgentContextCheckpointReplayState(input: {
211
+ readonly create: CreateAgentContextCheckpointInput
212
+ readonly existing: AgentContextCheckpointRecord
213
+ readonly latest: AgentContextCheckpointRecord | null
214
+ readonly headSeq: number
215
+ readonly prefix?: string
216
+ }): void {
217
+ const prefix = input.prefix ?? "Sixb"
218
+ if (input.headSeq !== input.create.expectedHeadSeq) {
219
+ throw new AgentStorageError(
220
+ "invalid_state",
221
+ `[${prefix}] Agent thread '${input.create.threadId}' message head changed from ${input.create.expectedHeadSeq} to ${input.headSeq}.`
222
+ )
223
+ }
224
+ if (input.latest?.id !== input.existing.id) {
225
+ throw new AgentStorageError(
226
+ "invalid_state",
227
+ `[${prefix}] Agent thread '${input.create.threadId}' checkpoint head changed after '${input.existing.id}'.`
228
+ )
229
+ }
230
+ }
231
+
232
+ /** Compare the durable semantic payload; delivery token and generated timestamp are not content. */
233
+ export function agentContextCheckpointMatchesCreateInput(
234
+ record: AgentContextCheckpointRecord,
235
+ input: CreateAgentContextCheckpointInput
236
+ ): boolean {
237
+ return (
238
+ record.id === input.id &&
239
+ record.projectId === input.projectId &&
240
+ record.threadId === input.threadId &&
241
+ record.createdByRunId === input.createdByRunId &&
242
+ (record.previousCheckpointId ?? null) === input.expectedPreviousCheckpointId &&
243
+ record.reason === input.reason &&
244
+ record.summary === input.summary &&
245
+ record.summaryFormatVersion === input.summaryFormatVersion &&
246
+ record.summarizedThroughSeq === input.summarizedThroughSeq &&
247
+ record.observedHeadSeq === input.observedHeadSeq &&
248
+ record.estimatedInputTokensBefore === input.estimatedInputTokensBefore &&
249
+ record.estimatedInputTokensAfter === input.estimatedInputTokensAfter &&
250
+ record.summaryModelId === input.summaryModelId
251
+ )
252
+ }
@@ -69,15 +69,17 @@ export const AGENT_RUN_FAILURE_CODES = [
69
69
  export type AgentRunFailureCode = (typeof AGENT_RUN_FAILURE_CODES)[number]
70
70
 
71
71
  /**
72
- * Why a run ended — our own SDK-independent vocabulary (it mirrors the AI SDK unified finish
73
- * reasons), so reads are typed and exhaustive without core depending on `ai`. `other`/`unknown` are
74
- * catch-alls: a provider value we don't recognise still records *that* the run ended.
72
+ * Why a run ended — our own SDK-independent vocabulary. It includes the AI SDK's unified finish
73
+ * reasons plus platform-level endings such as `timeout`, so reads are typed and exhaustive without
74
+ * core depending on `ai`. `other`/`unknown` are catch-alls: an unrecognised provider value still
75
+ * records *that* the run ended.
75
76
  */
76
77
  export const AGENT_RUN_FINISH_REASONS = [
77
78
  "stop",
78
79
  "length",
79
80
  "content-filter",
80
81
  "tool-calls",
82
+ "timeout",
81
83
  "error",
82
84
  "other",
83
85
  "unknown",
@@ -287,9 +289,17 @@ export interface AppendAgentMessageInput extends AgentMessage {
287
289
  readonly completedAt?: Date
288
290
  }
289
291
 
292
+ export interface DeleteAgentMessagesByRunInput {
293
+ readonly projectId: string
294
+ readonly threadId: string
295
+ readonly runId: string
296
+ }
297
+
290
298
  export interface ListAgentMessagesInput {
291
299
  readonly projectId: string
292
300
  readonly threadId: string
301
+ /** Return only messages whose per-thread sequence is greater than this retained boundary. */
302
+ readonly afterSeq?: number
293
303
  readonly roles?: readonly AgentMessageRole[]
294
304
  readonly limit?: number
295
305
  readonly offset?: number
@@ -302,6 +312,55 @@ export interface ListAgentMessagesResult {
302
312
  readonly total: number
303
313
  }
304
314
 
315
+ // ── agent_context_checkpoints — append-only model-context boundaries ──────────────────────────
316
+
317
+ export type AgentContextCheckpointReason = "threshold" | "overflow"
318
+
319
+ /**
320
+ * A durable summary boundary used only when projecting a thread into model context.
321
+ *
322
+ * Checkpoints never replace or mutate transcript messages. Normal thread reads remain authoritative
323
+ * and complete; the worker reads the latest checkpoint and only the retained message tail.
324
+ */
325
+ export interface AgentContextCheckpointRecord {
326
+ readonly id: string
327
+ readonly projectId: string
328
+ readonly threadId: string
329
+ readonly createdByRunId: string
330
+ readonly previousCheckpointId?: string
331
+ readonly reason: AgentContextCheckpointReason
332
+ readonly summary: string
333
+ readonly summaryFormatVersion: 1
334
+ readonly summarizedThroughSeq: number
335
+ readonly observedHeadSeq: number
336
+ readonly estimatedInputTokensBefore: number
337
+ readonly estimatedInputTokensAfter: number
338
+ readonly summaryModelId: string
339
+ readonly createdAt: Date
340
+ }
341
+
342
+ export interface CreateAgentContextCheckpointInput {
343
+ readonly id: string
344
+ readonly projectId: string
345
+ readonly threadId: string
346
+ readonly createdByRunId: string
347
+ /** Compare-and-swap anchor. `null` means the thread must not have a prior checkpoint. */
348
+ readonly expectedPreviousCheckpointId: string | null
349
+ /** Compare-and-swap anchor for the complete transcript observed by the summarizer. */
350
+ readonly expectedHeadSeq: number
351
+ /** Current delivery token for `createdByRunId`; stale redeliveries must not write. */
352
+ readonly executionToken: string
353
+ readonly reason: AgentContextCheckpointReason
354
+ readonly summary: string
355
+ readonly summaryFormatVersion: 1
356
+ readonly summarizedThroughSeq: number
357
+ readonly observedHeadSeq: number
358
+ readonly estimatedInputTokensBefore: number
359
+ readonly estimatedInputTokensAfter: number
360
+ readonly summaryModelId: string
361
+ readonly createdAt?: Date
362
+ }
363
+
305
364
  // ── Store ───────────────────────────────────────────────────────────────────────────────────────
306
365
 
307
366
  export interface AgentThreadStore {
@@ -337,12 +396,27 @@ export interface AgentRunStore {
337
396
  export interface AgentMessageStore {
338
397
  /** Insert a message (its `parts` are the canonical content) and bump thread stats. */
339
398
  append(input: AppendAgentMessageInput): Promise<AgentMessageRecord>
399
+ /** Delete every message produced by one run and repair the thread's message stats. */
400
+ deleteByRunId(input: DeleteAgentMessagesByRunInput): Promise<number>
340
401
  getById(params: { projectId: string; id: string }): Promise<AgentMessageRecord | null>
341
402
  list(input: ListAgentMessagesInput): Promise<ListAgentMessagesResult>
342
403
  }
343
404
 
405
+ export interface AgentContextCheckpointStore {
406
+ /**
407
+ * Append one checkpoint after atomically validating run ownership and both transcript anchors.
408
+ * Repeating the same payload for the same creating run is idempotent.
409
+ */
410
+ create(input: CreateAgentContextCheckpointInput): Promise<AgentContextCheckpointRecord>
411
+ getLatest(input: {
412
+ readonly projectId: string
413
+ readonly threadId: string
414
+ }): Promise<AgentContextCheckpointRecord | null>
415
+ }
416
+
344
417
  export interface AgentStorage {
345
418
  readonly threads: AgentThreadStore
346
419
  readonly runs: AgentRunStore
347
420
  readonly messages: AgentMessageStore
421
+ readonly checkpoints: AgentContextCheckpointStore
348
422
  }