@farukada/aws-langgraph-dynamodb-ts 1.0.0-rc.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (409) hide show
  1. package/README.md +390 -193
  2. package/dist/{backfill → cjs/backfill}/backfill.d.ts +15 -12
  3. package/dist/cjs/backfill/backfill.js +177 -0
  4. package/dist/{checkpointer → cjs/checkpointer}/actions/delete-thread.d.ts +1 -1
  5. package/dist/cjs/checkpointer/actions/delete-thread.js +26 -0
  6. package/dist/{checkpointer → cjs/checkpointer}/actions/get-tuple.d.ts +4 -3
  7. package/dist/cjs/checkpointer/actions/get-tuple.js +22 -0
  8. package/dist/{checkpointer → cjs/checkpointer}/actions/list.d.ts +7 -4
  9. package/dist/cjs/checkpointer/actions/list.js +70 -0
  10. package/dist/{checkpointer → cjs/checkpointer}/actions/put-writes.d.ts +8 -6
  11. package/dist/cjs/checkpointer/actions/put-writes.js +21 -0
  12. package/dist/{checkpointer → cjs/checkpointer}/actions/put.d.ts +21 -15
  13. package/dist/cjs/checkpointer/actions/put.js +79 -0
  14. package/dist/{checkpointer → cjs/checkpointer}/internal/delta-history.d.ts +38 -26
  15. package/dist/cjs/checkpointer/internal/delta-history.js +131 -0
  16. package/dist/{checkpointer → cjs/checkpointer}/internal/listing.d.ts +4 -4
  17. package/dist/cjs/checkpointer/internal/listing.js +104 -0
  18. package/dist/{checkpointer → cjs/checkpointer}/internal/parse.d.ts +51 -15
  19. package/dist/cjs/checkpointer/internal/parse.js +184 -0
  20. package/dist/{checkpointer → cjs/checkpointer}/internal/pending-writes.d.ts +64 -25
  21. package/dist/cjs/checkpointer/internal/pending-writes.js +241 -0
  22. package/dist/{checkpointer → cjs/checkpointer}/internal/read.d.ts +15 -10
  23. package/dist/cjs/checkpointer/internal/read.js +132 -0
  24. package/dist/{checkpointer → cjs/checkpointer}/internal/rows.d.ts +94 -21
  25. package/dist/cjs/checkpointer/internal/rows.js +356 -0
  26. package/dist/{checkpointer → cjs/checkpointer}/internal/setup.d.ts +13 -20
  27. package/dist/cjs/checkpointer/internal/setup.js +25 -0
  28. package/dist/{checkpointer → cjs/checkpointer}/saver.d.ts +72 -36
  29. package/dist/cjs/checkpointer/saver.js +56 -0
  30. package/dist/{checkpointer → cjs/checkpointer}/types.d.ts +1 -1
  31. package/dist/cjs/checkpointer/types.js +2 -0
  32. package/dist/{factory → cjs/factory}/factory.d.ts +25 -20
  33. package/dist/cjs/factory/factory.js +137 -0
  34. package/dist/{factory → cjs/factory}/types.d.ts +12 -12
  35. package/dist/cjs/factory/types.js +2 -0
  36. package/dist/{history → cjs/history}/actions/add-messages.d.ts +18 -10
  37. package/dist/cjs/history/actions/add-messages.js +17 -0
  38. package/dist/{history → cjs/history}/actions/clear.d.ts +1 -1
  39. package/dist/cjs/history/actions/clear.js +29 -0
  40. package/dist/{history → cjs/history}/actions/get-messages.d.ts +11 -9
  41. package/dist/cjs/history/actions/get-messages.js +58 -0
  42. package/dist/{history → cjs/history}/actions/list-sessions.d.ts +3 -3
  43. package/dist/cjs/history/actions/list-sessions.js +67 -0
  44. package/dist/{history → cjs/history}/actions/reconcile-count.d.ts +13 -9
  45. package/dist/cjs/history/actions/reconcile-count.js +8 -0
  46. package/dist/{history → cjs/history}/chat-message-history.d.ts +62 -30
  47. package/dist/cjs/history/chat-message-history.js +61 -0
  48. package/dist/{history → cjs/history}/internal/append.d.ts +64 -32
  49. package/dist/cjs/history/internal/append.js +267 -0
  50. package/dist/{history → cjs/history}/internal/message-read.d.ts +3 -3
  51. package/dist/cjs/history/internal/message-read.js +93 -0
  52. package/dist/{history → cjs/history}/internal/parse.d.ts +2 -2
  53. package/dist/cjs/history/internal/parse.js +113 -0
  54. package/dist/{history → cjs/history}/internal/rows.d.ts +11 -10
  55. package/dist/cjs/history/internal/rows.js +96 -0
  56. package/dist/{history → cjs/history}/internal/session.d.ts +41 -22
  57. package/dist/cjs/history/internal/session.js +296 -0
  58. package/dist/{history → cjs/history}/internal/setup.d.ts +2 -2
  59. package/dist/cjs/history/internal/setup.js +60 -0
  60. package/dist/{history → cjs/history}/session-adapter.d.ts +0 -6
  61. package/dist/cjs/history/session-adapter.js +38 -0
  62. package/dist/{history → cjs/history}/types.d.ts +18 -15
  63. package/dist/cjs/history/types.js +2 -0
  64. package/dist/{index.d.ts → cjs/index.d.ts} +27 -27
  65. package/dist/cjs/index.js +25 -0
  66. package/dist/cjs/package.json +1 -0
  67. package/dist/{shared → cjs/shared}/adapter.d.ts +27 -16
  68. package/dist/cjs/shared/adapter.js +70 -0
  69. package/dist/cjs/shared/clock.js +14 -0
  70. package/dist/{shared → cjs/shared}/codec/codec.d.ts +37 -20
  71. package/dist/cjs/shared/codec/codec.js +162 -0
  72. package/dist/{shared → cjs/shared}/codec/compression.d.ts +9 -4
  73. package/dist/cjs/shared/codec/compression.js +45 -0
  74. package/dist/cjs/shared/codec/json-serde.js +58 -0
  75. package/dist/{shared → cjs/shared}/codec/s3/client-types.d.ts +2 -1
  76. package/dist/cjs/shared/codec/s3/client-types.js +6 -0
  77. package/dist/{shared → cjs/shared}/codec/s3/client.d.ts +25 -7
  78. package/dist/cjs/shared/codec/s3/client.js +78 -0
  79. package/dist/{shared → cjs/shared}/codec/s3/config.d.ts +12 -7
  80. package/dist/cjs/shared/codec/s3/config.js +92 -0
  81. package/dist/{shared → cjs/shared}/codec/s3/lifecycle.d.ts +71 -17
  82. package/dist/cjs/shared/codec/s3/lifecycle.js +223 -0
  83. package/dist/{shared → cjs/shared}/codec/s3/offloader.d.ts +42 -29
  84. package/dist/cjs/shared/codec/s3/offloader.js +289 -0
  85. package/dist/cjs/shared/concurrency.js +31 -0
  86. package/dist/{shared → cjs/shared}/dynamodb/abort.d.ts +2 -2
  87. package/dist/cjs/shared/dynamodb/abort.js +16 -0
  88. package/dist/{shared → cjs/shared}/dynamodb/batch-write.d.ts +2 -2
  89. package/dist/cjs/shared/dynamodb/batch-write.js +79 -0
  90. package/dist/cjs/shared/dynamodb/cancellation.js +37 -0
  91. package/dist/{shared → cjs/shared}/dynamodb/client.d.ts +24 -22
  92. package/dist/cjs/shared/dynamodb/client.js +40 -0
  93. package/dist/{shared → cjs/shared}/dynamodb/idempotent-write.d.ts +64 -19
  94. package/dist/cjs/shared/dynamodb/idempotent-write.js +173 -0
  95. package/dist/{shared → cjs/shared}/dynamodb/paginate.d.ts +2 -2
  96. package/dist/cjs/shared/dynamodb/paginate.js +90 -0
  97. package/dist/{shared → cjs/shared}/dynamodb/partition-delete.d.ts +6 -6
  98. package/dist/cjs/shared/dynamodb/partition-delete.js +177 -0
  99. package/dist/{shared → cjs/shared}/dynamodb/recency-index.d.ts +27 -15
  100. package/dist/cjs/shared/dynamodb/recency-index.js +146 -0
  101. package/dist/{shared → cjs/shared}/dynamodb/retry.d.ts +37 -6
  102. package/dist/cjs/shared/dynamodb/retry.js +193 -0
  103. package/dist/cjs/shared/dynamodb/row-size.d.ts +33 -0
  104. package/dist/cjs/shared/dynamodb/row-size.js +30 -0
  105. package/dist/{shared → cjs/shared}/dynamodb/table-schema.d.ts +27 -18
  106. package/dist/cjs/shared/dynamodb/table-schema.js +52 -0
  107. package/dist/{shared → cjs/shared}/errors/base-error.d.ts +42 -7
  108. package/dist/cjs/shared/errors/base-error.js +73 -0
  109. package/dist/{shared → cjs/shared}/errors/boundary.d.ts +29 -14
  110. package/dist/cjs/shared/errors/boundary.js +61 -0
  111. package/dist/cjs/shared/errors/classify.d.ts +206 -0
  112. package/dist/cjs/shared/errors/classify.js +232 -0
  113. package/dist/{shared → cjs/shared}/errors/error-code.d.ts +17 -10
  114. package/dist/cjs/shared/errors/error-code.js +27 -0
  115. package/dist/{shared → cjs/shared}/errors/errors.d.ts +75 -9
  116. package/dist/cjs/shared/errors/errors.js +123 -0
  117. package/dist/cjs/shared/logging/logger.js +30 -0
  118. package/dist/{shared → cjs/shared}/logging/redaction.d.ts +8 -4
  119. package/dist/cjs/shared/logging/redaction.js +145 -0
  120. package/dist/{shared → cjs/shared}/logging/secret-patterns.d.ts +30 -7
  121. package/dist/cjs/shared/logging/secret-patterns.js +93 -0
  122. package/dist/cjs/shared/logging/truncate.js +31 -0
  123. package/dist/{shared → cjs/shared}/options.d.ts +27 -11
  124. package/dist/cjs/shared/options.js +2 -0
  125. package/dist/cjs/shared/ulid.js +83 -0
  126. package/dist/{shared → cjs/shared}/validation/collaborators.d.ts +21 -2
  127. package/dist/cjs/shared/validation/collaborators.js +79 -0
  128. package/dist/{shared → cjs/shared}/validation/option-shape.d.ts +7 -5
  129. package/dist/cjs/shared/validation/option-shape.js +31 -0
  130. package/dist/{shared → cjs/shared}/validation/options.d.ts +4 -4
  131. package/dist/cjs/shared/validation/options.js +166 -0
  132. package/dist/cjs/shared/validation/primitives.js +114 -0
  133. package/dist/{shared → cjs/shared}/validation/ttl.d.ts +26 -9
  134. package/dist/cjs/shared/validation/ttl.js +52 -0
  135. package/dist/{store → cjs/store}/actions/list-namespaces.d.ts +5 -5
  136. package/dist/cjs/store/actions/list-namespaces.js +92 -0
  137. package/dist/{store → cjs/store}/actions/put.d.ts +11 -4
  138. package/dist/cjs/store/actions/put.js +49 -0
  139. package/dist/{store → cjs/store}/actions/reconcile-vector-index.d.ts +5 -5
  140. package/dist/cjs/store/actions/reconcile-vector-index.js +13 -0
  141. package/dist/{store → cjs/store}/actions/search.d.ts +2 -2
  142. package/dist/cjs/store/actions/search.js +26 -0
  143. package/dist/cjs/store/internal/batch-plan.d.ts +56 -0
  144. package/dist/cjs/store/internal/batch-plan.js +32 -0
  145. package/dist/{store → cjs/store}/internal/filter.d.ts +3 -3
  146. package/dist/cjs/store/internal/filter.js +64 -0
  147. package/dist/cjs/store/internal/get-item.d.ts +77 -0
  148. package/dist/cjs/store/internal/get-item.js +58 -0
  149. package/dist/{store → cjs/store}/internal/item-write.d.ts +72 -32
  150. package/dist/cjs/store/internal/item-write.js +181 -0
  151. package/dist/{store → cjs/store}/internal/parse.d.ts +15 -10
  152. package/dist/cjs/store/internal/parse.js +180 -0
  153. package/dist/{store → cjs/store}/internal/rows.d.ts +38 -34
  154. package/dist/cjs/store/internal/rows.js +166 -0
  155. package/dist/{store → cjs/store}/internal/semantic-search.d.ts +2 -2
  156. package/dist/cjs/store/internal/semantic-search.js +211 -0
  157. package/dist/{store → cjs/store}/internal/setup.d.ts +10 -15
  158. package/dist/cjs/store/internal/setup.js +103 -0
  159. package/dist/{store → cjs/store}/internal/table-search.d.ts +5 -5
  160. package/dist/cjs/store/internal/table-search.js +123 -0
  161. package/dist/{store → cjs/store}/internal/vector-index.d.ts +26 -15
  162. package/dist/cjs/store/internal/vector-index.js +269 -0
  163. package/dist/{store → cjs/store}/store.d.ts +82 -39
  164. package/dist/cjs/store/store.js +97 -0
  165. package/dist/{store → cjs/store}/types.d.ts +25 -10
  166. package/dist/cjs/store/types.js +2 -0
  167. package/dist/cjs/store/vector-backend.js +4 -0
  168. package/dist/esm/backfill/backfill.d.ts +171 -0
  169. package/dist/esm/backfill/backfill.js +170 -0
  170. package/dist/{checkpointer/actions/delete-thread.js → esm/checkpointer/actions/delete-thread.d.ts} +4 -26
  171. package/dist/esm/checkpointer/actions/delete-thread.js +23 -0
  172. package/dist/{checkpointer/actions/get-tuple.js → esm/checkpointer/actions/get-tuple.d.ts} +7 -24
  173. package/dist/esm/checkpointer/actions/get-tuple.js +19 -0
  174. package/dist/esm/checkpointer/actions/list.d.ts +55 -0
  175. package/dist/esm/checkpointer/actions/list.js +67 -0
  176. package/dist/{checkpointer/actions/put-writes.js → esm/checkpointer/actions/put-writes.d.ts} +10 -37
  177. package/dist/esm/checkpointer/actions/put-writes.js +18 -0
  178. package/dist/esm/checkpointer/actions/put.d.ts +95 -0
  179. package/dist/esm/checkpointer/actions/put.js +75 -0
  180. package/dist/esm/checkpointer/internal/delta-history.d.ts +124 -0
  181. package/dist/esm/checkpointer/internal/delta-history.js +126 -0
  182. package/dist/{checkpointer/internal/listing.js → esm/checkpointer/internal/listing.d.ts} +22 -118
  183. package/dist/esm/checkpointer/internal/listing.js +95 -0
  184. package/dist/esm/checkpointer/internal/parse.d.ts +298 -0
  185. package/dist/esm/checkpointer/internal/parse.js +169 -0
  186. package/dist/esm/checkpointer/internal/pending-writes.d.ts +314 -0
  187. package/dist/esm/checkpointer/internal/pending-writes.js +229 -0
  188. package/dist/esm/checkpointer/internal/read.d.ts +135 -0
  189. package/dist/esm/checkpointer/internal/read.js +125 -0
  190. package/dist/esm/checkpointer/internal/rows.d.ts +644 -0
  191. package/dist/esm/checkpointer/internal/rows.js +323 -0
  192. package/dist/esm/checkpointer/internal/setup.d.ts +47 -0
  193. package/dist/esm/checkpointer/internal/setup.js +21 -0
  194. package/dist/{checkpointer/saver.js → esm/checkpointer/saver.d.ts} +84 -87
  195. package/dist/esm/checkpointer/saver.js +52 -0
  196. package/dist/esm/checkpointer/types.d.ts +51 -0
  197. package/dist/esm/checkpointer/types.js +1 -0
  198. package/dist/esm/factory/factory.d.ts +154 -0
  199. package/dist/esm/factory/factory.js +133 -0
  200. package/dist/esm/factory/types.d.ts +76 -0
  201. package/dist/esm/factory/types.js +1 -0
  202. package/dist/{history/actions/add-messages.js → esm/history/actions/add-messages.d.ts} +20 -26
  203. package/dist/esm/history/actions/add-messages.js +14 -0
  204. package/dist/{history/actions/clear.js → esm/history/actions/clear.d.ts} +4 -35
  205. package/dist/esm/history/actions/clear.js +26 -0
  206. package/dist/esm/history/actions/get-messages.d.ts +60 -0
  207. package/dist/esm/history/actions/get-messages.js +55 -0
  208. package/dist/esm/history/actions/list-sessions.d.ts +55 -0
  209. package/dist/esm/history/actions/list-sessions.js +64 -0
  210. package/dist/{history/actions/reconcile-count.js → esm/history/actions/reconcile-count.d.ts} +14 -16
  211. package/dist/esm/history/actions/reconcile-count.js +5 -0
  212. package/dist/{history/chat-message-history.js → esm/history/chat-message-history.d.ts} +76 -87
  213. package/dist/esm/history/chat-message-history.js +57 -0
  214. package/dist/esm/history/internal/append.d.ts +244 -0
  215. package/dist/esm/history/internal/append.js +259 -0
  216. package/dist/esm/history/internal/message-read.d.ts +84 -0
  217. package/dist/esm/history/internal/message-read.js +89 -0
  218. package/dist/esm/history/internal/parse.d.ts +153 -0
  219. package/dist/esm/history/internal/parse.js +105 -0
  220. package/dist/{history/internal/rows.js → esm/history/internal/rows.d.ts} +58 -112
  221. package/dist/esm/history/internal/rows.js +83 -0
  222. package/dist/esm/history/internal/session.d.ts +350 -0
  223. package/dist/esm/history/internal/session.js +285 -0
  224. package/dist/esm/history/internal/setup.d.ts +64 -0
  225. package/dist/esm/history/internal/setup.js +56 -0
  226. package/dist/{history/session-adapter.js → esm/history/session-adapter.d.ts} +25 -39
  227. package/dist/esm/history/session-adapter.js +34 -0
  228. package/dist/esm/history/types.d.ts +102 -0
  229. package/dist/esm/history/types.js +1 -0
  230. package/dist/esm/index.d.ts +53 -0
  231. package/dist/esm/index.js +10 -0
  232. package/dist/esm/shared/adapter.d.ts +146 -0
  233. package/dist/esm/shared/adapter.js +65 -0
  234. package/dist/{shared/clock.js → esm/shared/clock.d.ts} +3 -14
  235. package/dist/esm/shared/clock.js +9 -0
  236. package/dist/esm/shared/codec/codec.d.ts +336 -0
  237. package/dist/esm/shared/codec/codec.js +150 -0
  238. package/dist/esm/shared/codec/compression.d.ts +66 -0
  239. package/dist/esm/shared/codec/compression.js +40 -0
  240. package/dist/esm/shared/codec/json-serde.d.ts +80 -0
  241. package/dist/esm/shared/codec/json-serde.js +54 -0
  242. package/dist/esm/shared/codec/s3/client-types.d.ts +54 -0
  243. package/dist/esm/shared/codec/s3/client-types.js +3 -0
  244. package/dist/esm/shared/codec/s3/client.d.ts +63 -0
  245. package/dist/esm/shared/codec/s3/client.js +40 -0
  246. package/dist/{shared/codec/s3/config.js → esm/shared/codec/s3/config.d.ts} +45 -93
  247. package/dist/esm/shared/codec/s3/config.js +79 -0
  248. package/dist/esm/shared/codec/s3/lifecycle.d.ts +220 -0
  249. package/dist/esm/shared/codec/s3/lifecycle.js +214 -0
  250. package/dist/esm/shared/codec/s3/offloader.d.ts +428 -0
  251. package/dist/esm/shared/codec/s3/offloader.js +278 -0
  252. package/dist/{shared/concurrency.js → esm/shared/concurrency.d.ts} +2 -37
  253. package/dist/esm/shared/concurrency.js +27 -0
  254. package/dist/{shared/dynamodb/abort.js → esm/shared/dynamodb/abort.d.ts} +4 -16
  255. package/dist/esm/shared/dynamodb/abort.js +12 -0
  256. package/dist/esm/shared/dynamodb/batch-write.d.ts +86 -0
  257. package/dist/esm/shared/dynamodb/batch-write.js +74 -0
  258. package/dist/{shared/dynamodb/cancellation.js → esm/shared/dynamodb/cancellation.d.ts} +25 -53
  259. package/dist/esm/shared/dynamodb/cancellation.js +30 -0
  260. package/dist/{shared/dynamodb/client.js → esm/shared/dynamodb/client.d.ts} +74 -64
  261. package/dist/esm/shared/dynamodb/client.js +35 -0
  262. package/dist/{shared/dynamodb/idempotent-write.js → esm/shared/dynamodb/idempotent-write.d.ts} +172 -169
  263. package/dist/esm/shared/dynamodb/idempotent-write.js +153 -0
  264. package/dist/esm/shared/dynamodb/paginate.d.ts +111 -0
  265. package/dist/esm/shared/dynamodb/paginate.js +84 -0
  266. package/dist/esm/shared/dynamodb/partition-delete.d.ts +204 -0
  267. package/dist/esm/shared/dynamodb/partition-delete.js +171 -0
  268. package/dist/esm/shared/dynamodb/recency-index.d.ts +243 -0
  269. package/dist/esm/shared/dynamodb/recency-index.js +136 -0
  270. package/dist/esm/shared/dynamodb/retry.d.ts +317 -0
  271. package/dist/esm/shared/dynamodb/retry.js +180 -0
  272. package/dist/esm/shared/dynamodb/row-size.d.ts +33 -0
  273. package/dist/esm/shared/dynamodb/row-size.js +26 -0
  274. package/dist/{shared/dynamodb/table-schema.js → esm/shared/dynamodb/table-schema.d.ts} +57 -67
  275. package/dist/esm/shared/dynamodb/table-schema.js +43 -0
  276. package/dist/esm/shared/errors/base-error.d.ts +231 -0
  277. package/dist/esm/shared/errors/base-error.js +64 -0
  278. package/dist/esm/shared/errors/boundary.d.ts +86 -0
  279. package/dist/esm/shared/errors/boundary.js +54 -0
  280. package/dist/esm/shared/errors/classify.d.ts +206 -0
  281. package/dist/esm/shared/errors/classify.js +220 -0
  282. package/dist/{shared/errors/error-code.js → esm/shared/errors/error-code.d.ts} +39 -43
  283. package/dist/esm/shared/errors/error-code.js +24 -0
  284. package/dist/{shared/errors/errors.js → esm/shared/errors/errors.d.ts} +92 -98
  285. package/dist/esm/shared/errors/errors.js +110 -0
  286. package/dist/{shared/logging/logger.js → esm/shared/logging/logger.d.ts} +22 -52
  287. package/dist/esm/shared/logging/logger.js +25 -0
  288. package/dist/esm/shared/logging/redaction.d.ts +123 -0
  289. package/dist/esm/shared/logging/redaction.js +140 -0
  290. package/dist/{shared/logging/secret-patterns.js → esm/shared/logging/secret-patterns.d.ts} +46 -87
  291. package/dist/esm/shared/logging/secret-patterns.js +83 -0
  292. package/dist/{shared/logging/truncate.js → esm/shared/logging/truncate.d.ts} +6 -40
  293. package/dist/esm/shared/logging/truncate.js +25 -0
  294. package/dist/esm/shared/options.d.ts +100 -0
  295. package/dist/esm/shared/options.js +1 -0
  296. package/dist/{shared/ulid.js → esm/shared/ulid.d.ts} +4 -84
  297. package/dist/esm/shared/ulid.js +77 -0
  298. package/dist/{shared/validation/collaborators.js → esm/shared/validation/collaborators.d.ts} +37 -65
  299. package/dist/esm/shared/validation/collaborators.js +70 -0
  300. package/dist/{shared/validation/option-shape.js → esm/shared/validation/option-shape.d.ts} +14 -36
  301. package/dist/esm/shared/validation/option-shape.js +24 -0
  302. package/dist/esm/shared/validation/options.d.ts +145 -0
  303. package/dist/esm/shared/validation/options.js +156 -0
  304. package/dist/{shared/validation/primitives.js → esm/shared/validation/primitives.d.ts} +30 -125
  305. package/dist/esm/shared/validation/primitives.js +100 -0
  306. package/dist/esm/shared/validation/ttl.d.ts +94 -0
  307. package/dist/esm/shared/validation/ttl.js +46 -0
  308. package/dist/esm/store/actions/list-namespaces.d.ts +79 -0
  309. package/dist/esm/store/actions/list-namespaces.js +86 -0
  310. package/dist/esm/store/actions/put.d.ts +43 -0
  311. package/dist/esm/store/actions/put.js +46 -0
  312. package/dist/{store/actions/reconcile-vector-index.js → esm/store/actions/reconcile-vector-index.d.ts} +8 -16
  313. package/dist/esm/store/actions/reconcile-vector-index.js +10 -0
  314. package/dist/esm/store/actions/search.d.ts +38 -0
  315. package/dist/esm/store/actions/search.js +23 -0
  316. package/dist/esm/store/internal/batch-plan.d.ts +56 -0
  317. package/dist/esm/store/internal/batch-plan.js +28 -0
  318. package/dist/esm/store/internal/filter.d.ts +43 -0
  319. package/dist/esm/store/internal/filter.js +60 -0
  320. package/dist/esm/store/internal/get-item.d.ts +77 -0
  321. package/dist/esm/store/internal/get-item.js +54 -0
  322. package/dist/esm/store/internal/item-write.d.ts +270 -0
  323. package/dist/esm/store/internal/item-write.js +173 -0
  324. package/dist/esm/store/internal/parse.d.ts +230 -0
  325. package/dist/esm/store/internal/parse.js +169 -0
  326. package/dist/{store/internal/rows.js → esm/store/internal/rows.d.ts} +111 -199
  327. package/dist/esm/store/internal/rows.js +147 -0
  328. package/dist/esm/store/internal/semantic-search.d.ts +168 -0
  329. package/dist/esm/store/internal/semantic-search.js +200 -0
  330. package/dist/esm/store/internal/setup.d.ts +96 -0
  331. package/dist/esm/store/internal/setup.js +98 -0
  332. package/dist/esm/store/internal/table-search.d.ts +100 -0
  333. package/dist/esm/store/internal/table-search.js +119 -0
  334. package/dist/esm/store/internal/vector-index.d.ts +258 -0
  335. package/dist/esm/store/internal/vector-index.js +256 -0
  336. package/dist/{store/store.js → esm/store/store.d.ts} +99 -133
  337. package/dist/esm/store/store.js +93 -0
  338. package/dist/esm/store/types.d.ts +111 -0
  339. package/dist/esm/store/types.js +1 -0
  340. package/dist/esm/store/vector-backend.d.ts +104 -0
  341. package/dist/esm/store/vector-backend.js +1 -0
  342. package/package.json +50 -44
  343. package/dist/backfill/backfill.js +0 -393
  344. package/dist/checkpointer/actions/list.js +0 -142
  345. package/dist/checkpointer/actions/put.js +0 -195
  346. package/dist/checkpointer/internal/delta-history.js +0 -252
  347. package/dist/checkpointer/internal/parse.js +0 -372
  348. package/dist/checkpointer/internal/pending-writes.js +0 -588
  349. package/dist/checkpointer/internal/read.js +0 -264
  350. package/dist/checkpointer/internal/rows.js +0 -834
  351. package/dist/checkpointer/internal/setup.js +0 -72
  352. package/dist/checkpointer/types.js +0 -12
  353. package/dist/factory/factory.js +0 -266
  354. package/dist/factory/types.js +0 -10
  355. package/dist/history/actions/get-messages.js +0 -141
  356. package/dist/history/actions/list-sessions.js +0 -156
  357. package/dist/history/internal/append.js +0 -500
  358. package/dist/history/internal/message-read.js +0 -204
  359. package/dist/history/internal/parse.js +0 -252
  360. package/dist/history/internal/session.js +0 -628
  361. package/dist/history/internal/setup.js +0 -106
  362. package/dist/history/types.js +0 -12
  363. package/dist/index.js +0 -51
  364. package/dist/shared/adapter.js +0 -143
  365. package/dist/shared/codec/codec.js +0 -441
  366. package/dist/shared/codec/compression.js +0 -89
  367. package/dist/shared/codec/json-serde.js +0 -191
  368. package/dist/shared/codec/s3/client-types.js +0 -26
  369. package/dist/shared/codec/s3/client.js +0 -97
  370. package/dist/shared/codec/s3/lifecycle.js +0 -355
  371. package/dist/shared/codec/s3/offloader.js +0 -658
  372. package/dist/shared/dynamodb/batch-write.js +0 -173
  373. package/dist/shared/dynamodb/paginate.js +0 -188
  374. package/dist/shared/dynamodb/partition-delete.js +0 -340
  375. package/dist/shared/dynamodb/recency-index.js +0 -377
  376. package/dist/shared/dynamodb/retry.js +0 -463
  377. package/dist/shared/errors/base-error.js +0 -174
  378. package/dist/shared/errors/boundary.js +0 -143
  379. package/dist/shared/errors/classify.d.ts +0 -97
  380. package/dist/shared/errors/classify.js +0 -257
  381. package/dist/shared/logging/redaction.js +0 -316
  382. package/dist/shared/options.js +0 -11
  383. package/dist/shared/validation/options.js +0 -328
  384. package/dist/shared/validation/ttl.js +0 -132
  385. package/dist/store/actions/list-namespaces.js +0 -197
  386. package/dist/store/actions/put.js +0 -78
  387. package/dist/store/actions/search.js +0 -66
  388. package/dist/store/internal/batch-plan.d.ts +0 -26
  389. package/dist/store/internal/batch-plan.js +0 -109
  390. package/dist/store/internal/filter.js +0 -137
  391. package/dist/store/internal/get-item.d.ts +0 -45
  392. package/dist/store/internal/get-item.js +0 -115
  393. package/dist/store/internal/item-write.js +0 -463
  394. package/dist/store/internal/parse.js +0 -350
  395. package/dist/store/internal/semantic-search.js +0 -389
  396. package/dist/store/internal/setup.js +0 -223
  397. package/dist/store/internal/table-search.js +0 -213
  398. package/dist/store/internal/vector-index.js +0 -546
  399. package/dist/store/types.js +0 -15
  400. package/dist/store/vector-backend.js +0 -17
  401. /package/dist/{shared → cjs/shared}/clock.d.ts +0 -0
  402. /package/dist/{shared → cjs/shared}/codec/json-serde.d.ts +0 -0
  403. /package/dist/{shared → cjs/shared}/concurrency.d.ts +0 -0
  404. /package/dist/{shared → cjs/shared}/dynamodb/cancellation.d.ts +0 -0
  405. /package/dist/{shared → cjs/shared}/logging/logger.d.ts +0 -0
  406. /package/dist/{shared → cjs/shared}/logging/truncate.d.ts +0 -0
  407. /package/dist/{shared → cjs/shared}/ulid.d.ts +0 -0
  408. /package/dist/{shared → cjs/shared}/validation/primitives.d.ts +0 -0
  409. /package/dist/{store → cjs/store}/vector-backend.d.ts +0 -0
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Hides when a listing reads, and when it stops.
3
+ *
4
+ * A `limit` of `0` is answered before any request is built, a config that
5
+ * pins one checkpoint in a known namespace is a single direct read rather than
6
+ * a range, and every other listing streams tuples until the caller stops
7
+ * pulling or `limit` is reached. The read is deliberately unbounded and
8
+ * eventually consistent; past a threshold an operator is warned instead of the
9
+ * caller being refused. Where the rows come from is `listing`'s concern.
10
+ */
11
+ import type { RunnableConfig } from '@langchain/core/runnables';
12
+ import type { CheckpointListOptions, CheckpointTuple } from '@langchain/langgraph-checkpoint';
13
+ import type { CheckpointerContext } from '../internal/setup.js';
14
+ /**
15
+ * Yield checkpoint tuples for a thread, newest first: every namespace when the
16
+ * config names none (grouped by namespace, newest first within each), else the
17
+ * one namespace given. Without a `thread_id` every thread in the table is
18
+ * listed: through a table scan, as the reference savers do, which is unordered
19
+ * across threads, or through the recency index when `indexName` is set. Either
20
+ * read is cross-tenant by construction. Honors `options.before` (only
21
+ * checkpoints older than the given id), `options.filter` (metadata equality),
22
+ * and `options.limit` (max tuples yielded; the read stops right after the
23
+ * yield that reaches it).
24
+ *
25
+ * Accepts: `config` — `thread_id` scopes the read to one thread and its absence
26
+ * lists every thread in the table, through a scan as the reference savers do or
27
+ * through the recency index when `indexName` is set; `checkpoint_ns` scopes to
28
+ * one namespace and its absence spans every namespace of the thread.
29
+ * `options.before` — only checkpoints older than that id. `options.filter` —
30
+ * metadata equality. `options.limit` — at most this many tuples, up to the
31
+ * package's page ceiling; `0` yields nothing, which is what the reference
32
+ * returns, and a negative value is refused.
33
+ *
34
+ * Returns: an async generator over the tuples. With a `thread_id`, newest
35
+ * first within each namespace; without one, newest first across threads
36
+ * through the recency index, and on the scan path in the table's own order —
37
+ * oldest first within a thread, as DynamoDB stores an item collection, and
38
+ * threads in no particular order. The read stops right after the yield that
39
+ * reaches `limit`, and abandoning the generator stops it too.
40
+ *
41
+ * Throws: `VALIDATION`, from the first `.next()` and before any read, for
42
+ * a config of the wrong shape (`config`, `configurable`, `signal`), a
43
+ * malformed identifier, or options that fail the checks
44
+ * {@link parseListScope} makes;
45
+ * `FORMAT_UNSUPPORTED` for a row of ours written by a newer version; whatever
46
+ * the reads and decodes throw.
47
+ *
48
+ * Guarantees: eventually consistent — a listing tolerates the replica lag
49
+ * `getTuple` does not. The read is deliberately unbounded: this generator
50
+ * streams and never accumulates, `limit` returns early, and a raw-row cap would
51
+ * turn a caller asking for a handful of rare matches over a large thread into a
52
+ * hard error instead of the true (possibly empty) answer. Past the warning
53
+ * threshold an operator is told to narrow the filter or pass a limit.
54
+ */
55
+ export declare function listCheckpoints(context: CheckpointerContext, config: RunnableConfig, options?: CheckpointListOptions): AsyncGenerator<CheckpointTuple>;
@@ -0,0 +1,67 @@
1
+ import { nowSeconds } from '../../shared/clock.js';
2
+ import { LIST_SCAN_WARN_THRESHOLD } from '../../shared/dynamodb/paginate.js';
3
+ import { isExpiredRow } from '../../shared/dynamodb/table-schema.js';
4
+ import { metaRows, parseListedRow, passesKeyFilters, passesMetadataFilter, } from '../internal/listing.js';
5
+ import { parseListScope, } from '../internal/parse.js';
6
+ import { assembleTuple, fetchTargetMeta } from '../internal/read.js';
7
+ async function tupleFor(context, meta, scope) {
8
+ if (!passesKeyFilters(meta, scope))
9
+ return undefined;
10
+ const verdict = await passesMetadataFilter(context, meta, scope);
11
+ if (!verdict.pass)
12
+ return undefined;
13
+ return assembleTuple(context, { threadId: meta.threadId, checkpointNs: meta.checkpointNs }, meta, {
14
+ signal: scope.signal,
15
+ consistent: false,
16
+ metadata: verdict.metadata,
17
+ });
18
+ }
19
+ async function* listOne(context, scope) {
20
+ const meta = await fetchTargetMeta(context, {
21
+ threadId: scope.threadId,
22
+ checkpointNs: scope.checkpointNs,
23
+ checkpointId: scope.checkpointId,
24
+ }, scope.signal, 'list');
25
+ if (!meta)
26
+ return;
27
+ const tuple = await tupleFor(context, meta, scope);
28
+ if (tuple)
29
+ yield tuple;
30
+ }
31
+ function asksForNothing(scope) {
32
+ return scope.limit === 0;
33
+ }
34
+ function addressesOneRow(scope) {
35
+ return (scope.threadId !== undefined &&
36
+ scope.checkpointId !== undefined &&
37
+ scope.checkpointNs !== undefined);
38
+ }
39
+ export async function* listCheckpoints(context, config, options) {
40
+ const scope = parseListScope(config, options);
41
+ if (asksForNothing(scope))
42
+ return;
43
+ if (addressesOneRow(scope)) {
44
+ yield* listOne(context, scope);
45
+ return;
46
+ }
47
+ const now = nowSeconds();
48
+ let yielded = 0;
49
+ let scanned = 0;
50
+ for await (const raw of metaRows(context, scope, now)) {
51
+ scanned += 1;
52
+ if (scanned === LIST_SCAN_WARN_THRESHOLD) {
53
+ context.logger.warn('list: scanned a large number of rows without the caller stopping; this read is ' +
54
+ 'deliberately unbounded, so narrow the filter or pass options.limit', { threadId: scope.threadId, checkpointNs: scope.checkpointNs, scanned });
55
+ }
56
+ const meta = parseListedRow(context, raw);
57
+ if (!meta || isExpiredRow(meta, now))
58
+ continue;
59
+ const tuple = await tupleFor(context, meta, scope);
60
+ if (!tuple)
61
+ continue;
62
+ yield tuple;
63
+ yielded += 1;
64
+ if (scope.limit !== undefined && yielded >= scope.limit)
65
+ return;
66
+ }
67
+ }
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * Hides how one `putWrites` call's rows are known to be one call's.
4
3
  *
@@ -9,34 +8,19 @@
9
8
  * pick the earliest call that wrote a channel. A caller passes writes and a
10
9
  * task id and never sees the group.
11
10
  */
12
- Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.putWrites = putWrites;
14
- const ulid_1 = require("../../shared/ulid");
15
- const ttl_1 = require("../../shared/validation/ttl");
16
- const parse_1 = require("../internal/parse");
17
- const pending_writes_1 = require("../internal/pending-writes");
18
- const rows_1 = require("../internal/rows");
19
- /**
20
- * Stamps each `putWrites` call, identifying its rows as one group.
21
- *
22
- * It is what a guard rejection is compared against to tell "another call holds
23
- * this row" from "my own retry does", it is the object id every offloaded write
24
- * of the call is uploaded under, and — because ULIDs are lexicographically
25
- * time-ordered, and this factory is strictly monotonic even within a single
26
- * millisecond — it lets the read side identify the *earliest* call that wrote a
27
- * given channel (see `dropSupersededWrites`). A random UUID would identify a
28
- * call just as well but carries no ordering, which would leave that choice
29
- * arbitrary.
30
- */
31
- const nextWriteGroup = (0, ulid_1.createUlidFactory)();
11
+ import type { RunnableConfig } from '@langchain/core/runnables';
12
+ import type { PendingWrite } from '@langchain/langgraph-checkpoint';
13
+ import type { CheckpointerContext } from '../internal/setup.js';
32
14
  /**
33
15
  * Persist a task's intermediate writes for a checkpoint, one row per write.
34
16
  *
35
17
  * Accepts: `config` — must name a `checkpoint_id`, since writes always attach
36
18
  * to a checkpoint. `writes` — one task's, in order; their channels are
37
19
  * validated before anything is encoded or uploaded. `taskId` — validated as the
38
- * sort-key segment it becomes. `config.signal` — cancels the writes' retries;
39
- * checked before anything is encoded.
20
+ * sort-key segment it becomes. `taskPath` — the task's serialized path, which
21
+ * LangGraph 1.5 passes and earlier LangGraphs do not; stored beside every row
22
+ * of the call, to lead the order the writes are read back in. `config.signal`
23
+ * — cancels the writes' retries; checked before anything is encoded.
40
24
  *
41
25
  * Returns: nothing. Every write is attempted; a regular write that loses its
42
26
  * first-write-wins race is a normal outcome, not a failure.
@@ -44,8 +28,8 @@ const nextWriteGroup = (0, ulid_1.createUlidFactory)();
44
28
  * Throws: `VALIDATION` naming `config`, `configurable` or `signal` for a
45
29
  * config of the wrong shape; `thread_id`, `checkpoint_ns`, `checkpoint_id` or
46
30
  * `thread_ts` for a malformed identifier, and `checkpoint_id` when the config
47
- * names none; `taskId`, `writes`, `channel`, `sortKey` — every one of them
48
- * before anything is encoded or uploaded — `payload` or `s3Key`; the first
31
+ * names none; `taskId`, `taskPath`, `writes`, `channel`, `sortKey` — every one
32
+ * of them before anything is encoded or uploaded — `payload` or `s3Key`; the first
49
33
  * genuine write failure, after every write has settled and the cleanup has
50
34
  * run.
51
35
  *
@@ -62,15 +46,4 @@ const nextWriteGroup = (0, ulid_1.createUlidFactory)();
62
46
  * so no row another call writes names one of this call's uploads, and no
63
47
  * release reads the row again first.
64
48
  */
65
- async function putWrites(context, config, writes, taskId) {
66
- const request = (0, parse_1.parsePutWritesRequest)(config, writes, taskId);
67
- if (request.writes.length === 0)
68
- return;
69
- const ttlTimestamp = context.ttl ? (0, ttl_1.calculateTtlTimestamp)(context.ttl) : undefined;
70
- const items = await (0, rows_1.buildWriteRows)(context, request, nextWriteGroup(), ttlTimestamp);
71
- await (0, pending_writes_1.commitPendingWrites)(context, {
72
- threadId: request.address.threadId,
73
- items,
74
- signal: request.signal,
75
- });
76
- }
49
+ export declare function putWrites(context: CheckpointerContext, config: RunnableConfig, writes: PendingWrite[], taskId: string, taskPath?: string): Promise<void>;
@@ -0,0 +1,18 @@
1
+ import { createUlidFactory } from '../../shared/ulid.js';
2
+ import { calculateTtlTimestamp } from '../../shared/validation/ttl.js';
3
+ import { parsePutWritesRequest } from '../internal/parse.js';
4
+ import { commitPendingWrites } from '../internal/pending-writes.js';
5
+ import { buildWriteRows } from '../internal/rows.js';
6
+ const nextWriteGroup = createUlidFactory();
7
+ export async function putWrites(context, config, writes, taskId, taskPath) {
8
+ const request = parsePutWritesRequest(config, writes, taskId, taskPath);
9
+ if (request.writes.length === 0)
10
+ return;
11
+ const ttlTimestamp = context.ttl ? calculateTtlTimestamp(context.ttl) : undefined;
12
+ const items = await buildWriteRows(context, request, nextWriteGroup(), ttlTimestamp);
13
+ await commitPendingWrites(context, {
14
+ threadId: request.address.threadId,
15
+ items,
16
+ signal: request.signal,
17
+ });
18
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Hides what it takes for a checkpoint to land exactly once.
3
+ *
4
+ * The META and PAYLOAD rows go out as one transaction under a request token
5
+ * drawn once, and a failure with S3 offload configured is read back before
6
+ * any upload is released, so a lost acknowledgement reports success and only a
7
+ * confirmed non-commit cleans up (record 6). Every channel value is stored
8
+ * whatever `newVersions` says (record 10). A caller gets back the config that
9
+ * addresses the stored checkpoint and none of this.
10
+ */
11
+ import type { RunnableConfig } from '@langchain/core/runnables';
12
+ import type { Checkpoint, CheckpointMetadata } from '@langchain/langgraph-checkpoint';
13
+ import { type WriteVerdict } from '../../shared/dynamodb/idempotent-write.js';
14
+ import { type CheckpointMetaRow, type CheckpointPayloadRow } from '../internal/rows.js';
15
+ import type { CheckpointerContext } from '../internal/setup.js';
16
+ /**
17
+ * Persist a checkpoint and its metadata as a transactional pair of META and
18
+ * PAYLOAD rows, returning the config that addresses the stored checkpoint. The
19
+ * incoming `checkpoint_id` (if any) becomes the new checkpoint's parent.
20
+ *
21
+ * **Every channel value the checkpoint carries is stored.** The saver's
22
+ * `put` accepts a `newVersions` argument because `BaseCheckpointSaver.put`
23
+ * declares it (`@langchain/langgraph-checkpoint@1.1.5` `dist/base.d.ts:68`)
24
+ * and does not hand it on: narrowing the stored values to the ones it names, and
25
+ * carrying the rest forward from the parent, made a put whose `newVersions` is
26
+ * `{}` write no values at all. LangGraph passes `{}` when forking a checkpoint
27
+ * and when writing an empty-checkpoint update (`@langchain/langgraph@1.4.13`
28
+ * `dist/pregel/index.js:668` and `:613`), so that put silently dropped user
29
+ * state. The reference saver does not narrow either: `MemorySaver.put` takes
30
+ * three parameters and stores the whole checkpoint (`dist/memory.js:206`).
31
+ *
32
+ * Accepts: `config` — its `checkpoint_id`, when present, becomes the new
33
+ * checkpoint's parent. `checkpoint.id` — validated as the sort-key segment it
34
+ * becomes. `metadata` — stored beside it, on the light row a listing reads.
35
+ * `config.signal` — cancels the writes' retries; checked before anything is
36
+ * encoded.
37
+ *
38
+ * Returns: the config addressing the stored checkpoint, which is what the
39
+ * caller passes back to continue the thread.
40
+ *
41
+ * Throws: `VALIDATION` naming `config`, `configurable` or `signal` for a
42
+ * config of the wrong shape, `thread_id`, `checkpoint_ns`, `checkpoint_id` or
43
+ * `thread_ts` for a malformed identifier, `checkpoint` for a `null` or
44
+ * `undefined` checkpoint, `checkpoint_id` for a malformed `checkpoint.id`,
45
+ * `payload` for a payload too large to store inline without `s3`, or, once
46
+ * offloaded, larger than `s3.maxDownloadBytes`; `s3Key` for an offloaded
47
+ * object's key over S3's cap; `S3_OFFLOAD_FAILED`; whatever the transaction
48
+ * throws once the outcome is established.
49
+ *
50
+ * Guarantees: both rows land or neither does — they are one transaction, so a
51
+ * META row never names a payload that is not there. That transaction goes out
52
+ * under a client request token drawn once, with the request it travels on, so
53
+ * a retry that follows a lost acknowledgement is discarded by the service
54
+ * rather than applied a second time. Writing the same `checkpoint.id` again
55
+ * replaces both, which is what a retry and a repair tool both need; the objects
56
+ * the replaced rows named are not deleted by the put, and are left to the
57
+ * lifecycle rule. A payload the serde refuses is refused before any write and
58
+ * releases whatever the same call had already uploaded, so an encode that fails
59
+ * halfway leaves nothing behind either. On failure with S3 offload configured
60
+ * the row carrying an offloaded descriptor is read back before any upload is
61
+ * deleted (see {@link verifyCheckpointLanded}): a transaction that committed
62
+ * and lost its response is reported as success, a confirmed non-commit cleans
63
+ * up the objects this call uploaded, and an unverifiable outcome — a failed
64
+ * read, or a failure after which DynamoDB may still apply the write, because
65
+ * an attempt of its budget got no answer, was answered
66
+ * `TransactionInProgressException` or failed with a server error (5xx) —
67
+ * leaks them rather than risk stranding a live row, and a put
68
+ * whose signal fired before the transaction was sent sends nothing and
69
+ * releases its uploads. Each put uploads under an object id of its own, so no
70
+ * row another put commits names this call's uploads.
71
+ */
72
+ export declare function putCheckpoint(context: CheckpointerContext, config: RunnableConfig, checkpoint: Checkpoint, metadata: CheckpointMetadata): Promise<RunnableConfig>;
73
+ /**
74
+ * Read one of the two rows back after the META+PAYLOAD transaction failed and
75
+ * report what that failure actually did — never assuming it did nothing.
76
+ *
77
+ * Accepts: `meta` and `payload` — the two rows the failed transaction carried.
78
+ * Whichever of them has something offloaded is the one read back; a fully
79
+ * inline write has no object at stake and spends no read.
80
+ *
81
+ * Returns: the verdict. See {@link WriteVerdict} for what each answer licenses
82
+ * the caller to do. `'landed'` when the row holds this attempt's key,
83
+ * `'not-landed'` when it holds another or none, `'unverified'` when the read
84
+ * failed.
85
+ *
86
+ * Throws: nothing — a failed read is the `'unverified'` answer.
87
+ *
88
+ * Guarantees: both descriptors' keys end in the object id this put drew, which
89
+ * no other put uses. The row holds this attempt's key only if this put's
90
+ * transaction committed, and the other row commits with it, so one read decides
91
+ * the landing. A row holding any other key was committed by another put, whose
92
+ * rows name only that put's objects, so a `'not-landed'` answer leaves both of
93
+ * this put's uploads named by no row.
94
+ */
95
+ export declare function verifyCheckpointLanded(context: CheckpointerContext, meta: CheckpointMetaRow, payload: CheckpointPayloadRow): Promise<WriteVerdict>;
@@ -0,0 +1,75 @@
1
+ import { collectS3Keys } from '../../shared/codec/codec.js';
2
+ import { cleanUpS3Orphans } from '../../shared/codec/s3/offloader.js';
3
+ import { abortErrorFrom } from '../../shared/dynamodb/abort.js';
4
+ import { offloadedKey, settledVerdict, transactIdempotently, verifyRow, } from '../../shared/dynamodb/idempotent-write.js';
5
+ import { rowKeyOf } from '../../shared/dynamodb/table-schema.js';
6
+ import { calculateTtlTimestamp } from '../../shared/validation/ttl.js';
7
+ import { parsePutRequest } from '../internal/parse.js';
8
+ import { buildCheckpointRows, } from '../internal/rows.js';
9
+ export async function putCheckpoint(context, config, checkpoint, metadata) {
10
+ const request = parsePutRequest(config, checkpoint, metadata);
11
+ const { threadId, checkpointNs, checkpointId } = request.address;
12
+ const ttlTimestamp = context.ttl ? calculateTtlTimestamp(context.ttl) : undefined;
13
+ const { meta, payload } = await buildCheckpointRows(context, request, ttlTimestamp);
14
+ const stored = {
15
+ configurable: { thread_id: threadId, checkpoint_ns: checkpointNs, checkpoint_id: checkpointId },
16
+ };
17
+ if (request.signal?.aborted) {
18
+ await releaseOwnUploads(context, meta, payload);
19
+ throw abortErrorFrom(request.signal);
20
+ }
21
+ try {
22
+ await transactIdempotently(context, [
23
+ { Put: { TableName: context.tableName, Item: meta } },
24
+ { Put: { TableName: context.tableName, Item: payload } },
25
+ ], { signal: request.signal });
26
+ }
27
+ catch (error) {
28
+ if (!context.offloader)
29
+ throw error;
30
+ const verdict = settledVerdict(await verifyCheckpointLanded(context, meta, payload), error);
31
+ if (verdict === 'landed') {
32
+ context.logger.debug('put: transaction committed although its response was lost', {
33
+ threadId,
34
+ checkpointId,
35
+ });
36
+ return stored;
37
+ }
38
+ if (verdict === 'not-landed')
39
+ await releaseOwnUploads(context, meta, payload);
40
+ throw error;
41
+ }
42
+ return stored;
43
+ }
44
+ async function releaseOwnUploads(context, meta, payload) {
45
+ if (!context.offloader)
46
+ return;
47
+ await cleanUpS3Orphans(context.offloader, {
48
+ keys: collectS3Keys([meta.metadata, payload.checkpoint]),
49
+ operation: 'put',
50
+ logger: context.logger,
51
+ });
52
+ }
53
+ function chooseProbe(meta, payload) {
54
+ const metaKey = offloadedKey(meta.metadata);
55
+ if (metaKey !== undefined) {
56
+ return {
57
+ key: rowKeyOf(meta),
58
+ kind: 'descriptor',
59
+ attribute: 'metadata',
60
+ expected: metaKey,
61
+ descriptors: ['metadata'],
62
+ };
63
+ }
64
+ return {
65
+ key: rowKeyOf(payload),
66
+ kind: 'descriptor',
67
+ attribute: 'checkpoint',
68
+ expected: offloadedKey(payload.checkpoint),
69
+ descriptors: ['checkpoint'],
70
+ };
71
+ }
72
+ export async function verifyCheckpointLanded(context, meta, payload) {
73
+ const { verdict } = await verifyRow(context, chooseProbe(meta, payload));
74
+ return verdict;
75
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Hides how a delta channel's history is rebuilt, and what a hole in it means.
3
+ *
4
+ * A delta channel stores a full value only every `snapshotFrequency` updates,
5
+ * so its value at a checkpoint is its last snapshot plus the writes since,
6
+ * collected by walking parent pointers. The walk, the order the writes are
7
+ * collected in, and what a pointer the walk cannot follow means — a hole to
8
+ * report, whether its row is still stored past its ttl or already swept, and
9
+ * never the history's true start, which is a checkpoint with no pointer at all
10
+ * — are decided here.
11
+ */
12
+ import type { RunnableConfig } from '@langchain/core/runnables';
13
+ import type { CheckpointTuple, DeltaChannelHistory } from '@langchain/langgraph-checkpoint';
14
+ import { DynamoDBLangGraphError } from '../../shared/errors/base-error.js';
15
+ import type { CheckpointerContext } from './setup.js';
16
+ /**
17
+ * Walk a checkpoint's ancestors for the delta channels named, accumulating
18
+ * their writes oldest-first and the nearest stored value of each.
19
+ *
20
+ * Same contract and same result as the inherited implementation
21
+ * (`@langchain/langgraph-checkpoint@1.1.5` `dist/base.js:78`), with one
22
+ * difference that is the reason for overriding it: where the inherited walk
23
+ * meets an ancestor it cannot read it simply stops (`if (tup === void 0)
24
+ * break`), reports no seed, and the consumer rebuilds the channel from its
25
+ * initial value (`@langchain/langgraph@1.4.13` `dist/channels/delta.js:65`).
26
+ * That is silent state loss, and this package can produce it: a ttl is computed
27
+ * per put, so a long-running thread expires its own older checkpoints while the
28
+ * newer ones live on.
29
+ *
30
+ * Accepts: `channels` — the delta channels to rebuild; none returns nothing and
31
+ * reads nothing. `getTuple` — the saver's own, so the walk sees exactly what a
32
+ * reader would. `config` — the checkpoint to walk back from. `config.signal` —
33
+ * cancels the whole walk: it is re-attached to each ancestor cursor
34
+ * ({@link cursorFor}), because the pointer a tuple carries is a bare address.
35
+ *
36
+ * Returns: per channel, its on-path writes oldest-first and the nearest stored
37
+ * value found. A channel whose value was never stored gets none, which is the
38
+ * consumer's cue to start from its initial value — correctly, because there is
39
+ * nothing to lose.
40
+ *
41
+ * Throws: `ANCESTOR_EXPIRED` when a channel still needs an ancestor the walk
42
+ * cannot read — its row stored but past its ttl, or already removed by the
43
+ * sweep — or when the chain points back to a checkpoint already read
44
+ * ({@link ancestorExpired}). A checkpoint with no parent pointer ends the walk
45
+ * quietly — that is a thread's true start. `ABORTED` when the signal fires,
46
+ * at whichever hop it fires on, and in preference to a diagnosis of the stop:
47
+ * a walk cancelled just as it reached an expired ancestor reports the cancel,
48
+ * since the caller stopped waiting for the answer either way.
49
+ *
50
+ * Guarantees: the walk stops at the first ancestor that answers for every
51
+ * channel, so a deep thread costs reads only as far back as the nearest
52
+ * snapshot.
53
+ */
54
+ export declare function deltaChannelHistory(context: CheckpointerContext, getTuple: (config: RunnableConfig) => Promise<CheckpointTuple | undefined>, config: RunnableConfig, channels: string[]): Promise<Record<string, DeltaChannelHistory>>;
55
+ /** Where an ancestor walk stopped, and what kind of hole in the thread it found there. */
56
+ export interface WalkStop {
57
+ threadId: string;
58
+ checkpointId: string;
59
+ /**
60
+ * `'expired'` — the row is still stored, past its `ttl`; `'gone'` — no row at
61
+ * all, the sweep having removed it (or something else having deleted it);
62
+ * `'revisited'` — the chain pointed back to a checkpoint already read.
63
+ */
64
+ stop: 'expired' | 'gone' | 'revisited';
65
+ }
66
+ /**
67
+ * Read the META row an ancestor walk could not follow, **ignoring expiry**, to
68
+ * tell "this checkpoint is still stored but has expired" apart from "it is
69
+ * gone" — the sweep has removed it, which every expired row becomes within
70
+ * days. Both are holes; the read decides only what the error says.
71
+ *
72
+ * Every other read in this package hides an expired row, which is the right
73
+ * rule for a reader asking for state: checkpoint META, store and history rows
74
+ * by their own ttl, and a checkpoint's PAYLOAD and pending-WRITE rows by their
75
+ * checkpoint's META row, which is the only one checked (a pre-v4 checkpoint's
76
+ * migration is the exception: it reads its parent's pending writes under the
77
+ * child's META row). Here the row is wanted expired or not.
78
+ *
79
+ * Accepts: `config` — the parent pointer a walk stopped at. `config.signal` —
80
+ * cancels the read, and is read before it is sent. The walk re-attaches the
81
+ * caller's signal to every cursor, so the probe takes its cancel from the same
82
+ * place every other reader in this package takes it, rather than from a
83
+ * parameter of its own.
84
+ *
85
+ * Returns: whether that checkpoint is still stored and expired, or gone, or
86
+ * `undefined` when the config names no thread or no checkpoint — such a pointer
87
+ * addresses nothing that could have expired, so the walk has simply run out of
88
+ * chain.
89
+ *
90
+ * Throws: whatever the read throws after retries; `ABORTED` when the signal
91
+ * has already fired, which is answered in preference to the expiry this read
92
+ * exists to diagnose — a caller who cancelled is owed its own stop, and is no
93
+ * longer waiting to be told why the walk ended.
94
+ *
95
+ * Guarantees: the read ignores the ttl, deliberately. Every other read in this
96
+ * package hides an expired row by the rule above — META, store and history rows
97
+ * by their own ttl, PAYLOAD and WRITE rows by their checkpoint's META row, with
98
+ * the pre-v4 migration the exception — which is right for a reader asking for
99
+ * state; here an expired row is the evidence the error names.
100
+ */
101
+ export declare function probeAncestor(context: CheckpointerContext, config: RunnableConfig): Promise<WalkStop | undefined>;
102
+ /**
103
+ * The error a read raises when a delta channel's history has a hole in it.
104
+ *
105
+ * Accepts: `stop` — the ancestor the walk could not follow, and why. `channels`
106
+ * — the delta channels that still needed it, named in the message so the
107
+ * operator knows what was lost.
108
+ *
109
+ * Returns: the error, coded `ANCESTOR_EXPIRED` and carrying the thread and
110
+ * checkpoint. The message bounds all three: after the first hop the walk's
111
+ * cursor is a row's own `parentConfig`, so the identifiers it names come off a
112
+ * row, and `channels` is checked for being an array of strings and for nothing
113
+ * else — neither how many nor how long. `context` carries both identifiers
114
+ * whole, which is what a caller branches on.
115
+ *
116
+ * Throws: nothing — it builds the error, the caller throws it.
117
+ *
118
+ * Guarantees: returning the partial history instead would hand the caller a
119
+ * channel rebuilt from its initial value plus whatever writes survived — a
120
+ * shorter message list, say, with nothing to say that anything is missing. The
121
+ * reference contract has no way to express "incomplete", so refusing the read
122
+ * is the only honest answer.
123
+ */
124
+ export declare function ancestorExpired(stop: WalkStop, channels: string[]): DynamoDBLangGraphError;
@@ -0,0 +1,126 @@
1
+ import { nowSeconds } from '../../shared/clock.js';
2
+ import { withDynamoDBRetry, retryFor } from '../../shared/dynamodb/retry.js';
3
+ import { isExpiredRow } from '../../shared/dynamodb/table-schema.js';
4
+ import { DynamoDBLangGraphError } from '../../shared/errors/base-error.js';
5
+ import { ErrorCode } from '../../shared/errors/error-code.js';
6
+ import { truncateForLog, truncateLabelsForLog } from '../../shared/logging/truncate.js';
7
+ import { metaRowKey } from './rows.js';
8
+ function startWalk(channels) {
9
+ const writes = {};
10
+ for (const channel of channels)
11
+ writes[channel] = [];
12
+ return { remaining: new Set(channels), writes, seeds: {}, visited: new Set() };
13
+ }
14
+ function collectWrites(tuple, walk) {
15
+ const perChannel = {};
16
+ for (const write of tuple.pendingWrites ?? []) {
17
+ const channel = write[1];
18
+ if (walk.remaining.has(channel))
19
+ (perChannel[channel] ??= []).push(write);
20
+ }
21
+ for (const channel of Object.keys(perChannel)) {
22
+ const block = perChannel[channel];
23
+ for (let i = block.length - 1; i >= 0; i -= 1)
24
+ walk.writes[channel].push(block[i]);
25
+ }
26
+ }
27
+ function takeSeeds(tuple, walk) {
28
+ for (const channel of [...walk.remaining]) {
29
+ if (Object.prototype.hasOwnProperty.call(tuple.checkpoint.channel_values, channel)) {
30
+ walk.seeds[channel] = tuple.checkpoint.channel_values[channel];
31
+ walk.remaining.delete(channel);
32
+ }
33
+ }
34
+ }
35
+ function cursorFor(parent, signal) {
36
+ if (parent === undefined || signal === undefined)
37
+ return parent;
38
+ return { ...parent, signal };
39
+ }
40
+ async function walkAncestors(context, getTuple, walk, from) {
41
+ let cursor = cursorFor(from.start, from.signal);
42
+ while (cursor !== undefined && walk.remaining.size > 0) {
43
+ const revisit = revisitOf(cursor, walk);
44
+ if (revisit !== undefined)
45
+ throw ancestorExpired(revisit, [...walk.remaining]);
46
+ const tuple = await getTuple(cursor);
47
+ if (tuple === undefined) {
48
+ const stop = await probeAncestor(context, cursor);
49
+ if (stop === undefined)
50
+ return;
51
+ throw ancestorExpired(stop, [...walk.remaining]);
52
+ }
53
+ collectWrites(tuple, walk);
54
+ takeSeeds(tuple, walk);
55
+ cursor = cursorFor(tuple.parentConfig, from.signal);
56
+ }
57
+ }
58
+ function revisitOf(cursor, walk) {
59
+ const ids = cursor.configurable;
60
+ const threadId = ids?.thread_id;
61
+ const checkpointId = ids?.checkpoint_id;
62
+ if (typeof threadId !== 'string' || typeof checkpointId !== 'string')
63
+ return undefined;
64
+ const key = `${ids?.checkpoint_ns ?? ''}#${checkpointId}`;
65
+ if (walk.visited.has(key))
66
+ return { threadId, checkpointId, stop: 'revisited' };
67
+ walk.visited.add(key);
68
+ return undefined;
69
+ }
70
+ function historyOf(walk, channel) {
71
+ const writes = walk.writes[channel].slice().reverse();
72
+ return Object.prototype.hasOwnProperty.call(walk.seeds, channel)
73
+ ? { writes, seed: walk.seeds[channel] }
74
+ : { writes };
75
+ }
76
+ export async function deltaChannelHistory(context, getTuple, config, channels) {
77
+ if (channels.length === 0)
78
+ return {};
79
+ const walk = startWalk(channels);
80
+ const target = await getTuple(config);
81
+ await walkAncestors(context, getTuple, walk, {
82
+ start: target?.parentConfig,
83
+ signal: config.signal,
84
+ });
85
+ const result = {};
86
+ for (const channel of channels)
87
+ result[channel] = historyOf(walk, channel);
88
+ return result;
89
+ }
90
+ export async function probeAncestor(context, config) {
91
+ const ids = config.configurable;
92
+ const threadId = ids?.thread_id;
93
+ const checkpointId = ids?.checkpoint_id;
94
+ if (typeof threadId !== 'string' || typeof checkpointId !== 'string')
95
+ return undefined;
96
+ const checkpointNs = ids?.checkpoint_ns ?? '';
97
+ const result = await withDynamoDBRetry((request) => context.client.get({
98
+ TableName: context.tableName,
99
+ Key: metaRowKey({ threadId, checkpointNs, checkpointId }),
100
+ ConsistentRead: true,
101
+ }, request), retryFor(context, config.signal));
102
+ const row = result.Item;
103
+ return {
104
+ threadId,
105
+ checkpointId,
106
+ stop: row !== undefined && isExpiredRow(row, nowSeconds()) ? 'expired' : 'gone',
107
+ };
108
+ }
109
+ export function ancestorExpired(stop, channels) {
110
+ const named = truncateLabelsForLog(channels)
111
+ .map((channel) => `"${channel}"`)
112
+ .join(', ');
113
+ const what = stop.stop === 'expired'
114
+ ? 'has expired'
115
+ : stop.stop === 'gone'
116
+ ? 'is gone (expired and removed by DynamoDB, or deleted)'
117
+ : 'is named as its own ancestor, so the chain never reaches a stored value';
118
+ return new DynamoDBLangGraphError(`checkpoint "${truncateForLog(stop.checkpointId)}" of thread ` +
119
+ `"${truncateForLog(stop.threadId)}" ${what}, but later ` +
120
+ `checkpoints still need it to reconstruct ${named}. ` +
121
+ 'A delta channel writes a full snapshot only every `snapshotFrequency` updates and leaves ' +
122
+ 'itself out of the checkpoints in between, so its value is rebuilt from an earlier ' +
123
+ 'ancestor — which a per-checkpoint ttl expires while its descendants live on. Lower ' +
124
+ '`snapshotFrequency` (1 makes every checkpoint self-contained), or do not configure a ttl ' +
125
+ 'on threads that use delta channels.', ErrorCode.ANCESTOR_EXPIRED, { threadId: stop.threadId, checkpointId: stop.checkpointId });
126
+ }