@farukada/aws-langgraph-dynamodb-ts 0.2.2 → 0.3.1

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 (517) hide show
  1. package/README.md +224 -512
  2. package/dist/checkpointer/actions/delete-thread.d.ts +7 -6
  3. package/dist/checkpointer/actions/delete-thread.d.ts.map +1 -1
  4. package/dist/checkpointer/actions/delete-thread.js +47 -152
  5. package/dist/checkpointer/actions/delete-thread.js.map +1 -1
  6. package/dist/checkpointer/actions/get-tuple.d.ts +6 -14
  7. package/dist/checkpointer/actions/get-tuple.d.ts.map +1 -1
  8. package/dist/checkpointer/actions/get-tuple.js +13 -166
  9. package/dist/checkpointer/actions/get-tuple.js.map +1 -1
  10. package/dist/checkpointer/actions/list.d.ts +10 -0
  11. package/dist/checkpointer/actions/list.d.ts.map +1 -0
  12. package/dist/checkpointer/actions/list.js +51 -0
  13. package/dist/checkpointer/actions/list.js.map +1 -0
  14. package/dist/checkpointer/actions/put-writes.d.ts +6 -6
  15. package/dist/checkpointer/actions/put-writes.d.ts.map +1 -1
  16. package/dist/checkpointer/actions/put-writes.js +26 -75
  17. package/dist/checkpointer/actions/put-writes.js.map +1 -1
  18. package/dist/checkpointer/actions/put.d.ts +6 -11
  19. package/dist/checkpointer/actions/put.d.ts.map +1 -1
  20. package/dist/checkpointer/actions/put.js +29 -161
  21. package/dist/checkpointer/actions/put.js.map +1 -1
  22. package/dist/checkpointer/internal/assemble.d.ts +10 -0
  23. package/dist/checkpointer/internal/assemble.d.ts.map +1 -0
  24. package/dist/checkpointer/internal/assemble.js +37 -0
  25. package/dist/checkpointer/internal/assemble.js.map +1 -0
  26. package/dist/checkpointer/internal/configurable.d.ts +13 -0
  27. package/dist/checkpointer/internal/configurable.d.ts.map +1 -0
  28. package/dist/checkpointer/internal/configurable.js +23 -0
  29. package/dist/checkpointer/internal/configurable.js.map +1 -0
  30. package/dist/checkpointer/internal/fetch.d.ts +10 -0
  31. package/dist/checkpointer/internal/fetch.d.ts.map +1 -0
  32. package/dist/checkpointer/internal/fetch.js +46 -0
  33. package/dist/checkpointer/internal/fetch.js.map +1 -0
  34. package/dist/checkpointer/internal/filter-match.d.ts +12 -0
  35. package/dist/checkpointer/internal/filter-match.d.ts.map +1 -0
  36. package/dist/checkpointer/internal/filter-match.js +14 -0
  37. package/dist/checkpointer/internal/filter-match.js.map +1 -0
  38. package/dist/checkpointer/internal/item-reader.d.ts +10 -0
  39. package/dist/checkpointer/internal/item-reader.d.ts.map +1 -0
  40. package/dist/checkpointer/internal/item-reader.js +26 -0
  41. package/dist/checkpointer/internal/item-reader.js.map +1 -0
  42. package/dist/checkpointer/internal/item-writer.d.ts +14 -0
  43. package/dist/checkpointer/internal/item-writer.d.ts.map +1 -0
  44. package/dist/checkpointer/internal/item-writer.js +68 -0
  45. package/dist/checkpointer/internal/item-writer.js.map +1 -0
  46. package/dist/checkpointer/internal/keys.d.ts +15 -0
  47. package/dist/checkpointer/internal/keys.d.ts.map +1 -0
  48. package/dist/checkpointer/internal/keys.js +52 -0
  49. package/dist/checkpointer/internal/keys.js.map +1 -0
  50. package/dist/checkpointer/internal/query.d.ts +16 -0
  51. package/dist/checkpointer/internal/query.d.ts.map +1 -0
  52. package/dist/checkpointer/internal/query.js +33 -0
  53. package/dist/checkpointer/internal/query.js.map +1 -0
  54. package/dist/checkpointer/internal/setup.d.ts +31 -0
  55. package/dist/checkpointer/internal/setup.d.ts.map +1 -0
  56. package/dist/checkpointer/internal/setup.js +29 -0
  57. package/dist/checkpointer/internal/setup.js.map +1 -0
  58. package/dist/checkpointer/internal/validation.d.ts +9 -0
  59. package/dist/checkpointer/internal/validation.d.ts.map +1 -0
  60. package/dist/checkpointer/internal/validation.js +28 -0
  61. package/dist/checkpointer/internal/validation.js.map +1 -0
  62. package/dist/checkpointer/saver.d.ts +21 -0
  63. package/dist/checkpointer/saver.d.ts.map +1 -0
  64. package/dist/checkpointer/saver.js +49 -0
  65. package/dist/checkpointer/saver.js.map +1 -0
  66. package/dist/checkpointer/types.d.ts +43 -0
  67. package/dist/checkpointer/types.d.ts.map +1 -0
  68. package/dist/{store/types/index.js → checkpointer/types.js} +1 -1
  69. package/dist/checkpointer/types.js.map +1 -0
  70. package/dist/factory/factory.d.ts +41 -0
  71. package/dist/factory/factory.d.ts.map +1 -0
  72. package/dist/factory/factory.js +49 -0
  73. package/dist/factory/factory.js.map +1 -0
  74. package/dist/history/actions/add-messages.d.ts +12 -7
  75. package/dist/history/actions/add-messages.d.ts.map +1 -1
  76. package/dist/history/actions/add-messages.js +50 -48
  77. package/dist/history/actions/add-messages.js.map +1 -1
  78. package/dist/history/actions/clear.d.ts +5 -11
  79. package/dist/history/actions/clear.d.ts.map +1 -1
  80. package/dist/history/actions/clear.js +28 -62
  81. package/dist/history/actions/clear.js.map +1 -1
  82. package/dist/history/actions/get-messages.d.ts +6 -13
  83. package/dist/history/actions/get-messages.d.ts.map +1 -1
  84. package/dist/history/actions/get-messages.js +23 -59
  85. package/dist/history/actions/get-messages.js.map +1 -1
  86. package/dist/history/actions/list-sessions.d.ts +6 -22
  87. package/dist/history/actions/list-sessions.d.ts.map +1 -1
  88. package/dist/history/actions/list-sessions.js +26 -69
  89. package/dist/history/actions/list-sessions.js.map +1 -1
  90. package/dist/history/actions/reconcile-count.d.ts +10 -0
  91. package/dist/history/actions/reconcile-count.d.ts.map +1 -0
  92. package/dist/history/actions/reconcile-count.js +39 -0
  93. package/dist/history/actions/reconcile-count.js.map +1 -0
  94. package/dist/history/chat-message-history.d.ts +36 -0
  95. package/dist/history/chat-message-history.d.ts.map +1 -0
  96. package/dist/history/chat-message-history.js +67 -0
  97. package/dist/history/chat-message-history.js.map +1 -0
  98. package/dist/history/internal/append-saga.d.ts +17 -0
  99. package/dist/history/internal/append-saga.d.ts.map +1 -0
  100. package/dist/history/internal/append-saga.js +94 -0
  101. package/dist/history/internal/append-saga.js.map +1 -0
  102. package/dist/history/internal/item-mapper.d.ts +12 -0
  103. package/dist/history/internal/item-mapper.d.ts.map +1 -0
  104. package/dist/history/internal/item-mapper.js +33 -0
  105. package/dist/history/internal/item-mapper.js.map +1 -0
  106. package/dist/history/internal/keys.d.ts +9 -0
  107. package/dist/history/internal/keys.d.ts.map +1 -0
  108. package/dist/history/internal/keys.js +22 -0
  109. package/dist/history/internal/keys.js.map +1 -0
  110. package/dist/history/internal/message-chunker.d.ts +14 -0
  111. package/dist/history/internal/message-chunker.d.ts.map +1 -0
  112. package/dist/history/internal/message-chunker.js +60 -0
  113. package/dist/history/internal/message-chunker.js.map +1 -0
  114. package/dist/history/internal/message-transaction.d.ts +17 -0
  115. package/dist/history/internal/message-transaction.d.ts.map +1 -0
  116. package/dist/history/internal/message-transaction.js +27 -0
  117. package/dist/history/internal/message-transaction.js.map +1 -0
  118. package/dist/history/internal/query.d.ts +6 -0
  119. package/dist/history/internal/query.d.ts.map +1 -0
  120. package/dist/history/internal/query.js +28 -0
  121. package/dist/history/internal/query.js.map +1 -0
  122. package/dist/history/internal/session-update.d.ts +20 -0
  123. package/dist/history/internal/session-update.d.ts.map +1 -0
  124. package/dist/history/internal/session-update.js +46 -0
  125. package/dist/history/internal/session-update.js.map +1 -0
  126. package/dist/history/internal/setup.d.ts +28 -0
  127. package/dist/history/internal/setup.d.ts.map +1 -0
  128. package/dist/history/internal/setup.js +27 -0
  129. package/dist/history/internal/setup.js.map +1 -0
  130. package/dist/history/internal/title-generator.d.ts +7 -0
  131. package/dist/history/internal/title-generator.d.ts.map +1 -0
  132. package/dist/history/internal/title-generator.js +16 -0
  133. package/dist/history/internal/title-generator.js.map +1 -0
  134. package/dist/history/internal/ttl-anchor.d.ts +12 -0
  135. package/dist/history/internal/ttl-anchor.d.ts.map +1 -0
  136. package/dist/history/internal/ttl-anchor.js +26 -0
  137. package/dist/history/internal/ttl-anchor.js.map +1 -0
  138. package/dist/history/session-adapter.d.ts +10 -26
  139. package/dist/history/session-adapter.d.ts.map +1 -1
  140. package/dist/history/session-adapter.js +15 -57
  141. package/dist/history/session-adapter.js.map +1 -1
  142. package/dist/history/types.d.ts +36 -0
  143. package/dist/history/types.d.ts.map +1 -0
  144. package/dist/history/types.js +3 -0
  145. package/dist/history/types.js.map +1 -0
  146. package/dist/index.d.ts +18 -10
  147. package/dist/index.d.ts.map +1 -1
  148. package/dist/index.js +24 -16
  149. package/dist/index.js.map +1 -1
  150. package/dist/shared/clock.d.ts +3 -0
  151. package/dist/shared/clock.d.ts.map +1 -0
  152. package/dist/shared/clock.js +8 -0
  153. package/dist/shared/clock.js.map +1 -0
  154. package/dist/shared/codec/codec.d.ts +44 -0
  155. package/dist/shared/codec/codec.d.ts.map +1 -0
  156. package/dist/shared/codec/codec.js +44 -0
  157. package/dist/shared/codec/codec.js.map +1 -0
  158. package/dist/shared/codec/compression.d.ts +25 -0
  159. package/dist/shared/codec/compression.d.ts.map +1 -0
  160. package/dist/shared/codec/compression.js +49 -0
  161. package/dist/shared/codec/compression.js.map +1 -0
  162. package/dist/shared/codec/descriptor-keys.d.ts +4 -0
  163. package/dist/shared/codec/descriptor-keys.d.ts.map +1 -0
  164. package/dist/shared/codec/descriptor-keys.js +14 -0
  165. package/dist/shared/codec/descriptor-keys.js.map +1 -0
  166. package/dist/shared/codec/json-serde.d.ts +8 -0
  167. package/dist/shared/codec/json-serde.d.ts.map +1 -0
  168. package/dist/shared/codec/json-serde.js +18 -0
  169. package/dist/shared/codec/json-serde.js.map +1 -0
  170. package/dist/shared/codec/s3/client.d.ts +6 -0
  171. package/dist/shared/codec/s3/client.d.ts.map +1 -0
  172. package/dist/shared/codec/s3/client.js +18 -0
  173. package/dist/shared/codec/s3/client.js.map +1 -0
  174. package/dist/shared/codec/s3/config.d.ts +16 -0
  175. package/dist/shared/codec/s3/config.d.ts.map +1 -0
  176. package/dist/shared/codec/s3/config.js +14 -0
  177. package/dist/shared/codec/s3/config.js.map +1 -0
  178. package/dist/shared/codec/s3/delete.d.ts +8 -0
  179. package/dist/shared/codec/s3/delete.d.ts.map +1 -0
  180. package/dist/shared/codec/s3/delete.js +29 -0
  181. package/dist/shared/codec/s3/delete.js.map +1 -0
  182. package/dist/shared/codec/s3/lifecycle.d.ts +8 -0
  183. package/dist/shared/codec/s3/lifecycle.d.ts.map +1 -0
  184. package/dist/shared/codec/s3/lifecycle.js +47 -0
  185. package/dist/shared/codec/s3/lifecycle.js.map +1 -0
  186. package/dist/shared/codec/s3/offloader.d.ts +33 -0
  187. package/dist/shared/codec/s3/offloader.d.ts.map +1 -0
  188. package/dist/shared/codec/s3/offloader.js +80 -0
  189. package/dist/shared/codec/s3/offloader.js.map +1 -0
  190. package/dist/shared/codec/s3/orphans.d.ts +16 -0
  191. package/dist/shared/codec/s3/orphans.d.ts.map +1 -0
  192. package/dist/shared/codec/s3/orphans.js +73 -0
  193. package/dist/shared/codec/s3/orphans.js.map +1 -0
  194. package/dist/shared/codec/s3/read-write.d.ts +14 -0
  195. package/dist/shared/codec/s3/read-write.d.ts.map +1 -0
  196. package/dist/shared/codec/s3/read-write.js +42 -0
  197. package/dist/shared/codec/s3/read-write.js.map +1 -0
  198. package/dist/shared/constants.d.ts +37 -0
  199. package/dist/shared/constants.d.ts.map +1 -0
  200. package/dist/shared/constants.js +40 -0
  201. package/dist/shared/constants.js.map +1 -0
  202. package/dist/shared/dynamodb/backoff.d.ts +15 -0
  203. package/dist/shared/dynamodb/backoff.d.ts.map +1 -0
  204. package/dist/shared/dynamodb/backoff.js +48 -0
  205. package/dist/shared/dynamodb/backoff.js.map +1 -0
  206. package/dist/shared/dynamodb/batch-write.d.ts +10 -0
  207. package/dist/shared/dynamodb/batch-write.d.ts.map +1 -0
  208. package/dist/shared/dynamodb/batch-write.js +17 -0
  209. package/dist/shared/dynamodb/batch-write.js.map +1 -0
  210. package/dist/shared/dynamodb/client.d.ts +21 -0
  211. package/dist/shared/dynamodb/client.d.ts.map +1 -0
  212. package/dist/shared/dynamodb/client.js +19 -0
  213. package/dist/shared/dynamodb/client.js.map +1 -0
  214. package/dist/shared/dynamodb/drain-unprocessed.d.ts +15 -0
  215. package/dist/shared/dynamodb/drain-unprocessed.d.ts.map +1 -0
  216. package/dist/shared/dynamodb/drain-unprocessed.js +35 -0
  217. package/dist/shared/dynamodb/drain-unprocessed.js.map +1 -0
  218. package/dist/shared/dynamodb/paginate-core.d.ts +22 -0
  219. package/dist/shared/dynamodb/paginate-core.d.ts.map +1 -0
  220. package/dist/shared/dynamodb/paginate-core.js +52 -0
  221. package/dist/shared/dynamodb/paginate-core.js.map +1 -0
  222. package/dist/shared/dynamodb/paginate.d.ts +15 -0
  223. package/dist/shared/dynamodb/paginate.d.ts.map +1 -0
  224. package/dist/shared/dynamodb/paginate.js +20 -0
  225. package/dist/shared/dynamodb/paginate.js.map +1 -0
  226. package/dist/shared/dynamodb/retry-classifier.d.ts +9 -0
  227. package/dist/shared/dynamodb/retry-classifier.d.ts.map +1 -0
  228. package/dist/shared/dynamodb/retry-classifier.js +75 -0
  229. package/dist/shared/dynamodb/retry-classifier.js.map +1 -0
  230. package/dist/shared/dynamodb/retry.d.ts +18 -0
  231. package/dist/shared/dynamodb/retry.d.ts.map +1 -0
  232. package/dist/shared/dynamodb/retry.js +53 -0
  233. package/dist/shared/dynamodb/retry.js.map +1 -0
  234. package/dist/shared/dynamodb/scan.d.ts +15 -0
  235. package/dist/shared/dynamodb/scan.d.ts.map +1 -0
  236. package/dist/shared/dynamodb/scan.js +20 -0
  237. package/dist/shared/dynamodb/scan.js.map +1 -0
  238. package/dist/shared/dynamodb/types.d.ts +24 -0
  239. package/dist/shared/dynamodb/types.d.ts.map +1 -0
  240. package/dist/shared/dynamodb/types.js +3 -0
  241. package/dist/shared/dynamodb/types.js.map +1 -0
  242. package/dist/shared/errors/base-error.d.ts +22 -0
  243. package/dist/shared/errors/base-error.d.ts.map +1 -0
  244. package/dist/shared/errors/base-error.js +28 -0
  245. package/dist/shared/errors/base-error.js.map +1 -0
  246. package/dist/shared/errors/error-code.d.ts +13 -0
  247. package/dist/shared/errors/error-code.d.ts.map +1 -0
  248. package/dist/shared/errors/error-code.js +17 -0
  249. package/dist/shared/errors/error-code.js.map +1 -0
  250. package/dist/shared/errors/errors.d.ts +47 -0
  251. package/dist/shared/errors/errors.d.ts.map +1 -0
  252. package/dist/shared/errors/errors.js +82 -0
  253. package/dist/shared/errors/errors.js.map +1 -0
  254. package/dist/shared/errors/wrap-error.d.ts +16 -0
  255. package/dist/shared/errors/wrap-error.d.ts.map +1 -0
  256. package/dist/shared/errors/wrap-error.js +30 -0
  257. package/dist/shared/errors/wrap-error.js.map +1 -0
  258. package/dist/shared/logging/logger.d.ts +14 -0
  259. package/dist/shared/logging/logger.d.ts.map +1 -0
  260. package/dist/shared/logging/logger.js +16 -0
  261. package/dist/shared/logging/logger.js.map +1 -0
  262. package/dist/shared/logging/redaction.d.ts +19 -0
  263. package/dist/shared/logging/redaction.d.ts.map +1 -0
  264. package/dist/shared/logging/redaction.js +67 -0
  265. package/dist/shared/logging/redaction.js.map +1 -0
  266. package/dist/shared/options.d.ts +32 -0
  267. package/dist/shared/options.d.ts.map +1 -0
  268. package/dist/shared/options.js +3 -0
  269. package/dist/shared/options.js.map +1 -0
  270. package/dist/shared/ulid.d.ts +10 -0
  271. package/dist/shared/ulid.d.ts.map +1 -0
  272. package/dist/shared/ulid.js +65 -0
  273. package/dist/shared/ulid.js.map +1 -0
  274. package/dist/shared/validation/primitives.d.ts +17 -0
  275. package/dist/shared/validation/primitives.d.ts.map +1 -0
  276. package/dist/shared/validation/primitives.js +71 -0
  277. package/dist/shared/validation/primitives.js.map +1 -0
  278. package/dist/shared/validation/ttl.d.ts +16 -0
  279. package/dist/shared/validation/ttl.d.ts.map +1 -0
  280. package/dist/shared/validation/ttl.js +26 -0
  281. package/dist/shared/validation/ttl.js.map +1 -0
  282. package/dist/store/actions/get.d.ts +5 -0
  283. package/dist/store/actions/get.d.ts.map +1 -0
  284. package/dist/store/actions/get.js +21 -0
  285. package/dist/store/actions/get.js.map +1 -0
  286. package/dist/store/actions/list-namespaces.d.ts +9 -0
  287. package/dist/store/actions/list-namespaces.d.ts.map +1 -0
  288. package/dist/store/actions/list-namespaces.js +46 -0
  289. package/dist/store/actions/list-namespaces.js.map +1 -0
  290. package/dist/store/actions/put.d.ts +11 -0
  291. package/dist/store/actions/put.d.ts.map +1 -0
  292. package/dist/store/actions/put.js +81 -0
  293. package/dist/store/actions/put.js.map +1 -0
  294. package/dist/store/actions/reconcile-vector-index.d.ts +17 -0
  295. package/dist/store/actions/reconcile-vector-index.d.ts.map +1 -0
  296. package/dist/store/actions/reconcile-vector-index.js +27 -0
  297. package/dist/store/actions/reconcile-vector-index.js.map +1 -0
  298. package/dist/store/actions/search.d.ts +10 -0
  299. package/dist/store/actions/search.d.ts.map +1 -0
  300. package/dist/store/actions/search.js +72 -0
  301. package/dist/store/actions/search.js.map +1 -0
  302. package/dist/store/internal/filter.d.ts +10 -0
  303. package/dist/store/internal/filter.d.ts.map +1 -0
  304. package/dist/store/internal/filter.js +37 -0
  305. package/dist/store/internal/filter.js.map +1 -0
  306. package/dist/store/internal/index-reconcile.d.ts +22 -0
  307. package/dist/store/internal/index-reconcile.d.ts.map +1 -0
  308. package/dist/store/internal/index-reconcile.js +68 -0
  309. package/dist/store/internal/index-reconcile.js.map +1 -0
  310. package/dist/store/internal/index-sync.d.ts +11 -0
  311. package/dist/store/internal/index-sync.d.ts.map +1 -0
  312. package/dist/store/internal/index-sync.js +26 -0
  313. package/dist/store/internal/index-sync.js.map +1 -0
  314. package/dist/store/internal/item-mapper.d.ts +23 -0
  315. package/dist/store/internal/item-mapper.d.ts.map +1 -0
  316. package/dist/store/internal/item-mapper.js +51 -0
  317. package/dist/store/internal/item-mapper.js.map +1 -0
  318. package/dist/store/internal/keys.d.ts +18 -0
  319. package/dist/store/internal/keys.d.ts.map +1 -0
  320. package/dist/store/internal/keys.js +36 -0
  321. package/dist/store/internal/keys.js.map +1 -0
  322. package/dist/store/internal/namespace-match.d.ts +12 -0
  323. package/dist/store/internal/namespace-match.d.ts.map +1 -0
  324. package/dist/store/internal/namespace-match.js +41 -0
  325. package/dist/store/internal/namespace-match.js.map +1 -0
  326. package/dist/store/internal/query.d.ts +6 -0
  327. package/dist/store/internal/query.d.ts.map +1 -0
  328. package/dist/store/internal/query.js +32 -0
  329. package/dist/store/internal/query.js.map +1 -0
  330. package/dist/store/internal/ranker.d.ts +13 -0
  331. package/dist/store/internal/ranker.d.ts.map +1 -0
  332. package/dist/store/internal/ranker.js +29 -0
  333. package/dist/store/internal/ranker.js.map +1 -0
  334. package/dist/store/internal/semantic-search.d.ts +13 -0
  335. package/dist/store/internal/semantic-search.d.ts.map +1 -0
  336. package/dist/store/internal/semantic-search.js +47 -0
  337. package/dist/store/internal/semantic-search.js.map +1 -0
  338. package/dist/store/internal/setup.d.ts +31 -0
  339. package/dist/store/internal/setup.d.ts.map +1 -0
  340. package/dist/store/internal/setup.js +29 -0
  341. package/dist/store/internal/setup.js.map +1 -0
  342. package/dist/store/internal/validation.d.ts +7 -0
  343. package/dist/store/internal/validation.d.ts.map +1 -0
  344. package/dist/store/internal/validation.js +26 -0
  345. package/dist/store/internal/validation.js.map +1 -0
  346. package/dist/store/store.d.ts +24 -0
  347. package/dist/store/store.d.ts.map +1 -0
  348. package/dist/store/store.js +58 -0
  349. package/dist/store/store.js.map +1 -0
  350. package/dist/store/types.d.ts +28 -0
  351. package/dist/store/types.d.ts.map +1 -0
  352. package/dist/store/types.js +3 -0
  353. package/dist/store/types.js.map +1 -0
  354. package/dist/store/vector-backend.d.ts +27 -0
  355. package/dist/store/vector-backend.d.ts.map +1 -0
  356. package/dist/store/vector-backend.js +3 -0
  357. package/dist/store/vector-backend.js.map +1 -0
  358. package/package.json +21 -22
  359. package/dist/checkpointer/actions/index.d.ts +0 -5
  360. package/dist/checkpointer/actions/index.d.ts.map +0 -1
  361. package/dist/checkpointer/actions/index.js +0 -21
  362. package/dist/checkpointer/actions/index.js.map +0 -1
  363. package/dist/checkpointer/actions/validate-configurable.d.ts +0 -10
  364. package/dist/checkpointer/actions/validate-configurable.d.ts.map +0 -1
  365. package/dist/checkpointer/actions/validate-configurable.js +0 -39
  366. package/dist/checkpointer/actions/validate-configurable.js.map +0 -1
  367. package/dist/checkpointer/actions/writer.d.ts +0 -52
  368. package/dist/checkpointer/actions/writer.d.ts.map +0 -1
  369. package/dist/checkpointer/actions/writer.js +0 -109
  370. package/dist/checkpointer/actions/writer.js.map +0 -1
  371. package/dist/checkpointer/index.d.ts +0 -118
  372. package/dist/checkpointer/index.d.ts.map +0 -1
  373. package/dist/checkpointer/index.js +0 -393
  374. package/dist/checkpointer/index.js.map +0 -1
  375. package/dist/checkpointer/types/index.d.ts +0 -232
  376. package/dist/checkpointer/types/index.d.ts.map +0 -1
  377. package/dist/checkpointer/types/index.js +0 -13
  378. package/dist/checkpointer/types/index.js.map +0 -1
  379. package/dist/checkpointer/utils/deserialization.d.ts +0 -20
  380. package/dist/checkpointer/utils/deserialization.d.ts.map +0 -1
  381. package/dist/checkpointer/utils/deserialization.js +0 -81
  382. package/dist/checkpointer/utils/deserialization.js.map +0 -1
  383. package/dist/checkpointer/utils/index.d.ts +0 -7
  384. package/dist/checkpointer/utils/index.d.ts.map +0 -1
  385. package/dist/checkpointer/utils/index.js +0 -27
  386. package/dist/checkpointer/utils/index.js.map +0 -1
  387. package/dist/checkpointer/utils/validation.d.ts +0 -48
  388. package/dist/checkpointer/utils/validation.d.ts.map +0 -1
  389. package/dist/checkpointer/utils/validation.js +0 -235
  390. package/dist/checkpointer/utils/validation.js.map +0 -1
  391. package/dist/factory.d.ts +0 -153
  392. package/dist/factory.d.ts.map +0 -1
  393. package/dist/factory.js +0 -206
  394. package/dist/factory.js.map +0 -1
  395. package/dist/history/actions/add-message.d.ts +0 -10
  396. package/dist/history/actions/add-message.d.ts.map +0 -1
  397. package/dist/history/actions/add-message.js +0 -24
  398. package/dist/history/actions/add-message.js.map +0 -1
  399. package/dist/history/actions/index.d.ts +0 -9
  400. package/dist/history/actions/index.d.ts.map +0 -1
  401. package/dist/history/actions/index.js +0 -17
  402. package/dist/history/actions/index.js.map +0 -1
  403. package/dist/history/index.d.ts +0 -118
  404. package/dist/history/index.d.ts.map +0 -1
  405. package/dist/history/index.js +0 -179
  406. package/dist/history/index.js.map +0 -1
  407. package/dist/history/types/index.d.ts +0 -184
  408. package/dist/history/types/index.d.ts.map +0 -1
  409. package/dist/history/types/index.js +0 -7
  410. package/dist/history/types/index.js.map +0 -1
  411. package/dist/history/utils/index.d.ts +0 -9
  412. package/dist/history/utils/index.d.ts.map +0 -1
  413. package/dist/history/utils/index.js +0 -27
  414. package/dist/history/utils/index.js.map +0 -1
  415. package/dist/history/utils/optimistic-retry.d.ts +0 -31
  416. package/dist/history/utils/optimistic-retry.d.ts.map +0 -1
  417. package/dist/history/utils/optimistic-retry.js +0 -74
  418. package/dist/history/utils/optimistic-retry.js.map +0 -1
  419. package/dist/history/utils/title-generator.d.ts +0 -12
  420. package/dist/history/utils/title-generator.d.ts.map +0 -1
  421. package/dist/history/utils/title-generator.js +0 -57
  422. package/dist/history/utils/title-generator.js.map +0 -1
  423. package/dist/history/utils/update-expression-builder.d.ts +0 -55
  424. package/dist/history/utils/update-expression-builder.d.ts.map +0 -1
  425. package/dist/history/utils/update-expression-builder.js +0 -112
  426. package/dist/history/utils/update-expression-builder.js.map +0 -1
  427. package/dist/history/utils/validation.d.ts +0 -68
  428. package/dist/history/utils/validation.d.ts.map +0 -1
  429. package/dist/history/utils/validation.js +0 -213
  430. package/dist/history/utils/validation.js.map +0 -1
  431. package/dist/shared/index.d.ts +0 -5
  432. package/dist/shared/index.d.ts.map +0 -1
  433. package/dist/shared/index.js +0 -21
  434. package/dist/shared/index.js.map +0 -1
  435. package/dist/shared/utils/batch-write.d.ts +0 -74
  436. package/dist/shared/utils/batch-write.d.ts.map +0 -1
  437. package/dist/shared/utils/batch-write.js +0 -110
  438. package/dist/shared/utils/batch-write.js.map +0 -1
  439. package/dist/shared/utils/client-factory.d.ts +0 -25
  440. package/dist/shared/utils/client-factory.d.ts.map +0 -1
  441. package/dist/shared/utils/client-factory.js +0 -23
  442. package/dist/shared/utils/client-factory.js.map +0 -1
  443. package/dist/shared/utils/compressor.d.ts +0 -66
  444. package/dist/shared/utils/compressor.d.ts.map +0 -1
  445. package/dist/shared/utils/compressor.js +0 -133
  446. package/dist/shared/utils/compressor.js.map +0 -1
  447. package/dist/shared/utils/constants.d.ts +0 -13
  448. package/dist/shared/utils/constants.d.ts.map +0 -1
  449. package/dist/shared/utils/constants.js +0 -35
  450. package/dist/shared/utils/constants.js.map +0 -1
  451. package/dist/shared/utils/index.d.ts +0 -14
  452. package/dist/shared/utils/index.d.ts.map +0 -1
  453. package/dist/shared/utils/index.js +0 -30
  454. package/dist/shared/utils/index.js.map +0 -1
  455. package/dist/shared/utils/logger.d.ts +0 -75
  456. package/dist/shared/utils/logger.d.ts.map +0 -1
  457. package/dist/shared/utils/logger.js +0 -148
  458. package/dist/shared/utils/logger.js.map +0 -1
  459. package/dist/shared/utils/retry.d.ts +0 -26
  460. package/dist/shared/utils/retry.d.ts.map +0 -1
  461. package/dist/shared/utils/retry.js +0 -169
  462. package/dist/shared/utils/retry.js.map +0 -1
  463. package/dist/shared/utils/s3-offloader.d.ts +0 -153
  464. package/dist/shared/utils/s3-offloader.d.ts.map +0 -1
  465. package/dist/shared/utils/s3-offloader.js +0 -281
  466. package/dist/shared/utils/s3-offloader.js.map +0 -1
  467. package/dist/shared/utils/s3-orphans.d.ts +0 -16
  468. package/dist/shared/utils/s3-orphans.d.ts.map +0 -1
  469. package/dist/shared/utils/s3-orphans.js +0 -79
  470. package/dist/shared/utils/s3-orphans.js.map +0 -1
  471. package/dist/shared/utils/sleep.d.ts +0 -48
  472. package/dist/shared/utils/sleep.d.ts.map +0 -1
  473. package/dist/shared/utils/sleep.js +0 -82
  474. package/dist/shared/utils/sleep.js.map +0 -1
  475. package/dist/shared/utils/ttl.d.ts +0 -24
  476. package/dist/shared/utils/ttl.d.ts.map +0 -1
  477. package/dist/shared/utils/ttl.js +0 -43
  478. package/dist/shared/utils/ttl.js.map +0 -1
  479. package/dist/store/actions/get-operation.d.ts +0 -11
  480. package/dist/store/actions/get-operation.d.ts.map +0 -1
  481. package/dist/store/actions/get-operation.js +0 -42
  482. package/dist/store/actions/get-operation.js.map +0 -1
  483. package/dist/store/actions/index.d.ts +0 -5
  484. package/dist/store/actions/index.d.ts.map +0 -1
  485. package/dist/store/actions/index.js +0 -21
  486. package/dist/store/actions/index.js.map +0 -1
  487. package/dist/store/actions/list-namespaces-operation.d.ts +0 -10
  488. package/dist/store/actions/list-namespaces-operation.d.ts.map +0 -1
  489. package/dist/store/actions/list-namespaces-operation.js +0 -227
  490. package/dist/store/actions/list-namespaces-operation.js.map +0 -1
  491. package/dist/store/actions/put-operation.d.ts +0 -9
  492. package/dist/store/actions/put-operation.d.ts.map +0 -1
  493. package/dist/store/actions/put-operation.js +0 -107
  494. package/dist/store/actions/put-operation.js.map +0 -1
  495. package/dist/store/actions/search-operation.d.ts +0 -17
  496. package/dist/store/actions/search-operation.d.ts.map +0 -1
  497. package/dist/store/actions/search-operation.js +0 -203
  498. package/dist/store/actions/search-operation.js.map +0 -1
  499. package/dist/store/index.d.ts +0 -82
  500. package/dist/store/index.d.ts.map +0 -1
  501. package/dist/store/index.js +0 -172
  502. package/dist/store/index.js.map +0 -1
  503. package/dist/store/types/index.d.ts +0 -131
  504. package/dist/store/types/index.d.ts.map +0 -1
  505. package/dist/store/types/index.js.map +0 -1
  506. package/dist/store/utils/filter.d.ts +0 -16
  507. package/dist/store/utils/filter.d.ts.map +0 -1
  508. package/dist/store/utils/filter.js +0 -133
  509. package/dist/store/utils/filter.js.map +0 -1
  510. package/dist/store/utils/index.d.ts +0 -7
  511. package/dist/store/utils/index.d.ts.map +0 -1
  512. package/dist/store/utils/index.js +0 -27
  513. package/dist/store/utils/index.js.map +0 -1
  514. package/dist/store/utils/validation.d.ts +0 -61
  515. package/dist/store/utils/validation.d.ts.map +0 -1
  516. package/dist/store/utils/validation.js +0 -260
  517. package/dist/store/utils/validation.js.map +0 -1
package/README.md CHANGED
@@ -3,649 +3,361 @@
3
3
  [![npm version](https://img.shields.io/npm/v/%40farukada%2Faws-langgraph-dynamodb-ts)](https://www.npmjs.com/package/@farukada/aws-langgraph-dynamodb-ts)
4
4
  [![Sponsor](https://img.shields.io/badge/Sponsor-FarukAda-ea4aaa?logo=githubsponsors)](https://github.com/sponsors/FarukAda)
5
5
  ![Node >=22](https://img.shields.io/badge/node-%3E%3D22-339933)
6
- ![TypeScript](https://img.shields.io/badge/TypeScript-5.9-3178C6)
6
+ ![TypeScript](https://img.shields.io/badge/TypeScript-6.x-3178C6)
7
7
  ![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)
8
8
  ![AWS SDK v3](https://img.shields.io/badge/AWS%20SDK-v3-FF9900)
9
9
 
10
- AWS DynamoDB persistence layer for [LangGraph](https://langchain-ai.github.io/langgraphjs/) in TypeScript. Drop-in checkpoint storage, long-term memory with semantic search, and chat message history — all backed by DynamoDB with optional S3 offloading for large payloads.
10
+ A DynamoDB persistence layer for [LangGraph](https://langchain-ai.github.io/langgraphjs/) in TypeScript (CommonJS build, consumable from both ESM and CommonJS; Node ≥ 22). It provides three LangGraph/LangChain adapters plus a factory:
11
+
12
+ - **`DynamoDBSaver`** — checkpoint + pending-writes persistence (`extends BaseCheckpointSaver`).
13
+ - **`DynamoDBStore`** — long-term memory with optional semantic search (`extends BaseStore`).
14
+ - **`DynamoDBChatMessageHistory`** — multi-session chat history, with a single-session adapter for `RunnableWithMessageHistory`.
15
+ - **`DynamoDBFactory`** — convenience constructors, including `createAll` (one shared client + a `destroy()`).
16
+
17
+ Every adapter supports optional **gzip compression**, **S3 offloading** of payloads over DynamoDB's 400 KB item limit, and **TTL-based expiry**. The store additionally supports **vector semantic search** — in-DynamoDB by default, or delegated to a **pluggable `VectorBackend`** (e.g. OpenSearch / pgvector) for large corpora — via any LangChain `Embeddings` implementation.
11
18
 
12
19
  ## Table of Contents
13
20
 
21
+ - [Install](#install)
22
+ - [Table schema](#table-schema)
23
+ - [Quick start](#quick-start)
24
+ - [Checkpointer](#checkpointer)
25
+ - [Store + semantic search](#store--semantic-search)
26
+ - [Chat history](#chat-history)
27
+ - [Factory](#factory)
28
+ - [Options](#options)
14
29
  - [Features](#features)
15
- - [Architecture](#architecture)
16
- - [Quick Start](#quick-start)
17
- - [Infrastructure Setup](#infrastructure-setup)
18
- - [Advanced Features](#advanced-features)
19
- - [Configuration Reference](#configuration-reference)
20
- - [IAM Permissions](#iam-permissions)
21
- - [Documentation](#documentation)
30
+ - [Error handling](#error-handling)
31
+ - [Logging](#logging)
32
+ - [Infrastructure setup](#infrastructure-setup)
33
+ - [IAM permissions](#iam-permissions)
34
+ - [Migrating from earlier versions](#migrating-from-earlier-versions)
22
35
  - [Testing](#testing)
23
- - [Project Structure](#project-structure)
24
- - [Contributing](#contributing)
25
36
  - [License](#license)
26
37
 
27
38
  ---
28
39
 
29
- <a id="features"></a>
30
-
31
- ## Features
40
+ ## Install
32
41
 
33
- | Capability | Description |
34
- |---|---|
35
- | 🔄 **Checkpoint Saver** | Persistent checkpoint storage for LangGraph state management |
36
- | 💾 **Memory Store** | Long-term memory with namespace support and optional semantic search |
37
- | 💬 **Chat History** | Persistent chat message storage with auto-generated session titles |
38
- | 🗜️ **Compression** | Optional gzip compression with smart thresholds (auto-detect on read) |
39
- | ☁️ **S3 Offloading** | Transparent S3 offloading for payloads exceeding DynamoDB's 400 KB limit |
40
- | ⚡ **Performance** | Composite keys, batch operations, exponential-backoff retry |
41
- | ♻️ **TTL Support** | Automatic data expiration (days or seconds) |
42
- | 🔒 **Type-Safe** | Full TypeScript with comprehensive type definitions |
43
- | 🏭 **Factory** | One-line setup via `DynamoDBFactory.createAll()` |
44
-
45
- <a id="architecture"></a>
46
-
47
- ## Architecture
48
-
49
- ```mermaid
50
- flowchart LR
51
- subgraph yourApp ["Your Application"]
52
- graph_node["LangGraph Node"]
53
- end
54
-
55
- subgraph library ["@farukada/aws-langgraph-dynamodb-ts"]
56
- saver["DynamoDBSaver"]
57
- store["DynamoDBStore"]
58
- history["DynamoDBChatMessageHistory"]
59
- compressor["Compressor"]
60
- offloader["S3Offloader"]
61
- end
62
-
63
- subgraph aws ["AWS"]
64
- ddb[(DynamoDB)]
65
- s3[(S3)]
66
- bedrock["Bedrock Embeddings"]
67
- end
68
-
69
- graph_node --> saver
70
- graph_node --> store
71
- graph_node --> history
72
- saver --> compressor
73
- compressor --> offloader
74
- offloader --> s3
75
- saver --> ddb
76
- store --> ddb
77
- store -.-> bedrock
78
- history --> ddb
42
+ ```bash
43
+ npm install @farukada/aws-langgraph-dynamodb-ts \
44
+ @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb \
45
+ @langchain/core @langchain/langgraph @langchain/langgraph-checkpoint
79
46
  ```
80
47
 
81
- <a id="quick-start"></a>
82
-
83
- ## Quick Start
84
-
85
- ### Install
48
+ Optional peer dependencies, installed only if you use the matching feature:
86
49
 
87
50
  ```bash
88
- npm install @farukada/aws-langgraph-dynamodb-ts
51
+ # Required only when S3 offloading is enabled
52
+ npm install @aws-sdk/client-s3
53
+
54
+ # Required only for semantic search in the store (any LangChain Embeddings works)
55
+ npm install @langchain/aws # e.g. Bedrock Titan embeddings
89
56
  ```
90
57
 
91
- #### Peer Dependencies
58
+ ## Table schema
92
59
 
93
- ```bash
94
- npm install @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb \
95
- @langchain/core @langchain/langgraph @langchain/langgraph-checkpoint
60
+ Every adapter uses the **same simple key schema**: a string partition key `PK`, a string sort key `SK`, and an optional Number `ttl` attribute for expiry. Because the key spaces never collide, **a single table can back all three adapters**, or you can use a separate table per adapter — your choice via the `tableName` option.
96
61
 
97
- # Optional — semantic search in Memory Store
98
- npm install @langchain/aws
62
+ | Attribute | Type | Role |
63
+ | --- | --- | --- |
64
+ | `PK` | String (HASH) | partition key |
65
+ | `SK` | String (RANGE) | sort key |
66
+ | `ttl` | Number | (optional) Unix-epoch-seconds expiry; enable DynamoDB TTL on this attribute |
99
67
 
100
- # Optional — S3 offloading for large payloads
101
- npm install @aws-sdk/client-s3
102
- ```
68
+ How each adapter lays out keys (informational — you don't manage this):
69
+
70
+ - **Checkpointer** — `PK = <thread_id>`; `SK` = `META#<ns>#<checkpoint_id>` (metadata), `PAYLOAD#<ns>#<checkpoint_id>` (checkpoint), `WRITE#<ns>#<checkpoint_id>#<task>#<idx>` (pending writes).
71
+ - **Store** — `PK = <namespace[0]>` (the scope root); `SK = <namespace[1..]>#<key>`. This makes a scoped prefix search a native `Query` (`PK = root AND begins_with(SK, …)`); only a rootless "search everything" falls back to a `Scan`.
72
+ - **Chat history** — `PK = <sessionId>`; one item per message at `SK = MSG#<ULID>` (ordered, append-only) plus one `SK = SESSION` metadata item.
73
+
74
+ ## Quick start
103
75
 
104
- ### Checkpoint Storage
76
+ ### Checkpointer
105
77
 
106
78
  ```typescript
107
- import { StateGraph } from '@langchain/langgraph';
108
79
  import { DynamoDBSaver } from '@farukada/aws-langgraph-dynamodb-ts';
109
80
 
110
81
  const checkpointer = new DynamoDBSaver({
111
- checkpointsTableName: 'langgraph-checkpoints',
112
- writesTableName: 'langgraph-writes',
113
- ttlDays: 30,
114
- clientConfig: { region: 'us-east-1' },
82
+ tableName: 'langgraph',
83
+ clientConfig: { region: 'eu-west-1' },
115
84
  });
116
85
 
117
- const app = workflow.compile({ checkpointer });
86
+ const graph = workflow.compile({ checkpointer });
118
87
 
119
- // State is automatically persisted and can be resumed
120
- await app.invoke(input, {
121
- configurable: { thread_id: 'conversation-123' },
122
- });
88
+ const config = { configurable: { thread_id: 'user-42' } };
89
+ await graph.invoke({ messages: [/* ... */] }, config);
90
+
91
+ // Resume later (even in a new process) — state is loaded from DynamoDB.
92
+ const resumed = await graph.invoke({ messages: [/* ... */] }, config);
93
+
94
+ checkpointer.destroy(); // releases the client this instance created
123
95
  ```
124
96
 
125
- ### Memory Store
97
+ ### Store + semantic search
126
98
 
127
99
  ```typescript
128
100
  import { DynamoDBStore } from '@farukada/aws-langgraph-dynamodb-ts';
129
101
  import { BedrockEmbeddings } from '@langchain/aws';
130
102
 
131
103
  const store = new DynamoDBStore({
132
- memoryTableName: 'langgraph-memory',
133
- embedding: new BedrockEmbeddings({
134
- region: 'us-east-1',
135
- model: 'amazon.titan-embed-text-v1',
136
- }),
137
- ttlDays: 90,
104
+ tableName: 'langgraph',
105
+ clientConfig: { region: 'eu-west-1' },
106
+ index: {
107
+ dims: 1024,
108
+ embeddings: new BedrockEmbeddings({ model: 'amazon.titan-embed-text-v2:0', region: 'eu-west-1' }),
109
+ fields: ['text'], // which fields to embed; defaults to the whole document ('$')
110
+ },
138
111
  });
139
112
 
140
- // Put memories
141
- await store.batch([
142
- {
143
- namespace: ['user', 'preferences'],
144
- key: 'theme',
145
- value: { color: 'dark', fontSize: 14 },
146
- },
147
- ], { configurable: { user_id: 'user-123' } });
113
+ await store.put(['library'], 'doc-1', { text: 'Amazon DynamoDB is a serverless NoSQL database' });
114
+ await store.put(['library'], 'doc-2', { text: 'Espresso is a concentrated coffee' });
115
+
116
+ // Metadata filtering (operators: $eq, $ne, $gt, $gte, $lt, $lte)
117
+ await store.search(['library'], { filter: { type: 'note', score: { $gte: 5 } } });
148
118
 
149
- // Semantic search
150
- const [results] = await store.batch([
151
- { namespacePrefix: ['user'], query: 'color preferences', limit: 5 },
152
- ], { configurable: { user_id: 'user-123' } });
119
+ // Semantic search — ranked by cosine similarity to the query embedding
120
+ const hits = await store.search(['library'], { query: 'cloud database', limit: 5 });
121
+ //=> doc-1 ranks first, with a `score` on each SearchItem
122
+
123
+ await store.get(['library'], 'doc-1');
124
+ await store.delete(['library'], 'doc-1');
125
+ await store.listNamespaces({ prefix: ['library'], maxDepth: 1 });
153
126
  ```
154
127
 
155
- ### Chat History
128
+ ### Chat history
156
129
 
157
130
  ```typescript
158
131
  import { DynamoDBChatMessageHistory } from '@farukada/aws-langgraph-dynamodb-ts';
159
- import { HumanMessage, AIMessage } from '@langchain/core/messages';
132
+ import { HumanMessage } from '@langchain/core/messages';
160
133
 
161
134
  const history = new DynamoDBChatMessageHistory({
162
- tableName: 'langgraph-chat-history',
163
- ttlDays: 30,
135
+ tableName: 'langgraph',
136
+ clientConfig: { region: 'eu-west-1' },
164
137
  });
165
138
 
166
- await history.addMessages('user-123', 'session-456', [
167
- new HumanMessage('Hello!'),
168
- new AIMessage('Hi there!'),
169
- ]);
170
-
171
- const sessions = await history.listSessions('user-123');
139
+ await history.addMessages('session-1', [new HumanMessage('Hello!')]);
140
+ const messages = await history.getMessages('session-1');
141
+ const sessions = await history.listSessions(); // [{ sessionId, title, messageCount, ... }]
142
+ await history.clear('session-1');
172
143
  ```
173
144
 
174
- > **TTL semantics.** The session metadata item's TTL is refreshed on every
175
- > `addMessage`/`addMessages` call, so `listSessions()` keeps reporting the
176
- > session as live while activity continues. Individual message items get their
177
- > TTL stamped at write time and expire independently — a long-lived session can
178
- > develop gaps where older messages drop out while recent ones persist. If that
179
- > isn't acceptable, set `ttlDays` well above your expected session lifetime or
180
- > manage deletion explicitly via `clear()`.
181
-
182
- ### Factory (One-Liner)
145
+ Use it with LangChain's `RunnableWithMessageHistory` via the single-session adapter:
183
146
 
184
147
  ```typescript
185
- import { DynamoDBFactory } from '@farukada/aws-langgraph-dynamodb-ts';
148
+ import { RunnableWithMessageHistory } from '@langchain/core/runnables';
186
149
 
187
- const { checkpointer, store, chatHistory, destroy } = DynamoDBFactory.createAll({
188
- tablePrefix: 'my-app',
189
- ttlDays: 30,
190
- clientConfig: { region: 'us-east-1' },
150
+ const withHistory = new RunnableWithMessageHistory({
151
+ runnable: chain,
152
+ getMessageHistory: (sessionId) => history.forSession(sessionId),
153
+ inputMessagesKey: 'input',
154
+ historyMessagesKey: 'history',
191
155
  });
192
-
193
- // When done, release the shared DynamoDB client
194
- destroy();
195
156
  ```
196
157
 
197
- <a id="infrastructure-setup"></a>
198
-
199
- ## Infrastructure Setup
158
+ ### Factory
200
159
 
201
- Create the required DynamoDB tables using **AWS CDK** or **Terraform**.
202
-
203
- <details>
204
- <summary><strong>AWS CDK (TypeScript)</strong></summary>
160
+ `createAll` builds all three adapters on **one shared DynamoDB client** and returns a single `destroy()` that tears everything down.
205
161
 
206
162
  ```typescript
207
- import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
163
+ import { DynamoDBFactory } from '@farukada/aws-langgraph-dynamodb-ts';
208
164
 
209
- // Checkpoints
210
- new dynamodb.Table(this, 'Checkpoints', {
211
- tableName: 'langgraph-checkpoints',
212
- partitionKey: { name: 'thread_id', type: dynamodb.AttributeType.STRING },
213
- sortKey: { name: 'checkpoint_id', type: dynamodb.AttributeType.STRING },
214
- billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
215
- timeToLiveAttribute: 'ttl',
216
- });
165
+ const factory = new DynamoDBFactory({ clientConfig: { region: 'eu-west-1' } });
217
166
 
218
- // Writes
219
- new dynamodb.Table(this, 'Writes', {
220
- tableName: 'langgraph-writes',
221
- partitionKey: { name: 'thread_id_checkpoint_id_checkpoint_ns', type: dynamodb.AttributeType.STRING },
222
- sortKey: { name: 'task_id_idx', type: dynamodb.AttributeType.STRING },
223
- billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
224
- timeToLiveAttribute: 'ttl',
167
+ const { saver, store, history, destroy } = factory.createAll({
168
+ saver: { tableName: 'langgraph' },
169
+ store: { tableName: 'langgraph', index: { dims: 1024, embeddings } },
170
+ history: { tableName: 'langgraph' },
225
171
  });
226
172
 
227
- // Memory
228
- new dynamodb.Table(this, 'Memory', {
229
- tableName: 'langgraph-memory',
230
- partitionKey: { name: 'user_id', type: dynamodb.AttributeType.STRING },
231
- sortKey: { name: 'namespace_key', type: dynamodb.AttributeType.STRING },
232
- billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
233
- timeToLiveAttribute: 'ttl',
234
- });
173
+ // ... use saver / store / history ...
235
174
 
236
- // Chat History
237
- new dynamodb.Table(this, 'ChatHistory', {
238
- tableName: 'langgraph-chat-history',
239
- partitionKey: { name: 'userId', type: dynamodb.AttributeType.STRING },
240
- sortKey: { name: 'sessionId', type: dynamodb.AttributeType.STRING },
241
- billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
242
- timeToLiveAttribute: 'ttl',
243
- });
175
+ destroy(); // closes the one shared client
244
176
  ```
245
177
 
246
- </details>
247
-
248
- <details>
249
- <summary><strong>Terraform</strong></summary>
250
-
251
- ```hcl
252
- resource "aws_dynamodb_table" "checkpoints" {
253
- name = "langgraph-checkpoints"
254
- billing_mode = "PAY_PER_REQUEST"
255
- hash_key = "thread_id"
256
- range_key = "checkpoint_id"
257
- attribute { name = "thread_id" type = "S" }
258
- attribute { name = "checkpoint_id" type = "S" }
259
- ttl { attribute_name = "ttl" enabled = true }
260
- }
178
+ ## Options
261
179
 
262
- resource "aws_dynamodb_table" "writes" {
263
- name = "langgraph-writes"
264
- billing_mode = "PAY_PER_REQUEST"
265
- hash_key = "thread_id_checkpoint_id_checkpoint_ns"
266
- range_key = "task_id_idx"
267
- attribute { name = "thread_id_checkpoint_id_checkpoint_ns" type = "S" }
268
- attribute { name = "task_id_idx" type = "S" }
269
- ttl { attribute_name = "ttl" enabled = true }
270
- }
180
+ All adapters share a common base. Provide **either** a prebuilt `client` (which the adapter will not own/close) **or** `clientConfig` (the adapter builds and owns the client).
271
181
 
272
- resource "aws_dynamodb_table" "memory" {
273
- name = "langgraph-memory"
274
- billing_mode = "PAY_PER_REQUEST"
275
- hash_key = "user_id"
276
- range_key = "namespace_key"
277
- attribute { name = "user_id" type = "S" }
278
- attribute { name = "namespace_key" type = "S" }
279
- ttl { attribute_name = "ttl" enabled = true }
280
- }
281
-
282
- resource "aws_dynamodb_table" "chat_history" {
283
- name = "langgraph-chat-history"
284
- billing_mode = "PAY_PER_REQUEST"
285
- hash_key = "userId"
286
- range_key = "sessionId"
287
- attribute { name = "userId" type = "S" }
288
- attribute { name = "sessionId" type = "S" }
289
- ttl { attribute_name = "ttl" enabled = true }
290
- }
291
- ```
292
-
293
- </details>
182
+ | Option | Type | Applies to | Notes |
183
+ | --- | --- | --- | --- |
184
+ | `tableName` | `string` | all | **required** |
185
+ | `client` | `DynamoDBDocument` | all | reuse an existing client; not closed by `destroy()` |
186
+ | `clientConfig` | `DynamoDBClientConfig` | all | used to build a client when `client` is omitted |
187
+ | `ttl` | `{ days: number }` \| `{ seconds: number }` | all | expiry written to the `ttl` attribute |
188
+ | `logger` | `Logger` | all | per-instance logger (default: silent) |
189
+ | `compression` | `CompressionConfig` | all | `{ enabled, minSizeBytes?, level?, maxDecompressedBytes? }` |
190
+ | `s3` | `S3OffloadConfig` | all | offload large payloads to S3 (see below) |
191
+ | `serde` | `SerializerProtocol` | all | serializer override (checkpointer defaults to LangGraph's; store/history to JSON) |
192
+ | `index` | `IndexConfig` | store only | `{ dims, embeddings, fields? }` for semantic search |
193
+ | `vectorBackend` | `VectorBackend` | store only | delegate similarity search to an external index; DynamoDB keeps the canonical item |
194
+ | `maxSearchCandidates` | `number` | store only | cap for the in-DB ranker before it errors (default 1000) |
294
195
 
295
- <a id="advanced-features"></a>
196
+ `S3OffloadConfig`: `{ bucketName, keyPrefix?, thresholdBytes?, serverSideEncryption?, sseKmsKeyId?, clientConfig? }`.
296
197
 
297
- ## Advanced Features
198
+ ## Features
298
199
 
299
- ### Gzip Compression
200
+ **Gzip compression** — set `compression: { enabled: true }`. Payloads at or above `minSizeBytes` (default 1 KB) are gzipped transparently; decompression auto-detects on read and is guarded against decompression-bomb expansion (`maxDecompressedBytes`, default 50 MiB).
300
201
 
301
- Reduce DynamoDB item sizes and costs by enabling transparent gzip compression:
202
+ **S3 offloading** — set `s3: { bucketName }`. Any serialized payload at or above `thresholdBytes` (default 350 KB) is written to S3, with only a reference stored in DynamoDB; reads rehydrate transparently. Requires the optional `@aws-sdk/client-s3` peer. When a `ttl` is also configured the library best-effort installs a matching S3 lifecycle expiration rule (logged, never fatal). Deleting a checkpoint thread / chat session also best-effort deletes its offloaded objects.
302
203
 
303
- ```typescript
304
- const checkpointer = new DynamoDBSaver({
305
- checkpointsTableName: 'langgraph-checkpoints',
306
- writesTableName: 'langgraph-writes',
307
- compression: {
308
- enabled: true,
309
- minSizeBytes: 1024, // Only compress payloads ≥ 1 KB
310
- },
311
- });
312
- ```
204
+ **TTL expiry** — set `ttl: { days }` or `ttl: { seconds }`. The `ttl` attribute is written as a Unix-epoch-seconds timestamp; enable DynamoDB TTL on the `ttl` attribute for automatic deletion. Chat history anchors a single **uniform whole-conversation TTL** at session creation (via `if_not_exists`), shared by every message, so a live session never develops mid-history gaps; expired messages are also filtered out on read.
313
205
 
314
- ### S3 Offloading
206
+ **Semantic search** (store) — provide `index` with a LangChain `Embeddings` implementation. On `put`, the configured `fields` are embedded; on `search` with a `query`, results are ranked by cosine similarity. By default the embedding is stored on the item and ranking happens in-process over the scoped candidate set (bounded by `maxSearchCandidates`, default 1000 — exceeding it throws, steering you to an external index). For large corpora, pass a `vectorBackend`: the embedding is sent there instead, similarity search is delegated to it, and DynamoDB still holds the canonical item. Per-item indexing can be overridden via the `index` argument to `put` (`false` to skip, or a `string[]` of fields).
315
207
 
316
- Automatically offload payloads exceeding DynamoDB's 400 KB item limit to S3:
208
+ **Vector index consistency** — when a `vectorBackend` is configured, **DynamoDB holds the canonical item** and the backend is a rebuildable index. After each canonical write the embedding is synced to the backend best-effort: a failure is logged (not thrown), so a backend hiccup never fails an otherwise-successful `put`/`delete`. To repair drift, call `store.reconcileVectorIndex(namespacePrefix)` — it re-pushes every live embedding and, when the backend implements the optional `listKeys`, prunes vectors with no canonical item; it returns `{ upserted, pruned }`. Run it when the namespace is idle. Caveats: reconciliation re-embeds with the store's **configured** index fields, so per-`put` field overrides are not reproduced; prune happens only when `listKeys` is implemented (otherwise reconcile re-pushes only and logs that prune was skipped); the prefix must be a non-empty namespace.
317
209
 
318
- ```typescript
319
- const checkpointer = new DynamoDBSaver({
320
- checkpointsTableName: 'langgraph-checkpoints',
321
- writesTableName: 'langgraph-writes',
322
- s3OffloadConfig: {
323
- bucketName: 'my-checkpoints-bucket',
324
- keyPrefix: 'langgraph/', // default: 'langgraph-checkpoints/'
325
- thresholdBytes: 350 * 1024, // default: 350 KB
326
- serverSideEncryption: 'aws:kms', // optional: 'AES256' or 'aws:kms'
327
- sseKmsKeyId: 'alias/my-key', // optional: KMS key ID/ARN
328
- clientConfig: { region: 'us-east-1' },
329
- },
330
- });
331
- ```
210
+ **Strong consistency** — checkpointer read-your-writes (`getTuple`) and every `store.get` use `ConsistentRead`, so a value written and immediately read back is never served a stale replica. Bulk reads (`list`, `listNamespaces`, `listSessions`) stay eventually consistent for lower cost.
332
211
 
333
- When TTL and S3 offloading are both enabled, the library automatically configures an S3 lifecycle expiration rule on the bucket (scoped to the key prefix). This requires `s3:GetBucketLifecycleConfiguration` and `s3:PutBucketLifecycleConfiguration` permissions on the bucket. If these permissions are unavailable, a warning is logged but the saver continues to function normally.
212
+ ## Error handling
334
213
 
335
- ### Store Filters
214
+ All errors thrown by the library extend `DynamoDbLangGraphError` and carry a stable `code` from the `ErrorCode` enum plus a native `cause` chain. Branch on `code`:
336
215
 
337
216
  ```typescript
338
- // Supported operators: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin.
339
- // Filter keys are fields inside the stored `value` — the library wraps each
340
- // key as `value.<key>` when building the DynamoDB FilterExpression.
341
- const [results] = await store.batch([
342
- {
343
- namespacePrefix: ['products'],
344
- filter: {
345
- price: { $gte: 10, $lte: 100 },
346
- category: { $in: ['electronics', 'books'] },
347
- status: { $ne: 'archived' },
348
- },
349
- limit: 10,
350
- },
351
- ], { configurable: { user_id: 'user-123' } });
217
+ import { ErrorCode, DynamoDbLangGraphError } from '@farukada/aws-langgraph-dynamodb-ts';
218
+
219
+ try {
220
+ await store.put([''], 'k', { v: 1 });
221
+ } catch (error) {
222
+ if (error instanceof DynamoDbLangGraphError && error.code === ErrorCode.VALIDATION) {
223
+ // bad input
224
+ }
225
+ }
352
226
  ```
353
227
 
354
- ### Namespace Organization
355
-
356
- ```typescript
357
- // Hierarchical namespace patterns
358
- ['user', userId, 'preferences']
359
- ['user', userId, 'conversations', threadId]
360
- ['documents', 'category', 'subcategory']
361
- ```
228
+ `ErrorCode` values: `VALIDATION`, `CONDITION_CONFLICT`, `RETRY_EXHAUSTED`, `BATCH_WRITE_INCOMPLETE`, `COMPRESSION_LIMIT`, `S3_OFFLOAD_FAILED`, `ABORTED`. Typed subclasses are exported where callers commonly branch: `ValidationError`, `ConflictError`, `RetryExhaustedError`, `BatchWriteIncompleteError`, `AbortError`.
362
229
 
363
- ### LangChain `RunnableWithMessageHistory` integration
230
+ ## Logging
364
231
 
365
- `DynamoDBChatMessageHistory` is a multi-session store; to hand a single
366
- `(userId, sessionId)` pair to LangChain's `RunnableWithMessageHistory`, bind it
367
- with `forSession()` which returns a `BaseListChatMessageHistory` compatible
368
- instance:
232
+ Logging is **per-instance and silent by default** — the library never writes to your console uninvited. Pass any object matching the `Logger` interface (`info`/`warn`/`error`/`debug`):
369
233
 
370
234
  ```typescript
371
- import { RunnableWithMessageHistory } from '@langchain/core/runnables';
372
- import { DynamoDBChatMessageHistory } from '@farukada/aws-langgraph-dynamodb-ts';
235
+ import { redactLogger, type Logger } from '@farukada/aws-langgraph-dynamodb-ts';
373
236
 
374
- const store = new DynamoDBChatMessageHistory({ tableName: 'chat-sessions' });
237
+ const logger: Logger = {
238
+ info: (m, ...a) => console.info(m, ...a),
239
+ warn: (m, ...a) => console.warn(m, ...a),
240
+ error: (m, ...a) => console.error(m, ...a),
241
+ debug: () => {},
242
+ };
375
243
 
376
- const chain = new RunnableWithMessageHistory({
377
- runnable,
378
- getMessageHistory: (sessionId) => store.forSession(userId, sessionId),
379
- inputMessagesKey: 'input',
380
- historyMessagesKey: 'history',
381
- });
244
+ const store = new DynamoDBStore({ tableName: 'langgraph', logger: redactLogger(logger) });
382
245
  ```
383
246
 
384
- ### Atomicity contract
247
+ `redactLogger` wraps a logger so secret-looking fields (access keys, tokens, passwords, …) are replaced with `[REDACTED]` in structured log arguments. `redactSecrets` exposes the same redaction for arbitrary objects.
385
248
 
386
- | Operation | Atomicity scope | Failure mode |
387
- |---|---|---|
388
- | `DynamoDBSaver.put()` | Single `TransactWrite` on the **checkpoints** table. Both the metadata item and the payload item either both persist or neither does. | Throws; any S3 objects already uploaded are best-effort cleaned, otherwise swept by the S3 lifecycle rule. |
389
- | `DynamoDBSaver.putWrites()` | `BatchWriteItem` against the **writes** table, chunked in groups of 25. Each 25-item batch is independently atomic at the DynamoDB level; batches are *not* transactional with each other. | On retry exhaustion, throws `BatchWriteIncompleteError` with `.succeededCount` and `.unprocessed` so callers can drive reconciliation. Items already acked by DynamoDB remain persisted. |
390
- | `put()` ↔ `putWrites()` | **Not** atomic across tables. LangGraph calls them as distinct steps; a crash between them leaves a checkpoint without its writes (or vice versa). | LangGraph's node-retry loop will re-invoke both; the idempotency guard on `put()` makes re-submission safe. |
391
- | `DynamoDBChatMessageHistory.addMessage(s)` | `TransactWriteItems` — up to 99 message items plus the metadata counter update, guarded by an optimistic `messageCount` condition. All-or-nothing per call. | Throws on conflict; the helper retries up to 5× on `ConditionalCheckFailed` sub-reasons. |
392
- | `DynamoDBStore.batch()` (Put) | Per-item `UpdateItem` / `PutItem`. Batch failure is per-operation. | Each op's error propagates via `Promise.all`. |
249
+ ## Infrastructure setup
393
250
 
394
- ### `put()` optimistic-concurrency guard
251
+ One table backs all three adapters. Create it with **AWS CDK** or **Terraform**.
395
252
 
396
- Every `put()` writes metadata with a `ConditionExpression` that rejects the
397
- transaction when a pre-existing row for the same `(thread_id, checkpoint_id)`
398
- disagrees on `parent_checkpoint_id` or serializer `type`. Effect:
253
+ <details>
254
+ <summary><strong>AWS CDK (TypeScript)</strong></summary>
399
255
 
400
- - A fresh checkpoint always succeeds.
401
- - A retry after a transient error (network blip, throttling) re-issues the same
402
- `(parent, type)` and succeeds as if idempotent.
403
- - Two concurrent workers writing the same `checkpoint_id` but with different
404
- lineage surface a `ConditionalCheckFailedException` instead of silently
405
- last-writer-wins. Treat it as a signal that your application is accidentally
406
- racing two graphs on the same thread.
256
+ ```typescript
257
+ import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
407
258
 
408
- ### Limits and safety caps
259
+ new dynamodb.Table(this, 'LangGraph', {
260
+ tableName: 'langgraph',
261
+ partitionKey: { name: 'PK', type: dynamodb.AttributeType.STRING },
262
+ sortKey: { name: 'SK', type: dynamodb.AttributeType.STRING },
263
+ billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
264
+ timeToLiveAttribute: 'ttl', // optional; only needed if you use the `ttl` option
265
+ });
266
+ ```
409
267
 
410
- The library enforces a set of client-side caps to produce clean, actionable
411
- errors before DynamoDB / zlib / memory blow up on pathological inputs. All of
412
- them are configurable or can be raised if a legitimate workload needs more.
268
+ </details>
413
269
 
414
- | Cap | Default | Raise via | Hit when |
415
- |---|---|---|---|
416
- | Decompressed checkpoint size | 50 MiB | `compression.maxDecompressedBytes` | Gzip payload expands beyond the cap — defends against gzip bombs. |
417
- | Filter expression string | 3.5 KiB | not configurable — simplify the filter | Complex / deeply-nested `Store.batch` searches. DynamoDB's hard limit is 4 KiB. |
418
- | `$in` / `$nin` array size | 50 values | not configurable — split the query | Store filter with oversized enum sets. |
419
- | `list()` page iterations | 1000 pages | not configurable — narrow the filter or add a GSI | Filters that match almost nothing across a very large thread. |
420
- | `deleteThread()` page iterations | 10 000 pages | not configurable — investigate the thread | Effectively "unbounded for real workloads"; only trips on extreme datasets. |
421
- | Retry `cause`-chain depth | 32 | not configurable | Hostile error with an absurd nesting depth; prevents stack-overflow DoS. |
270
+ <details>
271
+ <summary><strong>Terraform</strong></summary>
422
272
 
423
- ### S3 encryption
273
+ ```hcl
274
+ resource "aws_dynamodb_table" "langgraph" {
275
+ name = "langgraph"
276
+ billing_mode = "PAY_PER_REQUEST"
277
+ hash_key = "PK"
278
+ range_key = "SK"
424
279
 
425
- Offloaded checkpoint payloads are written with `ServerSideEncryption: AES256`
426
- by default (matching S3's own default since 2023). If your bucket policy
427
- enforces a different algorithm (e.g. `aws:kms`), set it explicitly:
280
+ attribute { name = "PK" type = "S" }
281
+ attribute { name = "SK" type = "S" }
428
282
 
429
- ```typescript
430
- s3OffloadConfig: {
431
- bucketName: 'my-checkpoints-bucket',
432
- serverSideEncryption: 'aws:kms',
433
- sseKmsKeyId: 'alias/my-key',
283
+ ttl {
284
+ attribute_name = "ttl"
285
+ enabled = true
286
+ }
434
287
  }
435
288
  ```
436
289
 
437
- IAM: the `s3:PutObject` permission granted in the minimum policy above is
438
- sufficient. If your bucket policy denies the `AES256` algorithm, either grant
439
- the key permissions required for `aws:kms` or set `serverSideEncryption`
440
- explicitly to match the bucket policy.
441
-
442
- ### Checkpoint data migration (v<4)
443
-
444
- LangGraph bumped the `Checkpoint.v` field to **4** in `@langchain/langgraph-checkpoint@1.0`. Reading data written by older versions (v<4) requires synthesizing the `TASKS` channel from parent-checkpoint writes — this library does not migrate on read. If you have pre-1.0 data, run LangGraph's reference migration before switching to this saver, or drop the older checkpoints.
445
-
446
- <a id="configuration-reference"></a>
447
-
448
- ## Configuration Reference
449
-
450
- ### DynamoDBSaver
451
-
452
- | Option | Type | Default | Description |
453
- |---|---|---|---|
454
- | `checkpointsTableName` | `string` | — | Checkpoints table name (**required**) |
455
- | `writesTableName` | `string` | — | Writes table name (**required**) |
456
- | `ttlDays` | `number` | — | TTL in days |
457
- | `ttlSeconds` | `number` | — | TTL in seconds (overrides `ttlDays`) |
458
- | `compression` | `object` | — | `{ enabled, minSizeBytes?, level? }` |
459
- | `s3OffloadConfig` | `object` | — | `{ bucketName, keyPrefix?, thresholdBytes?, serverSideEncryption?, sseKmsKeyId?, clientConfig? }` |
460
- | `clientConfig` | `object` | — | AWS SDK `DynamoDBClientConfig` |
461
- | `client` | `DynamoDBDocument` | — | Pre-built client (takes precedence over `clientConfig`) |
462
-
463
- ### DynamoDBStore
464
-
465
- | Option | Type | Default | Description |
466
- |---|---|---|---|
467
- | `memoryTableName` | `string` | — | Memory table name (**required**) |
468
- | `embedding` | `EmbeddingsInterface` | — | Any LangChain embeddings provider for semantic search |
469
- | `ttlDays` | `number` | — | TTL in days |
470
- | `clientConfig` | `object` | — | AWS SDK `DynamoDBClientConfig` |
471
- | `client` | `DynamoDBDocument` | — | Pre-built client (takes precedence over `clientConfig`) |
472
-
473
- ### DynamoDBChatMessageHistory
474
-
475
- | Option | Type | Default | Description |
476
- |---|---|---|---|
477
- | `tableName` | `string` | — | Chat history table name (**required**) |
478
- | `ttlDays` | `number` | — | TTL in days |
479
- | `clientConfig` | `object` | — | AWS SDK `DynamoDBClientConfig` |
480
- | `client` | `DynamoDBDocument` | — | Pre-built client (takes precedence over `clientConfig`) |
290
+ </details>
481
291
 
482
- <a id="iam-permissions"></a>
292
+ ## IAM permissions
483
293
 
484
- ## IAM Permissions
294
+ Minimum DynamoDB actions on the table:
485
295
 
486
- <details>
487
- <summary><strong>Minimum IAM Policy</strong></summary>
488
-
489
- ```json
490
- {
491
- "Version": "2012-10-17",
492
- "Statement": [
493
- {
494
- "Sid": "CheckpointerAccess",
495
- "Effect": "Allow",
496
- "Action": [
497
- "dynamodb:GetItem",
498
- "dynamodb:PutItem",
499
- "dynamodb:Query",
500
- "dynamodb:BatchGetItem",
501
- "dynamodb:BatchWriteItem",
502
- "dynamodb:TransactWriteItems"
503
- ],
504
- "Resource": [
505
- "arn:aws:dynamodb:REGION:ACCOUNT:table/langgraph-checkpoints",
506
- "arn:aws:dynamodb:REGION:ACCOUNT:table/langgraph-writes"
507
- ]
508
- },
509
- {
510
- "Sid": "StoreAndHistoryAccess",
511
- "Effect": "Allow",
512
- "Action": [
513
- "dynamodb:GetItem",
514
- "dynamodb:PutItem",
515
- "dynamodb:UpdateItem",
516
- "dynamodb:DeleteItem",
517
- "dynamodb:Query",
518
- "dynamodb:BatchWriteItem"
519
- ],
520
- "Resource": [
521
- "arn:aws:dynamodb:REGION:ACCOUNT:table/langgraph-memory",
522
- "arn:aws:dynamodb:REGION:ACCOUNT:table/langgraph-chat-history"
523
- ]
524
- },
525
- {
526
- "Sid": "OptionalSemanticSearch",
527
- "Effect": "Allow",
528
- "Action": ["bedrock:InvokeModel"],
529
- "Resource": "arn:aws:bedrock:REGION::foundation-model/amazon.titan-embed-text-v1"
530
- },
531
- {
532
- "Sid": "OptionalS3Offloading",
533
- "Effect": "Allow",
534
- "Action": [
535
- "s3:PutObject",
536
- "s3:GetObject",
537
- "s3:DeleteObject",
538
- "s3:DeleteObjects"
539
- ],
540
- "Resource": "arn:aws:s3:::YOUR-BUCKET/langgraph-checkpoints/*"
541
- },
542
- {
543
- "Sid": "OptionalS3LifecycleManagement",
544
- "Effect": "Allow",
545
- "Action": [
546
- "s3:GetBucketLifecycleConfiguration",
547
- "s3:PutBucketLifecycleConfiguration"
548
- ],
549
- "Resource": "arn:aws:s3:::YOUR-BUCKET"
550
- }
551
- ]
552
- }
296
+ ```
297
+ dynamodb:GetItem
298
+ dynamodb:PutItem
299
+ dynamodb:DeleteItem
300
+ dynamodb:Query
301
+ dynamodb:Scan
302
+ dynamodb:BatchGetItem
303
+ dynamodb:BatchWriteItem
304
+ dynamodb:TransactWriteItems
553
305
  ```
554
306
 
555
- </details>
307
+ When S3 offloading is enabled, on the bucket/objects: `s3:GetObject`, `s3:PutObject`, `s3:DeleteObject`, `s3:ListBucket`, and — only if TTL-driven lifecycle rules are desired — `s3:GetBucketLifecycleConfiguration` and `s3:PutBucketLifecycleConfiguration`. For semantic search via Bedrock embeddings: `bedrock:InvokeModel`.
556
308
 
557
- <a id="documentation"></a>
309
+ ## Migrating from earlier versions
558
310
 
559
- ## Documentation
311
+ **0.2.x → 0.3.0** is a complete, ground-up rewrite. The public API is similar, but the table schema, on-disk layout, and several options changed, so existing data is **not compatible** — create a new table.
560
312
 
561
- - **[Checkpointer Guide](./src/checkpointer/checkpointer.md)** — Checkpoint management, workflow persistence, recovery
562
- - **[Store Guide](./src/store/store.md)** — Memory storage, semantic search, filtering, namespaces
563
- - **[History Guide](./src/history/history.md)** — Chat message storage, session management
564
- - **[API Reference (TypeDoc)](./docs/README.md)** — Full class & interface documentation
313
+ - **Table schema is now `PK`/`SK` strings** (one table for all adapters) instead of per-adapter custom key names. The key attribute names changed, so CDK/Terraform definitions need updating.
314
+ - **Store keys** are `PK = namespace[0]`, `SK = namespace[1..]#key` (was `PK = full namespace`, `SK = key`).
315
+ - **Chat history is one item per message** (`SK = MSG#<ULID>`) plus a `SESSION` metadata item, replacing the single per-session item.
316
+ - **Single `tableName` option** per adapter (was `checkpointsTableName`/`writesTableName`, etc.).
317
+ - **One `ttl` option** — `{ days }` or `{ seconds }` — replaces `ttlDays`/`ttlSeconds`.
318
+ - **S3 config option renamed** `s3OffloadConfig` → `s3`.
319
+ - **Per-instance `logger` option** replaces the global `setGlobalLogger` singleton; default logging is now silent.
320
+ - **Unified error model** — all errors extend `DynamoDbLangGraphError` with an `ErrorCode`.
565
321
 
566
- <a id="testing"></a>
322
+ ## Production notes
567
323
 
568
- ## Testing
324
+ - **Sharing one table** across all three adapters is supported — their key spaces don't collide, and table-wide reads filter to their own items. Checkpointer, chat-history, and *scoped* store reads are all partition-scoped (`Query`/`GetItem`).
325
+ - **Scoped reads are `Query`s.** `store.search`/`store.listNamespaces` with a concrete namespace prefix and `history.getMessages` are native `Query`s. Only a rootless `store.search([])` / unprefixed `listNamespaces` and `history.listSessions` fall back to `Scan` (cost scales with table size) — keep those rare or use a dedicated table.
326
+ - **Hot partitions.** The store's partition key is `namespace[0]` and chat history's is `sessionId`. A single partition tops out around ~1000 WCU / 3000 RCU, so avoid funneling very high write throughput through one tenant/session id; spread load across scope roots (e.g. include a tenant id as `namespace[0]`).
327
+ - **Very large vector corpora** outgrow the in-DB ranker (`maxSearchCandidates`). Configure a `vectorBackend` (OpenSearch, pgvector, …) — the library keeps DynamoDB as the source of truth and only delegates similarity ranking.
328
+ - **TTL deletion timing** is governed by DynamoDB (typically within 48 h of expiry) and S3 lifecycle expiry is day-granular — the library writes the correct expiry timestamp / lifecycle rule (and filters expired chat messages on read) but does not guarantee instant deletion.
569
329
 
570
- ### Unit tests
330
+ ## Testing
571
331
 
572
332
  ```bash
573
- npm test # Run all tests (672 unit tests, ~28s)
574
- npm test -- --coverage # With coverage
575
- npm run build # Type-check + compile
576
- npm run lint # ESLint
333
+ npm test # unit + static-guard + type tests, 100% coverage
334
+ npm run typecheck
335
+ npm run lint
336
+ npm run build
577
337
  ```
578
338
 
579
- ### Integration tests (DynamoDB Local)
580
-
581
- A dedicated integration tier verifies the library against a real DynamoDB API
582
- (catches things `aws-sdk-client-mock` cannot, such as `ValidationException` on
583
- malformed filter expressions, `ConditionExpression` enforcement, primary-key
584
- attribute rules, and lex-sort assumptions on sort keys).
339
+ Integration and contract tiers run against DynamoDB Local (Docker) and are kept out of the default `npm test`:
585
340
 
586
341
  ```bash
587
- npm run test:integration:up # docker compose up (amazon/dynamodb-local)
588
- npm run test:integration # 15 e2e tests against localhost:8000
589
- npm run test:integration:down # docker compose down
342
+ npm run test:integration:up # docker compose up -d (DynamoDB Local)
343
+ npm run test:integration # integration flows + LangGraph/LangChain contract conformance
344
+ npm run test:integration:down
590
345
  ```
591
346
 
592
- CI runs the same suite via a `DynamoDB Local` GitHub Actions service container
593
- on every pull request.
594
-
595
- ### Mutation testing (Stryker)
596
-
597
- Line coverage tells you what code ran; **mutation coverage** tells you what
598
- tests would *catch regressions*. Run against a hot spot:
347
+ Real-AWS verification scripts live in `examples/` (each creates and tears down its own resources):
599
348
 
600
349
  ```bash
601
- npm run test:mutate:quick # retry.ts, compressor.ts, filter.ts (~15 min)
602
- npm run test:mutate # full src/ (long — use incremental mode)
350
+ node examples/verify-checkpointer.mjs # save/resume/writes/list/delete, compression, S3, TTL
351
+ node examples/verify-store.mjs # filters, semantic search, S3 offload, TTL
352
+ node examples/verify-history.mjs # per-message model, concurrency, RunnableWithMessageHistory agent
353
+ node examples/verify-factory.mjs # shared-client createAll across all three adapters
354
+ node examples/verify-agents.mjs # real LangGraph agents using the saver + store as memory
355
+ node examples/verify-edge-cases.mjs # filter operators, multi-page reads, compression+S3, scale
603
356
  ```
604
357
 
605
- Stryker runs with `incremental: true`, so re-runs only re-check files that
606
- changed since the last run. Baseline kill-rate goal: **≥80%** for new code in
607
- `src/shared/` and `src/checkpointer/`.
608
-
609
- <a id="project-structure"></a>
610
-
611
- ## Project Structure
612
-
613
- ```text
614
- src/
615
- ├── checkpointer/ # DynamoDBSaver — checkpoint persistence
616
- │ ├── actions/ # put, putWrites, getTuple, deleteThread, writer
617
- │ ├── types/ # TypeScript interfaces & constants
618
- │ └── utils/ # Deserialization, validation
619
- ├── store/ # DynamoDBStore — long-term memory
620
- │ ├── actions/ # get, put, search, listNamespaces
621
- │ ├── types/ # TypeScript interfaces
622
- │ └── utils/ # Validation, filtering
623
- ├── history/ # DynamoDBChatMessageHistory — chat sessions
624
- │ ├── actions/ # getMessages, addMessage(s), clear, listSessions
625
- │ ├── types/ # TypeScript interfaces
626
- │ └── utils/ # Validation, title generation
627
- ├── shared/ # Cross-cutting utilities
628
- │ └── utils/ # Compressor, S3Offloader, retry, TTL, batch-write, logger
629
- └── factory.ts # DynamoDBFactory one-liner setup
630
- ```
631
-
632
- <a id="contributing"></a>
633
-
634
- ## Contributing
635
-
636
- Contributions welcome! Please:
637
-
638
- 1. Check existing issues or create a new one
639
- 2. Fork the repository
640
- 3. Create a feature branch
641
- 4. Add tests for your changes
642
- 5. Submit a pull request
643
-
644
- <a id="license"></a>
645
-
646
358
  ## License
647
359
 
648
- MIT © [FarukAda](https://github.com/farukada)
360
+ MIT © [Faruk Ada](https://github.com/FarukAda)
649
361
 
650
362
  ---
651
363