@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,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseSessionId = parseSessionId;
4
+ exports.parseStoredMessages = parseStoredMessages;
5
+ exports.parseMessages = parseMessages;
6
+ exports.parseMessageWindow = parseMessageWindow;
7
+ exports.parseGetMessagesRequest = parseGetMessagesRequest;
8
+ exports.parseListSessionsRequest = parseListSessionsRequest;
9
+ const messages_1 = require("@langchain/core/messages");
10
+ const table_schema_js_1 = require("../../shared/dynamodb/table-schema.js");
11
+ const errors_js_1 = require("../../shared/errors/errors.js");
12
+ const secret_patterns_js_1 = require("../../shared/logging/secret-patterns.js");
13
+ const truncate_js_1 = require("../../shared/logging/truncate.js");
14
+ const ulid_js_1 = require("../../shared/ulid.js");
15
+ const collaborators_js_1 = require("../../shared/validation/collaborators.js");
16
+ const option_shape_js_1 = require("../../shared/validation/option-shape.js");
17
+ const primitives_js_1 = require("../../shared/validation/primitives.js");
18
+ const setup_js_1 = require("./setup.js");
19
+ function parseSessionId(value) {
20
+ return (0, primitives_js_1.parseIdentifier)(value, table_schema_js_1.KEY_SEPARATOR, 'sessionId', table_schema_js_1.MAX_PARTITION_ID_BYTES);
21
+ }
22
+ function toStoredMessages(messages) {
23
+ const stored = [];
24
+ for (let index = 0; index < messages.length; index += 1) {
25
+ try {
26
+ stored.push((0, messages_1.mapChatMessagesToStoredMessages)([messages[index]])[0]);
27
+ }
28
+ catch (error) {
29
+ throw (0, errors_js_1.validationError)(`messages[${index}] is not a LangChain message: ` + (0, secret_patterns_js_1.redactedMessage)(error), 'messages');
30
+ }
31
+ }
32
+ return stored;
33
+ }
34
+ function parseStoredMessages(stored) {
35
+ for (let index = 0; index < stored.length; index += 1) {
36
+ const message = stored[index];
37
+ if (message === undefined) {
38
+ throw (0, errors_js_1.validationError)(`messages[${index}] is missing`, 'messages');
39
+ }
40
+ try {
41
+ (0, messages_1.mapStoredMessagesToChatMessages)([message]);
42
+ }
43
+ catch (error) {
44
+ throw (0, errors_js_1.validationError)(`messages[${index}] of type "${(0, truncate_js_1.truncateForLog)(message.type)}" cannot be stored: ` +
45
+ (0, secret_patterns_js_1.redactedMessage)(error), 'messages');
46
+ }
47
+ }
48
+ return stored;
49
+ }
50
+ function parseMessages(messages) {
51
+ if (!Array.isArray(messages)) {
52
+ throw (0, errors_js_1.validationError)('messages must be an array', 'messages');
53
+ }
54
+ return parseStoredMessages(toStoredMessages(messages));
55
+ }
56
+ function windowBound(before) {
57
+ const hasGetTime = before !== null && typeof before.getTime === 'function';
58
+ const time = hasGetTime ? before.getTime() : Number.NaN;
59
+ if (!Number.isFinite(time))
60
+ throw (0, errors_js_1.validationError)('before must be a valid Date', 'before');
61
+ if (time < 0 || time >= ulid_js_1.ULID_TIME_RANGE_MS) {
62
+ throw (0, errors_js_1.validationError)('before must be a Date from the epoch onwards and before the year 37648: the bound is ' +
63
+ 'the message id of that instant, and a message id encodes its millisecond in ten ' +
64
+ 'base-32 characters, which hold no instant outside that range', 'before');
65
+ }
66
+ return new Date(time);
67
+ }
68
+ function parseMessageWindow(window) {
69
+ const parsed = {};
70
+ if (window.limit !== undefined)
71
+ parsed.limit = (0, primitives_js_1.parseLimit)(window.limit, 1);
72
+ if (window.before !== undefined)
73
+ parsed.before = windowBound(window.before);
74
+ return parsed;
75
+ }
76
+ function parseGetMessagesRequest(sessionId, options) {
77
+ (0, option_shape_js_1.assertShape)(options, setup_js_1.GET_MESSAGES_KEYS, 'options');
78
+ (0, collaborators_js_1.assertSignalLike)(options.signal);
79
+ const parsedSessionId = parseSessionId(sessionId);
80
+ return {
81
+ sessionId: parsedSessionId,
82
+ window: parseMessageWindow(options),
83
+ signal: options.signal,
84
+ };
85
+ }
86
+ function scanCap(value, field) {
87
+ if (value === undefined || value === Infinity)
88
+ return value;
89
+ return (0, primitives_js_1.parseInteger)(value, field, { min: 1 });
90
+ }
91
+ function pageCursor(cursor, indexName) {
92
+ if (cursor === undefined)
93
+ return undefined;
94
+ if (indexName === undefined) {
95
+ throw (0, errors_js_1.validationError)('paging by cursor needs a configured `indexName`: without the recency index a listing is ' +
96
+ 'one table scan, which has no position to resume from', 'cursor');
97
+ }
98
+ return (0, primitives_js_1.parseString)(cursor, 'cursor');
99
+ }
100
+ function parseListSessionsRequest(options, indexName) {
101
+ (0, option_shape_js_1.assertShape)(options, setup_js_1.LIST_SESSIONS_KEYS, 'options');
102
+ (0, collaborators_js_1.assertSignalLike)(options.signal);
103
+ const limit = options.limit === undefined ? undefined : (0, primitives_js_1.parseLimit)(options.limit, 0);
104
+ const maxItems = scanCap(options.maxItems, 'maxItems');
105
+ const maxIterations = scanCap(options.maxIterations, 'maxIterations');
106
+ return {
107
+ limit,
108
+ maxItems,
109
+ maxIterations,
110
+ cursor: pageCursor(options.cursor, indexName),
111
+ signal: options.signal,
112
+ };
113
+ }
@@ -10,11 +10,11 @@
10
10
  */
11
11
  import type { QueryCommandInput } from '@aws-sdk/lib-dynamodb';
12
12
  import type { StoredMessage } from '@langchain/core/messages';
13
- import { type PayloadDescriptor } from '../../shared/codec/codec';
14
- import type { AttributeMap } from '../../shared/dynamodb/client';
15
- import { type RowKey } from '../../shared/dynamodb/table-schema';
16
- import type { SessionId } from './parse';
17
- import type { HistoryContext } from './setup';
13
+ import { type PayloadDescriptor } from '../../shared/codec/codec.js';
14
+ import type { AttributeMap } from '../../shared/dynamodb/client.js';
15
+ import { type RowKey } from '../../shared/dynamodb/table-schema.js';
16
+ import type { SessionId } from './parse.js';
17
+ import type { HistoryContext } from './setup.js';
18
18
  /** Fixed sort key for the per-session metadata item. */
19
19
  export declare const SESSION_SORT_KEY = "HISTORY#SESSION";
20
20
  /**
@@ -161,14 +161,15 @@ export interface MessageRowSource {
161
161
  * than losing its oldest turns first. `signal` — cancels the upload an
162
162
  * offloaded message costs.
163
163
  *
164
- * Returns: the row, keyed by the session partition and a `MSG#<messageId>` sort
165
- * key, its payload inline or offloaded to
164
+ * Returns: the row, keyed by the session partition and a
165
+ * `HISTORY#MSG#<messageId>` sort key, its payload inline or offloaded to
166
166
  * `<keyPrefix><sessionId, base64url>/<messageId>.bin`.
167
167
  *
168
168
  * Throws: `VALIDATION` naming `value` for a message the serializer cannot
169
- * represent; `S3_OFFLOAD_FAILED` when an offloaded payload cannot be uploaded.
170
- * Encoding precedes the transaction, so a message that cannot be stored never
171
- * half-writes a turn.
169
+ * represent, or `payload` for one too large to store inline without `s3`,
170
+ * or, once offloaded, larger than `s3.maxDownloadBytes`; `S3_OFFLOAD_FAILED`
171
+ * when an offloaded payload cannot be uploaded. Encoding precedes the
172
+ * transaction, so a message that cannot be stored never half-writes a turn.
172
173
  */
173
174
  export declare function buildMessageRow(context: HistoryContext, source: MessageRowSource, signal?: AbortSignal): Promise<MessageRow>;
174
175
  /**
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SESSION_SORT_KEY = void 0;
4
+ exports.historyPartitionPrefix = historyPartitionPrefix;
5
+ exports.sessionPartition = sessionPartition;
6
+ exports.sessionRowKey = sessionRowKey;
7
+ exports.messageSortKey = messageSortKey;
8
+ exports.isHistorySortKey = isHistorySortKey;
9
+ exports.messageSortKeyPrefix = messageSortKeyPrefix;
10
+ exports.sessionRowsQuery = sessionRowsQuery;
11
+ exports.messageQuery = messageQuery;
12
+ exports.buildMessageRow = buildMessageRow;
13
+ exports.parseMessageRow = parseMessageRow;
14
+ const codec_js_1 = require("../../shared/codec/codec.js");
15
+ const table_schema_js_1 = require("../../shared/dynamodb/table-schema.js");
16
+ const ADAPTER_PREFIX = `HISTORY${table_schema_js_1.KEY_SEPARATOR}`;
17
+ exports.SESSION_SORT_KEY = `${ADAPTER_PREFIX}SESSION`;
18
+ const MESSAGE_PREFIX = `${ADAPTER_PREFIX}MSG${table_schema_js_1.KEY_SEPARATOR}`;
19
+ const ADAPTER_PARTITION_PREFIX = `${table_schema_js_1.ADAPTER_TAGS.history}${table_schema_js_1.KEY_SEPARATOR}`;
20
+ function historyPartitionPrefix() {
21
+ return ADAPTER_PARTITION_PREFIX;
22
+ }
23
+ function sessionPartition(sessionId) {
24
+ return `${ADAPTER_PARTITION_PREFIX}${sessionId}`;
25
+ }
26
+ function sessionRowKey(sessionId) {
27
+ return { PK: sessionPartition(sessionId), SK: exports.SESSION_SORT_KEY };
28
+ }
29
+ function messageSortKey(ulid) {
30
+ return `${MESSAGE_PREFIX}${ulid}`;
31
+ }
32
+ function isHistorySortKey(sortKey) {
33
+ return sortKey.startsWith(ADAPTER_PREFIX);
34
+ }
35
+ function messageSortKeyPrefix() {
36
+ return MESSAGE_PREFIX;
37
+ }
38
+ function sessionRowsQuery(tableName, sessionId, options = {}) {
39
+ const params = {
40
+ TableName: tableName,
41
+ KeyConditionExpression: '#pk = :pk',
42
+ ExpressionAttributeNames: { '#pk': table_schema_js_1.PARTITION_KEY_ATTRIBUTE },
43
+ ExpressionAttributeValues: { ':pk': sessionPartition(sessionId) },
44
+ };
45
+ if (options.consistent)
46
+ params.ConsistentRead = true;
47
+ return params;
48
+ }
49
+ function messageQuery(tableName, sessionId, options = {}) {
50
+ const params = {
51
+ TableName: tableName,
52
+ KeyConditionExpression: '#pk = :pk AND begins_with(#sk, :skp)',
53
+ ExpressionAttributeNames: { '#pk': table_schema_js_1.PARTITION_KEY_ATTRIBUTE, '#sk': table_schema_js_1.SORT_KEY_ATTRIBUTE },
54
+ ExpressionAttributeValues: {
55
+ ':pk': sessionPartition(sessionId),
56
+ ':skp': messageSortKeyPrefix(),
57
+ },
58
+ ScanIndexForward: !options.descending,
59
+ };
60
+ if (options.beforeSortKey !== undefined) {
61
+ params.KeyConditionExpression = '#pk = :pk AND #sk BETWEEN :skp AND :before';
62
+ params.ExpressionAttributeValues[':before'] = options.beforeSortKey;
63
+ }
64
+ if (options.limit !== undefined)
65
+ params.Limit = options.limit;
66
+ if (options.consistent)
67
+ params.ConsistentRead = true;
68
+ return params;
69
+ }
70
+ async function buildMessageRow(context, source, signal) {
71
+ const { sessionId, messageId, message, ttlTimestamp } = source;
72
+ const pk = sessionPartition(sessionId);
73
+ const sk = messageSortKey(messageId);
74
+ const descriptor = await (0, codec_js_1.encodePayload)(message, (0, codec_js_1.codecDepsOf)(context, signal), {
75
+ keyParts: [sessionId],
76
+ objectId: messageId,
77
+ row: { pk, sk },
78
+ });
79
+ const item = {
80
+ PK: pk,
81
+ SK: sk,
82
+ v: table_schema_js_1.ROW_FORMAT_VERSION,
83
+ sessionId,
84
+ message: descriptor,
85
+ };
86
+ if (ttlTimestamp !== undefined)
87
+ item.ttl = ttlTimestamp;
88
+ return item;
89
+ }
90
+ function parseMessageRow(raw) {
91
+ const shaped = typeof raw.sessionId === 'string' && typeof raw.message === 'object' && raw.message !== null;
92
+ if (!shaped)
93
+ return undefined;
94
+ const item = raw;
95
+ return item.PK === sessionPartition(item.sessionId) ? item : undefined;
96
+ }
@@ -14,11 +14,11 @@
14
14
  * backfill writes the keys onto it directly, for a row that predates the index.
15
15
  */
16
16
  import type { StoredMessage } from '@langchain/core/messages';
17
- import type { AttributeMap, TransactAction } from '../../shared/dynamodb/client';
18
- import { type IndexTarget } from '../../shared/dynamodb/recency-index';
19
- import type { SessionMetadata } from '../types';
20
- import type { SessionId } from './parse';
21
- import type { HistoryContext } from './setup';
17
+ import type { AttributeMap, TransactAction } from '../../shared/dynamodb/client.js';
18
+ import { type IndexTarget } from '../../shared/dynamodb/recency-index.js';
19
+ import type { SessionMetadata } from '../types.js';
20
+ import type { SessionId } from './parse.js';
21
+ import type { HistoryContext } from './setup.js';
22
22
  /**
23
23
  * Subtract a count this append already added from the session, leaving it consistent.
24
24
  * Guarded so a concurrently-deleted SESSION row is never resurrected as a
@@ -154,6 +154,15 @@ export interface SessionUpdateFields {
154
154
  title?: string;
155
155
  ttlTimestamp?: number;
156
156
  forceTtlRefresh?: boolean;
157
+ /**
158
+ * The expired `ttl` anchor the stored session row carries, when it does:
159
+ * that row is a dead incarnation every reader already hides, so this update
160
+ * starts the session over — count, creation time and title are this
161
+ * append's — pinned to that anchor, so of two appends restarting one
162
+ * session the second loses the pin and adds to the first on its retry. Set
163
+ * on an append's first chunk only, by {@link appendChunks}.
164
+ */
165
+ restart?: number;
157
166
  }
158
167
  /**
159
168
  * Build the metadata `Update` transact-item: `ADD` the message count and `SET`
@@ -170,13 +179,21 @@ export interface SessionUpdateFields {
170
179
  * caller's already-healed anchor can never be regressed backward — see
171
180
  * append.ts for how a lost race is retried without forcing.
172
181
  *
182
+ * When `restart` names the expired anchor the row carries, the update starts
183
+ * the session over instead: the count is `SET` to this append's, `createdAt`
184
+ * and `sessionId` are written outright, the title is this append's or removed,
185
+ * and the whole item is pinned to that expired anchor. The dead incarnation's
186
+ * title and creation time would otherwise be served for the new conversation
187
+ * — a `listSessions` row titled after a conversation that expired — and its
188
+ * count would carry over, for as long as DynamoDB's sweep left the row.
189
+ *
173
190
  * Accepts: `count` — how many messages this append adds, which `ADD` applies to
174
191
  * whatever the row holds, so two concurrent appends both count. `title` —
175
192
  * written once and never overwritten, so a session keeps the title its first
176
193
  * turn produced. `writeId` — the appending write's own id, rewritten on every
177
194
  * append so the row always names the write that last added to it.
178
- * `ttlTimestamp` — absent leaves the row without an expiry. `forceTtlRefresh` —
179
- * see above.
195
+ * `ttlTimestamp` — absent leaves the row without an expiry. `forceTtlRefresh`
196
+ * and `restart` — see above.
180
197
  *
181
198
  * Returns: the `Update` transact-item. It creates the row when there is none:
182
199
  * every once-only field is an `if_not_exists`, so the first append and the
@@ -191,11 +208,11 @@ export declare function buildSessionUpdate(tableName: string, fields: SessionUpd
191
208
  * row itself could not be deleted because a concurrent append has since added
192
209
  * messages to it.
193
210
  *
194
- * Without this, that narrow window reopens exactly the leak C4 closes: the
195
- * title is derived from the first human message of an append the caller was
196
- * told had failed, and `if_not_exists` means nothing ever overwrites it — so
197
- * a row that now belongs to a different caller keeps up to 80 characters of
198
- * rolled-back message content.
211
+ * Without this, that narrow window reopens the leak that deleting the row
212
+ * closes: the title is derived from the first human message of an append the
213
+ * caller was told had failed, and `if_not_exists` means nothing ever
214
+ * overwrites it — so a row that now belongs to a different caller keeps up to
215
+ * 80 characters of rolled-back message content.
199
216
  *
200
217
  * Both guards are load-bearing. `createdAt = :now` establishes that this call
201
218
  * created the row, and `title = :title` that the title on it is still the one
@@ -216,6 +233,8 @@ export declare function removeRolledBackTitle(context: HistoryContext, sessionId
216
233
  export interface TtlAnchorResult {
217
234
  ttlTimestamp: number;
218
235
  refresh: boolean;
236
+ /** The expired anchor the SESSION row carries, when it carries one: a dead incarnation to start over. */
237
+ expiredAnchor?: number;
219
238
  }
220
239
  /**
221
240
  * Resolve the session's creation-anchored TTL: the value already stored on the
@@ -226,20 +245,20 @@ export interface TtlAnchorResult {
226
245
  * This is a strongly-consistent read, never a write, so it cannot leave a
227
246
  * metadata-only orphan row when the following append transaction fails.
228
247
  *
229
- * When a stale anchor is healed, only the persisted SESSION row's `ttl` is
230
- * force-refreshed — the message rows already written under the expired
231
- * anchor keep their own (already-expired) `ttl` and get swept independently
232
- * by DynamoDB's TTL sweep. Until that sweep runs (and until
233
- * `reconcileMessageCount` repairs the count), `messageCount` can therefore be
234
- * temporarily overstated relative to what `getMessages` actually returns.
235
- * This is expected, not a bug.
248
+ * An anchor that has passed is handed back as `expiredAnchor`: the stored
249
+ * session is then a dead incarnation — every reader already hides it and its
250
+ * messages — and the append starts the session over, pinned to that anchor
251
+ * (see {@link buildSessionUpdate}). The message rows written under the expired
252
+ * anchor keep their own, expired `ttl` and are swept independently by
253
+ * DynamoDB; nothing reads them in the meantime.
236
254
  *
237
255
  * Accepts: `candidate` — the anchor this append would use if the session has
238
256
  * none, already computed from the configured ttl.
239
257
  *
240
- * Returns: the anchor to stamp on this append's messages, and whether the
241
- * SESSION row's own `ttl` must be force-overwritten rather than left to
242
- * `if_not_exists`.
258
+ * Returns: the anchor to stamp on this append's messages, whether the SESSION
259
+ * row's own `ttl` must be force-overwritten rather than left to
260
+ * `if_not_exists`, and the expired anchor it replaces when the row carries
261
+ * one.
243
262
  *
244
263
  * Throws: whatever the read throws after retries.
245
264
  *
@@ -0,0 +1,296 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.revertSessionCount = revertSessionCount;
4
+ exports.revertSessionCreation = revertSessionCreation;
5
+ exports.buildSessionUpdate = buildSessionUpdate;
6
+ exports.removeRolledBackTitle = removeRolledBackTitle;
7
+ exports.resolveTtlAnchor = resolveTtlAnchor;
8
+ exports.deriveTitle = deriveTitle;
9
+ exports.repairMessageCount = repairMessageCount;
10
+ exports.summariseSession = summariseSession;
11
+ exports.sessionIndexTarget = sessionIndexTarget;
12
+ const clock_js_1 = require("../../shared/clock.js");
13
+ const cancellation_js_1 = require("../../shared/dynamodb/cancellation.js");
14
+ const idempotent_write_js_1 = require("../../shared/dynamodb/idempotent-write.js");
15
+ const recency_index_js_1 = require("../../shared/dynamodb/recency-index.js");
16
+ const retry_js_1 = require("../../shared/dynamodb/retry.js");
17
+ const table_schema_js_1 = require("../../shared/dynamodb/table-schema.js");
18
+ const classify_js_1 = require("../../shared/errors/classify.js");
19
+ const error_code_js_1 = require("../../shared/errors/error-code.js");
20
+ const errors_js_1 = require("../../shared/errors/errors.js");
21
+ const message_read_js_1 = require("./message-read.js");
22
+ const rows_js_1 = require("./rows.js");
23
+ function isCancelledByCondition(error) {
24
+ return (0, cancellation_js_1.conditionFailedAt)(error, 0);
25
+ }
26
+ async function revertSessionCount(context, sessionId, delta, createdBefore) {
27
+ if (delta === 0)
28
+ return;
29
+ const update = {
30
+ TableName: context.tableName,
31
+ Key: (0, rows_js_1.sessionRowKey)(sessionId),
32
+ UpdateExpression: 'ADD #count :neg',
33
+ ConditionExpression: `attribute_exists(${table_schema_js_1.PARTITION_KEY_ATTRIBUTE}) AND #c <= :now`,
34
+ ExpressionAttributeNames: { '#count': 'messageCount', '#c': 'createdAt' },
35
+ ExpressionAttributeValues: { ':neg': -delta, ':now': createdBefore },
36
+ };
37
+ try {
38
+ await (0, idempotent_write_js_1.transactIdempotently)(context, [{ Update: update }]);
39
+ }
40
+ catch (error) {
41
+ if (isCancelledByCondition(error))
42
+ return;
43
+ throw error;
44
+ }
45
+ }
46
+ async function revertSessionCreation(context, sessionId, created) {
47
+ if (created.total === 0)
48
+ return;
49
+ try {
50
+ await (0, idempotent_write_js_1.transactIdempotently)(context, [
51
+ {
52
+ Delete: {
53
+ TableName: context.tableName,
54
+ Key: (0, rows_js_1.sessionRowKey)(sessionId),
55
+ ConditionExpression: '#count = :total AND #c = :now',
56
+ ExpressionAttributeNames: { '#count': 'messageCount', '#c': 'createdAt' },
57
+ ExpressionAttributeValues: { ':total': created.total, ':now': created.createdAt },
58
+ },
59
+ },
60
+ ]);
61
+ return;
62
+ }
63
+ catch (error) {
64
+ if (!isCancelledByCondition(error))
65
+ throw error;
66
+ }
67
+ await revertSessionCount(context, sessionId, created.total, created.createdAt);
68
+ if (created.title !== undefined) {
69
+ await removeRolledBackTitle(context, sessionId, created.createdAt, created.title);
70
+ }
71
+ }
72
+ function buildSessionUpdate(tableName, fields) {
73
+ const index = (0, recency_index_js_1.indexKeys)('SESS', fields.sessionId, fields.now, fields.indexShards ?? recency_index_js_1.DEFAULT_INDEX_SHARDS);
74
+ const names = {
75
+ '#count': 'messageCount',
76
+ '#u': 'updatedAt',
77
+ '#c': 'createdAt',
78
+ '#sid': 'sessionId',
79
+ '#wid': idempotent_write_js_1.WRITE_ID_ATTRIBUTE,
80
+ '#v': 'v',
81
+ '#gpk': recency_index_js_1.INDEX_PARTITION_ATTRIBUTE,
82
+ '#gsk': recency_index_js_1.INDEX_SORT_ATTRIBUTE,
83
+ };
84
+ const values = {
85
+ ':n': fields.count,
86
+ ':u': fields.now,
87
+ ':c': fields.now,
88
+ ':sid': fields.sessionId,
89
+ ':wid': fields.writeId,
90
+ ':v': table_schema_js_1.ROW_FORMAT_VERSION,
91
+ ':gpk': index.gsi1pk,
92
+ ':gsk': index.gsi1sk,
93
+ };
94
+ const restarting = fields.restart !== undefined && fields.ttlTimestamp !== undefined;
95
+ const sets = [
96
+ '#u = :u',
97
+ restarting ? '#c = :c' : '#c = if_not_exists(#c, :c)',
98
+ restarting ? '#sid = :sid' : '#sid = if_not_exists(#sid, :sid)',
99
+ '#wid = :wid',
100
+ '#v = :v',
101
+ '#gpk = :gpk',
102
+ '#gsk = :gsk',
103
+ ];
104
+ let removes = '';
105
+ if (fields.title !== undefined) {
106
+ names['#title'] = 'title';
107
+ values[':title'] = fields.title;
108
+ sets.push(restarting ? '#title = :title' : '#title = if_not_exists(#title, :title)');
109
+ }
110
+ else if (restarting) {
111
+ names['#title'] = 'title';
112
+ removes = ' REMOVE #title';
113
+ }
114
+ let conditionExpression;
115
+ if (fields.ttlTimestamp !== undefined) {
116
+ names['#ttl'] = 'ttl';
117
+ values[':ttl'] = fields.ttlTimestamp;
118
+ if (restarting) {
119
+ sets.push('#ttl = :ttl');
120
+ values[':expired'] = fields.restart;
121
+ conditionExpression = '#ttl = :expired';
122
+ }
123
+ else if (fields.forceTtlRefresh) {
124
+ sets.push('#ttl = :ttl');
125
+ conditionExpression = 'attribute_not_exists(#ttl) OR #ttl <= :ttl';
126
+ }
127
+ else {
128
+ sets.push('#ttl = if_not_exists(#ttl, :ttl)');
129
+ }
130
+ }
131
+ const count = restarting ? 'SET #count = :n, ' : 'ADD #count :n SET ';
132
+ return {
133
+ Update: {
134
+ TableName: tableName,
135
+ Key: (0, rows_js_1.sessionRowKey)(fields.sessionId),
136
+ UpdateExpression: `${count}${sets.join(', ')}${removes}`,
137
+ ...(conditionExpression ? { ConditionExpression: conditionExpression } : {}),
138
+ ExpressionAttributeNames: names,
139
+ ExpressionAttributeValues: values,
140
+ },
141
+ };
142
+ }
143
+ function isConditionRejected(error) {
144
+ return (0, classify_js_1.classifyAwsError)(error) === error_code_js_1.ErrorCode.CONDITION_CONFLICT;
145
+ }
146
+ async function removeRolledBackTitle(context, sessionId, createdAt, title) {
147
+ try {
148
+ await (0, retry_js_1.withDynamoDBRetry)((request) => context.client.update({
149
+ TableName: context.tableName,
150
+ Key: (0, rows_js_1.sessionRowKey)(sessionId),
151
+ UpdateExpression: 'REMOVE #title',
152
+ ConditionExpression: '#c = :now AND #title = :title',
153
+ ExpressionAttributeNames: { '#title': 'title', '#c': 'createdAt' },
154
+ ExpressionAttributeValues: { ':now': createdAt, ':title': title },
155
+ }, request), context.retry);
156
+ }
157
+ catch (error) {
158
+ if (isConditionRejected(error))
159
+ return;
160
+ throw error;
161
+ }
162
+ }
163
+ async function resolveTtlAnchor(context, sessionId, candidate, signal) {
164
+ const result = await (0, retry_js_1.withDynamoDBRetry)((request) => context.client.get({
165
+ TableName: context.tableName,
166
+ Key: (0, rows_js_1.sessionRowKey)(sessionId),
167
+ ConsistentRead: true,
168
+ ProjectionExpression: '#ttl',
169
+ ExpressionAttributeNames: { '#ttl': 'ttl' },
170
+ }, request), (0, retry_js_1.retryFor)(context, signal));
171
+ const ttl = result.Item?.ttl;
172
+ if (typeof ttl !== 'number')
173
+ return { ttlTimestamp: candidate, refresh: true };
174
+ if (ttl > (0, clock_js_1.nowSeconds)())
175
+ return { ttlTimestamp: ttl, refresh: false };
176
+ return { ttlTimestamp: candidate, refresh: true, expiredAnchor: ttl };
177
+ }
178
+ const MAX_TITLE_LENGTH = 80;
179
+ function isTextBlock(block) {
180
+ const candidate = block;
181
+ return candidate.type === 'text' && typeof candidate.text === 'string';
182
+ }
183
+ function textOf(content) {
184
+ if (typeof content === 'string')
185
+ return content;
186
+ if (!Array.isArray(content))
187
+ return undefined;
188
+ const block = content.find((entry) => typeof entry === 'object' && entry !== null && isTextBlock(entry));
189
+ return block?.text;
190
+ }
191
+ function deriveTitle(messages) {
192
+ const firstHuman = messages.find((message) => message.type === 'human');
193
+ const content = firstHuman === undefined ? undefined : textOf(firstHuman.data.content);
194
+ if (content === undefined || content.length === 0)
195
+ return undefined;
196
+ const kept = [];
197
+ for (const codePoint of content) {
198
+ if (kept.length === MAX_TITLE_LENGTH)
199
+ return `${kept.slice(0, MAX_TITLE_LENGTH - 1).join('')}…`;
200
+ kept.push(codePoint);
201
+ }
202
+ return content;
203
+ }
204
+ async function observeCount(context, sessionId, signal) {
205
+ const result = await (0, retry_js_1.withDynamoDBRetry)((request) => context.client.get({
206
+ TableName: context.tableName,
207
+ Key: (0, rows_js_1.sessionRowKey)(sessionId),
208
+ ConsistentRead: true,
209
+ ProjectionExpression: '#count',
210
+ ExpressionAttributeNames: { '#count': 'messageCount' },
211
+ }, request), (0, retry_js_1.retryFor)(context, signal));
212
+ if (!result.Item)
213
+ return { exists: false };
214
+ const count = result.Item.messageCount;
215
+ return typeof count === 'number' ? { exists: true, count } : { exists: true };
216
+ }
217
+ function countGuard(observed) {
218
+ if (observed.count === undefined) {
219
+ return {
220
+ ConditionExpression: `attribute_exists(${table_schema_js_1.PARTITION_KEY_ATTRIBUTE}) AND attribute_not_exists(#count)`,
221
+ };
222
+ }
223
+ return {
224
+ ConditionExpression: `attribute_exists(${table_schema_js_1.PARTITION_KEY_ATTRIBUTE}) AND #count = :expected`,
225
+ ExpressionAttributeValues: { ':expected': observed.count },
226
+ };
227
+ }
228
+ async function writeCount(context, sessionId, repair, signal) {
229
+ const guard = countGuard(repair.observed);
230
+ await (0, retry_js_1.withDynamoDBRetry)((request) => context.client.update({
231
+ TableName: context.tableName,
232
+ Key: (0, rows_js_1.sessionRowKey)(sessionId),
233
+ UpdateExpression: 'SET #count = :count',
234
+ ExpressionAttributeNames: { '#count': 'messageCount' },
235
+ ExpressionAttributeValues: { ':count': repair.count, ...guard.ExpressionAttributeValues },
236
+ ConditionExpression: guard.ConditionExpression,
237
+ }, request), (0, retry_js_1.retryFor)(context, signal));
238
+ }
239
+ async function repairMessageCount(context, sessionId, signal) {
240
+ for (let attempt = 1; attempt <= idempotent_write_js_1.OVERWRITE_CAS_MAX_ATTEMPTS; attempt++) {
241
+ const observed = await observeCount(context, sessionId, signal);
242
+ if (!observed.exists) {
243
+ throw (0, errors_js_1.conflictError)(`Cannot reconcile messageCount: session "${sessionId}" does not exist`);
244
+ }
245
+ const count = await (0, message_read_js_1.countLiveMessages)(context, sessionId, signal);
246
+ try {
247
+ await writeCount(context, sessionId, { count, observed }, signal);
248
+ return count;
249
+ }
250
+ catch (error) {
251
+ if (!isConditionRejected(error))
252
+ throw error;
253
+ }
254
+ }
255
+ throw (0, errors_js_1.conflictError)(`Cannot reconcile messageCount: session "${sessionId}" changed during every one of ` +
256
+ `${idempotent_write_js_1.OVERWRITE_CAS_MAX_ATTEMPTS} attempts; retry when it is quieter`);
257
+ }
258
+ function hasReadableTtl(ttl) {
259
+ if (ttl === undefined)
260
+ return true;
261
+ return typeof ttl === 'number' && Number.isFinite(new Date(ttl * 1000).getTime());
262
+ }
263
+ function isSummarisable(raw) {
264
+ return (typeof raw.messageCount === 'number' &&
265
+ typeof raw.createdAt === 'string' &&
266
+ typeof raw.updatedAt === 'string' &&
267
+ (raw.title === undefined || typeof raw.title === 'string') &&
268
+ hasReadableTtl(raw.ttl));
269
+ }
270
+ function summariseSession(raw, atSeconds) {
271
+ const item = raw;
272
+ (0, table_schema_js_1.assertReadableRow)(item, 'session');
273
+ if (item.SK !== rows_js_1.SESSION_SORT_KEY || typeof item.sessionId !== 'string')
274
+ return undefined;
275
+ if (item.PK !== (0, rows_js_1.sessionPartition)(item.sessionId))
276
+ return undefined;
277
+ if (!isSummarisable(raw) || (0, table_schema_js_1.isExpiredRow)(item, atSeconds))
278
+ return undefined;
279
+ return {
280
+ sessionId: item.sessionId,
281
+ title: item.title,
282
+ messageCount: item.messageCount,
283
+ createdAt: item.createdAt,
284
+ updatedAt: item.updatedAt,
285
+ expiresAt: item.ttl === undefined ? undefined : new Date(item.ttl * 1000).toISOString(),
286
+ };
287
+ }
288
+ function sessionIndexTarget(row) {
289
+ const pk = typeof row.PK === 'string' ? row.PK : '';
290
+ const sk = typeof row.SK === 'string' ? row.SK : '';
291
+ if (!pk.startsWith((0, rows_js_1.historyPartitionPrefix)()))
292
+ return undefined;
293
+ return sk.endsWith('SESSION') && typeof row.sessionId === 'string'
294
+ ? { tag: 'SESS', id: row.sessionId, at: (0, recency_index_js_1.backfilledAt)(row.updatedAt) }
295
+ : undefined;
296
+ }
@@ -8,8 +8,8 @@
8
8
  * context every action receives.
9
9
  */
10
10
  import type { SerializerProtocol } from '@langchain/langgraph-checkpoint';
11
- import { type AdapterCore, type AdapterShell } from '../../shared/adapter';
12
- import type { CorruptMessagePolicy, DynamoDBChatMessageHistoryOptions } from '../types';
11
+ import { type AdapterCore, type AdapterShell } from '../../shared/adapter.js';
12
+ import type { CorruptMessagePolicy, DynamoDBChatMessageHistoryOptions } from '../types.js';
13
13
  /**
14
14
  * Max attempts for the message-append transaction. It shares one session's
15
15
  * metadata row across every concurrent `addMessages` caller on that session,