@farukada/aws-langgraph-dynamodb-ts 1.0.0-rc.1 → 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 (608) hide show
  1. package/README.md +1820 -290
  2. package/dist/cjs/backfill/backfill.d.ts +171 -0
  3. package/dist/cjs/backfill/backfill.js +177 -0
  4. package/dist/cjs/checkpointer/actions/delete-thread.d.ts +50 -0
  5. package/dist/cjs/checkpointer/actions/delete-thread.js +26 -0
  6. package/dist/cjs/checkpointer/actions/get-tuple.d.ts +36 -0
  7. package/dist/cjs/checkpointer/actions/get-tuple.js +22 -0
  8. package/dist/cjs/checkpointer/actions/list.d.ts +55 -0
  9. package/dist/cjs/checkpointer/actions/list.js +70 -0
  10. package/dist/cjs/checkpointer/actions/put-writes.d.ts +49 -0
  11. package/dist/cjs/checkpointer/actions/put-writes.js +21 -0
  12. package/dist/cjs/checkpointer/actions/put.d.ts +95 -0
  13. package/dist/cjs/checkpointer/actions/put.js +79 -0
  14. package/dist/cjs/checkpointer/internal/delta-history.d.ts +124 -0
  15. package/dist/cjs/checkpointer/internal/delta-history.js +131 -0
  16. package/dist/cjs/checkpointer/internal/listing.d.ts +149 -0
  17. package/dist/cjs/checkpointer/internal/listing.js +104 -0
  18. package/dist/cjs/checkpointer/internal/parse.d.ts +298 -0
  19. package/dist/cjs/checkpointer/internal/parse.js +184 -0
  20. package/dist/cjs/checkpointer/internal/pending-writes.d.ts +314 -0
  21. package/dist/cjs/checkpointer/internal/pending-writes.js +241 -0
  22. package/dist/cjs/checkpointer/internal/read.d.ts +135 -0
  23. package/dist/cjs/checkpointer/internal/read.js +132 -0
  24. package/dist/cjs/checkpointer/internal/rows.d.ts +644 -0
  25. package/dist/cjs/checkpointer/internal/rows.js +356 -0
  26. package/dist/cjs/checkpointer/internal/setup.d.ts +47 -0
  27. package/dist/cjs/checkpointer/internal/setup.js +25 -0
  28. package/dist/cjs/checkpointer/saver.d.ts +306 -0
  29. package/dist/cjs/checkpointer/saver.js +56 -0
  30. package/dist/cjs/checkpointer/types.d.ts +51 -0
  31. package/dist/cjs/factory/factory.d.ts +154 -0
  32. package/dist/cjs/factory/factory.js +137 -0
  33. package/dist/{factory → cjs/factory}/types.d.ts +33 -14
  34. package/dist/cjs/history/actions/add-messages.d.ts +51 -0
  35. package/dist/cjs/history/actions/add-messages.js +17 -0
  36. package/dist/cjs/history/actions/clear.d.ts +52 -0
  37. package/dist/cjs/history/actions/clear.js +29 -0
  38. package/dist/cjs/history/actions/get-messages.d.ts +60 -0
  39. package/dist/cjs/history/actions/get-messages.js +58 -0
  40. package/dist/cjs/history/actions/list-sessions.d.ts +55 -0
  41. package/dist/cjs/history/actions/list-sessions.js +67 -0
  42. package/dist/cjs/history/actions/reconcile-count.d.ts +49 -0
  43. package/dist/cjs/history/actions/reconcile-count.js +8 -0
  44. package/dist/cjs/history/chat-message-history.d.ts +267 -0
  45. package/dist/cjs/history/chat-message-history.js +61 -0
  46. package/dist/cjs/history/internal/append.d.ts +244 -0
  47. package/dist/cjs/history/internal/append.js +267 -0
  48. package/dist/cjs/history/internal/message-read.d.ts +84 -0
  49. package/dist/cjs/history/internal/message-read.js +93 -0
  50. package/dist/cjs/history/internal/parse.d.ts +153 -0
  51. package/dist/cjs/history/internal/parse.js +113 -0
  52. package/dist/cjs/history/internal/rows.d.ts +196 -0
  53. package/dist/cjs/history/internal/rows.js +96 -0
  54. package/dist/cjs/history/internal/session.d.ts +350 -0
  55. package/dist/cjs/history/internal/session.js +296 -0
  56. package/dist/cjs/history/internal/setup.d.ts +64 -0
  57. package/dist/cjs/history/internal/setup.js +60 -0
  58. package/dist/cjs/history/session-adapter.d.ts +112 -0
  59. package/dist/cjs/history/session-adapter.js +38 -0
  60. package/dist/cjs/history/types.d.ts +102 -0
  61. package/dist/cjs/index.d.ts +53 -0
  62. package/dist/cjs/index.js +25 -0
  63. package/dist/cjs/package.json +1 -0
  64. package/dist/cjs/shared/adapter.d.ts +146 -0
  65. package/dist/cjs/shared/adapter.js +70 -0
  66. package/dist/cjs/shared/clock.d.ts +52 -0
  67. package/dist/cjs/shared/clock.js +14 -0
  68. package/dist/cjs/shared/codec/codec.d.ts +336 -0
  69. package/dist/cjs/shared/codec/codec.js +162 -0
  70. package/dist/cjs/shared/codec/compression.d.ts +66 -0
  71. package/dist/cjs/shared/codec/compression.js +45 -0
  72. package/dist/cjs/shared/codec/json-serde.d.ts +80 -0
  73. package/dist/cjs/shared/codec/json-serde.js +58 -0
  74. package/dist/{shared → cjs/shared}/codec/s3/client-types.d.ts +22 -2
  75. package/dist/{shared → cjs/shared}/codec/s3/client-types.js +0 -1
  76. package/dist/cjs/shared/codec/s3/client.d.ts +63 -0
  77. package/dist/cjs/shared/codec/s3/client.js +78 -0
  78. package/dist/cjs/shared/codec/s3/config.d.ts +260 -0
  79. package/dist/cjs/shared/codec/s3/config.js +92 -0
  80. package/dist/cjs/shared/codec/s3/lifecycle.d.ts +220 -0
  81. package/dist/cjs/shared/codec/s3/lifecycle.js +223 -0
  82. package/dist/cjs/shared/codec/s3/offloader.d.ts +428 -0
  83. package/dist/cjs/shared/codec/s3/offloader.js +289 -0
  84. package/dist/cjs/shared/concurrency.d.ts +43 -0
  85. package/dist/{shared → cjs/shared}/concurrency.js +10 -9
  86. package/dist/cjs/shared/dynamodb/abort.d.ts +47 -0
  87. package/dist/cjs/shared/dynamodb/abort.js +16 -0
  88. package/dist/cjs/shared/dynamodb/batch-write.d.ts +86 -0
  89. package/dist/cjs/shared/dynamodb/batch-write.js +79 -0
  90. package/dist/cjs/shared/dynamodb/cancellation.d.ts +124 -0
  91. package/dist/cjs/shared/dynamodb/cancellation.js +37 -0
  92. package/dist/cjs/shared/dynamodb/client.d.ts +177 -0
  93. package/dist/{shared → cjs/shared}/dynamodb/client.js +12 -14
  94. package/dist/cjs/shared/dynamodb/idempotent-write.d.ts +596 -0
  95. package/dist/cjs/shared/dynamodb/idempotent-write.js +173 -0
  96. package/dist/cjs/shared/dynamodb/paginate.d.ts +111 -0
  97. package/dist/cjs/shared/dynamodb/paginate.js +90 -0
  98. package/dist/cjs/shared/dynamodb/partition-delete.d.ts +204 -0
  99. package/dist/cjs/shared/dynamodb/partition-delete.js +177 -0
  100. package/dist/cjs/shared/dynamodb/recency-index.d.ts +243 -0
  101. package/dist/cjs/shared/dynamodb/recency-index.js +146 -0
  102. package/dist/cjs/shared/dynamodb/retry.d.ts +317 -0
  103. package/dist/cjs/shared/dynamodb/retry.js +193 -0
  104. package/dist/cjs/shared/dynamodb/row-size.d.ts +33 -0
  105. package/dist/cjs/shared/dynamodb/row-size.js +30 -0
  106. package/dist/cjs/shared/dynamodb/table-schema.d.ts +199 -0
  107. package/dist/cjs/shared/dynamodb/table-schema.js +52 -0
  108. package/dist/cjs/shared/errors/base-error.d.ts +231 -0
  109. package/dist/cjs/shared/errors/base-error.js +73 -0
  110. package/dist/cjs/shared/errors/boundary.d.ts +86 -0
  111. package/dist/cjs/shared/errors/boundary.js +61 -0
  112. package/dist/cjs/shared/errors/classify.d.ts +206 -0
  113. package/dist/cjs/shared/errors/classify.js +232 -0
  114. package/dist/cjs/shared/errors/error-code.d.ts +95 -0
  115. package/dist/{shared → cjs/shared}/errors/error-code.js +12 -2
  116. package/dist/cjs/shared/errors/errors.d.ts +233 -0
  117. package/dist/cjs/shared/errors/errors.js +123 -0
  118. package/dist/cjs/shared/logging/logger.d.ts +80 -0
  119. package/dist/cjs/shared/logging/logger.js +30 -0
  120. package/dist/cjs/shared/logging/redaction.d.ts +123 -0
  121. package/dist/cjs/shared/logging/redaction.js +145 -0
  122. package/dist/cjs/shared/logging/secret-patterns.d.ts +227 -0
  123. package/dist/cjs/shared/logging/secret-patterns.js +93 -0
  124. package/dist/cjs/shared/logging/truncate.d.ts +197 -0
  125. package/dist/cjs/shared/logging/truncate.js +31 -0
  126. package/dist/cjs/shared/options.d.ts +100 -0
  127. package/dist/cjs/shared/ulid.d.ts +80 -0
  128. package/dist/{shared → cjs/shared}/ulid.js +7 -21
  129. package/dist/cjs/shared/validation/collaborators.d.ts +160 -0
  130. package/dist/cjs/shared/validation/collaborators.js +79 -0
  131. package/dist/cjs/shared/validation/option-shape.d.ts +91 -0
  132. package/dist/cjs/shared/validation/option-shape.js +31 -0
  133. package/dist/cjs/shared/validation/options.d.ts +145 -0
  134. package/dist/cjs/shared/validation/options.js +166 -0
  135. package/dist/cjs/shared/validation/primitives.d.ts +292 -0
  136. package/dist/cjs/shared/validation/primitives.js +114 -0
  137. package/dist/cjs/shared/validation/ttl.d.ts +94 -0
  138. package/dist/cjs/shared/validation/ttl.js +52 -0
  139. package/dist/cjs/store/actions/list-namespaces.d.ts +79 -0
  140. package/dist/cjs/store/actions/list-namespaces.js +92 -0
  141. package/dist/cjs/store/actions/put.d.ts +43 -0
  142. package/dist/cjs/store/actions/put.js +49 -0
  143. package/dist/cjs/store/actions/reconcile-vector-index.d.ts +38 -0
  144. package/dist/cjs/store/actions/reconcile-vector-index.js +13 -0
  145. package/dist/cjs/store/actions/search.d.ts +38 -0
  146. package/dist/cjs/store/actions/search.js +26 -0
  147. package/dist/cjs/store/internal/batch-plan.d.ts +56 -0
  148. package/dist/cjs/store/internal/batch-plan.js +32 -0
  149. package/dist/cjs/store/internal/filter.d.ts +43 -0
  150. package/dist/cjs/store/internal/filter.js +64 -0
  151. package/dist/cjs/store/internal/get-item.d.ts +77 -0
  152. package/dist/cjs/store/internal/get-item.js +58 -0
  153. package/dist/cjs/store/internal/item-write.d.ts +270 -0
  154. package/dist/cjs/store/internal/item-write.js +181 -0
  155. package/dist/cjs/store/internal/parse.d.ts +230 -0
  156. package/dist/cjs/store/internal/parse.js +180 -0
  157. package/dist/cjs/store/internal/rows.d.ts +359 -0
  158. package/dist/cjs/store/internal/rows.js +166 -0
  159. package/dist/cjs/store/internal/semantic-search.d.ts +168 -0
  160. package/dist/{store/internal/text-path.js → cjs/store/internal/semantic-search.js} +92 -28
  161. package/dist/cjs/store/internal/setup.d.ts +96 -0
  162. package/dist/cjs/store/internal/setup.js +103 -0
  163. package/dist/cjs/store/internal/table-search.d.ts +100 -0
  164. package/dist/cjs/store/internal/table-search.js +123 -0
  165. package/dist/cjs/store/internal/vector-index.d.ts +258 -0
  166. package/dist/cjs/store/internal/vector-index.js +269 -0
  167. package/dist/cjs/store/store.d.ts +329 -0
  168. package/dist/cjs/store/store.js +97 -0
  169. package/dist/cjs/store/types.d.ts +111 -0
  170. package/dist/cjs/store/vector-backend.d.ts +104 -0
  171. package/dist/cjs/store/vector-backend.js +4 -0
  172. package/dist/esm/backfill/backfill.d.ts +171 -0
  173. package/dist/esm/backfill/backfill.js +170 -0
  174. package/dist/esm/checkpointer/actions/delete-thread.d.ts +50 -0
  175. package/dist/esm/checkpointer/actions/delete-thread.js +23 -0
  176. package/dist/esm/checkpointer/actions/get-tuple.d.ts +36 -0
  177. package/dist/esm/checkpointer/actions/get-tuple.js +19 -0
  178. package/dist/esm/checkpointer/actions/list.d.ts +55 -0
  179. package/dist/esm/checkpointer/actions/list.js +67 -0
  180. package/dist/esm/checkpointer/actions/put-writes.d.ts +49 -0
  181. package/dist/esm/checkpointer/actions/put-writes.js +18 -0
  182. package/dist/esm/checkpointer/actions/put.d.ts +95 -0
  183. package/dist/esm/checkpointer/actions/put.js +75 -0
  184. package/dist/esm/checkpointer/internal/delta-history.d.ts +124 -0
  185. package/dist/esm/checkpointer/internal/delta-history.js +126 -0
  186. package/dist/esm/checkpointer/internal/listing.d.ts +149 -0
  187. package/dist/esm/checkpointer/internal/listing.js +95 -0
  188. package/dist/esm/checkpointer/internal/parse.d.ts +298 -0
  189. package/dist/esm/checkpointer/internal/parse.js +169 -0
  190. package/dist/esm/checkpointer/internal/pending-writes.d.ts +314 -0
  191. package/dist/esm/checkpointer/internal/pending-writes.js +229 -0
  192. package/dist/esm/checkpointer/internal/read.d.ts +135 -0
  193. package/dist/esm/checkpointer/internal/read.js +125 -0
  194. package/dist/esm/checkpointer/internal/rows.d.ts +644 -0
  195. package/dist/esm/checkpointer/internal/rows.js +323 -0
  196. package/dist/esm/checkpointer/internal/setup.d.ts +47 -0
  197. package/dist/esm/checkpointer/internal/setup.js +21 -0
  198. package/dist/esm/checkpointer/saver.d.ts +306 -0
  199. package/dist/esm/checkpointer/saver.js +52 -0
  200. package/dist/esm/checkpointer/types.d.ts +51 -0
  201. package/dist/esm/checkpointer/types.js +1 -0
  202. package/dist/esm/factory/factory.d.ts +154 -0
  203. package/dist/esm/factory/factory.js +133 -0
  204. package/dist/esm/factory/types.d.ts +76 -0
  205. package/dist/esm/factory/types.js +1 -0
  206. package/dist/esm/history/actions/add-messages.d.ts +51 -0
  207. package/dist/esm/history/actions/add-messages.js +14 -0
  208. package/dist/esm/history/actions/clear.d.ts +52 -0
  209. package/dist/esm/history/actions/clear.js +26 -0
  210. package/dist/esm/history/actions/get-messages.d.ts +60 -0
  211. package/dist/esm/history/actions/get-messages.js +55 -0
  212. package/dist/esm/history/actions/list-sessions.d.ts +55 -0
  213. package/dist/esm/history/actions/list-sessions.js +64 -0
  214. package/dist/esm/history/actions/reconcile-count.d.ts +49 -0
  215. package/dist/esm/history/actions/reconcile-count.js +5 -0
  216. package/dist/esm/history/chat-message-history.d.ts +267 -0
  217. package/dist/esm/history/chat-message-history.js +57 -0
  218. package/dist/esm/history/internal/append.d.ts +244 -0
  219. package/dist/esm/history/internal/append.js +259 -0
  220. package/dist/esm/history/internal/message-read.d.ts +84 -0
  221. package/dist/esm/history/internal/message-read.js +89 -0
  222. package/dist/esm/history/internal/parse.d.ts +153 -0
  223. package/dist/esm/history/internal/parse.js +105 -0
  224. package/dist/esm/history/internal/rows.d.ts +196 -0
  225. package/dist/esm/history/internal/rows.js +83 -0
  226. package/dist/esm/history/internal/session.d.ts +350 -0
  227. package/dist/esm/history/internal/session.js +285 -0
  228. package/dist/esm/history/internal/setup.d.ts +64 -0
  229. package/dist/esm/history/internal/setup.js +56 -0
  230. package/dist/esm/history/session-adapter.d.ts +112 -0
  231. package/dist/esm/history/session-adapter.js +34 -0
  232. package/dist/esm/history/types.d.ts +102 -0
  233. package/dist/esm/history/types.js +1 -0
  234. package/dist/esm/index.d.ts +53 -0
  235. package/dist/esm/index.js +10 -0
  236. package/dist/esm/shared/adapter.d.ts +146 -0
  237. package/dist/esm/shared/adapter.js +65 -0
  238. package/dist/esm/shared/clock.d.ts +52 -0
  239. package/dist/esm/shared/clock.js +9 -0
  240. package/dist/esm/shared/codec/codec.d.ts +336 -0
  241. package/dist/esm/shared/codec/codec.js +150 -0
  242. package/dist/esm/shared/codec/compression.d.ts +66 -0
  243. package/dist/esm/shared/codec/compression.js +40 -0
  244. package/dist/esm/shared/codec/json-serde.d.ts +80 -0
  245. package/dist/esm/shared/codec/json-serde.js +54 -0
  246. package/dist/esm/shared/codec/s3/client-types.d.ts +54 -0
  247. package/dist/esm/shared/codec/s3/client-types.js +3 -0
  248. package/dist/esm/shared/codec/s3/client.d.ts +63 -0
  249. package/dist/esm/shared/codec/s3/client.js +40 -0
  250. package/dist/esm/shared/codec/s3/config.d.ts +260 -0
  251. package/dist/esm/shared/codec/s3/config.js +79 -0
  252. package/dist/esm/shared/codec/s3/lifecycle.d.ts +220 -0
  253. package/dist/esm/shared/codec/s3/lifecycle.js +214 -0
  254. package/dist/esm/shared/codec/s3/offloader.d.ts +428 -0
  255. package/dist/esm/shared/codec/s3/offloader.js +278 -0
  256. package/dist/esm/shared/concurrency.d.ts +43 -0
  257. package/dist/esm/shared/concurrency.js +27 -0
  258. package/dist/esm/shared/dynamodb/abort.d.ts +47 -0
  259. package/dist/esm/shared/dynamodb/abort.js +12 -0
  260. package/dist/esm/shared/dynamodb/batch-write.d.ts +86 -0
  261. package/dist/esm/shared/dynamodb/batch-write.js +74 -0
  262. package/dist/esm/shared/dynamodb/cancellation.d.ts +124 -0
  263. package/dist/esm/shared/dynamodb/cancellation.js +30 -0
  264. package/dist/esm/shared/dynamodb/client.d.ts +177 -0
  265. package/dist/esm/shared/dynamodb/client.js +35 -0
  266. package/dist/esm/shared/dynamodb/idempotent-write.d.ts +596 -0
  267. package/dist/esm/shared/dynamodb/idempotent-write.js +153 -0
  268. package/dist/esm/shared/dynamodb/paginate.d.ts +111 -0
  269. package/dist/esm/shared/dynamodb/paginate.js +84 -0
  270. package/dist/esm/shared/dynamodb/partition-delete.d.ts +204 -0
  271. package/dist/esm/shared/dynamodb/partition-delete.js +171 -0
  272. package/dist/esm/shared/dynamodb/recency-index.d.ts +243 -0
  273. package/dist/esm/shared/dynamodb/recency-index.js +136 -0
  274. package/dist/esm/shared/dynamodb/retry.d.ts +317 -0
  275. package/dist/esm/shared/dynamodb/retry.js +180 -0
  276. package/dist/esm/shared/dynamodb/row-size.d.ts +33 -0
  277. package/dist/esm/shared/dynamodb/row-size.js +26 -0
  278. package/dist/esm/shared/dynamodb/table-schema.d.ts +199 -0
  279. package/dist/esm/shared/dynamodb/table-schema.js +43 -0
  280. package/dist/esm/shared/errors/base-error.d.ts +231 -0
  281. package/dist/esm/shared/errors/base-error.js +64 -0
  282. package/dist/esm/shared/errors/boundary.d.ts +86 -0
  283. package/dist/esm/shared/errors/boundary.js +54 -0
  284. package/dist/esm/shared/errors/classify.d.ts +206 -0
  285. package/dist/esm/shared/errors/classify.js +220 -0
  286. package/dist/esm/shared/errors/error-code.d.ts +95 -0
  287. package/dist/esm/shared/errors/error-code.js +24 -0
  288. package/dist/esm/shared/errors/errors.d.ts +233 -0
  289. package/dist/esm/shared/errors/errors.js +110 -0
  290. package/dist/esm/shared/logging/logger.d.ts +80 -0
  291. package/dist/esm/shared/logging/logger.js +25 -0
  292. package/dist/esm/shared/logging/redaction.d.ts +123 -0
  293. package/dist/esm/shared/logging/redaction.js +140 -0
  294. package/dist/esm/shared/logging/secret-patterns.d.ts +227 -0
  295. package/dist/esm/shared/logging/secret-patterns.js +83 -0
  296. package/dist/esm/shared/logging/truncate.d.ts +197 -0
  297. package/dist/esm/shared/logging/truncate.js +25 -0
  298. package/dist/esm/shared/options.d.ts +100 -0
  299. package/dist/esm/shared/options.js +1 -0
  300. package/dist/esm/shared/ulid.d.ts +80 -0
  301. package/dist/esm/shared/ulid.js +77 -0
  302. package/dist/esm/shared/validation/collaborators.d.ts +160 -0
  303. package/dist/esm/shared/validation/collaborators.js +70 -0
  304. package/dist/esm/shared/validation/option-shape.d.ts +91 -0
  305. package/dist/esm/shared/validation/option-shape.js +24 -0
  306. package/dist/esm/shared/validation/options.d.ts +145 -0
  307. package/dist/esm/shared/validation/options.js +156 -0
  308. package/dist/esm/shared/validation/primitives.d.ts +292 -0
  309. package/dist/esm/shared/validation/primitives.js +100 -0
  310. package/dist/esm/shared/validation/ttl.d.ts +94 -0
  311. package/dist/esm/shared/validation/ttl.js +46 -0
  312. package/dist/esm/store/actions/list-namespaces.d.ts +79 -0
  313. package/dist/esm/store/actions/list-namespaces.js +86 -0
  314. package/dist/esm/store/actions/put.d.ts +43 -0
  315. package/dist/esm/store/actions/put.js +46 -0
  316. package/dist/esm/store/actions/reconcile-vector-index.d.ts +38 -0
  317. package/dist/esm/store/actions/reconcile-vector-index.js +10 -0
  318. package/dist/esm/store/actions/search.d.ts +38 -0
  319. package/dist/esm/store/actions/search.js +23 -0
  320. package/dist/esm/store/internal/batch-plan.d.ts +56 -0
  321. package/dist/esm/store/internal/batch-plan.js +28 -0
  322. package/dist/esm/store/internal/filter.d.ts +43 -0
  323. package/dist/esm/store/internal/filter.js +60 -0
  324. package/dist/esm/store/internal/get-item.d.ts +77 -0
  325. package/dist/esm/store/internal/get-item.js +54 -0
  326. package/dist/esm/store/internal/item-write.d.ts +270 -0
  327. package/dist/esm/store/internal/item-write.js +173 -0
  328. package/dist/esm/store/internal/parse.d.ts +230 -0
  329. package/dist/esm/store/internal/parse.js +169 -0
  330. package/dist/esm/store/internal/rows.d.ts +359 -0
  331. package/dist/esm/store/internal/rows.js +147 -0
  332. package/dist/esm/store/internal/semantic-search.d.ts +168 -0
  333. package/dist/esm/store/internal/semantic-search.js +200 -0
  334. package/dist/esm/store/internal/setup.d.ts +96 -0
  335. package/dist/esm/store/internal/setup.js +98 -0
  336. package/dist/esm/store/internal/table-search.d.ts +100 -0
  337. package/dist/esm/store/internal/table-search.js +119 -0
  338. package/dist/esm/store/internal/vector-index.d.ts +258 -0
  339. package/dist/esm/store/internal/vector-index.js +256 -0
  340. package/dist/esm/store/store.d.ts +329 -0
  341. package/dist/esm/store/store.js +93 -0
  342. package/dist/esm/store/types.d.ts +111 -0
  343. package/dist/esm/store/types.js +1 -0
  344. package/dist/esm/store/vector-backend.d.ts +104 -0
  345. package/dist/esm/store/vector-backend.js +1 -0
  346. package/package.json +68 -46
  347. package/dist/checkpointer/actions/delete-thread.d.ts +0 -10
  348. package/dist/checkpointer/actions/delete-thread.js +0 -38
  349. package/dist/checkpointer/actions/get-tuple.d.ts +0 -11
  350. package/dist/checkpointer/actions/get-tuple.js +0 -25
  351. package/dist/checkpointer/actions/list.d.ts +0 -20
  352. package/dist/checkpointer/actions/list.js +0 -113
  353. package/dist/checkpointer/actions/put-writes.d.ts +0 -15
  354. package/dist/checkpointer/actions/put-writes.js +0 -62
  355. package/dist/checkpointer/actions/put.d.ts +0 -17
  356. package/dist/checkpointer/actions/put.js +0 -73
  357. package/dist/checkpointer/internal/assemble.d.ts +0 -17
  358. package/dist/checkpointer/internal/assemble.js +0 -38
  359. package/dist/checkpointer/internal/checkpoint-write-verify.d.ts +0 -24
  360. package/dist/checkpointer/internal/checkpoint-write-verify.js +0 -67
  361. package/dist/checkpointer/internal/configurable.d.ts +0 -12
  362. package/dist/checkpointer/internal/configurable.js +0 -24
  363. package/dist/checkpointer/internal/fetch.d.ts +0 -19
  364. package/dist/checkpointer/internal/fetch.js +0 -88
  365. package/dist/checkpointer/internal/filter-match.d.ts +0 -13
  366. package/dist/checkpointer/internal/filter-match.js +0 -15
  367. package/dist/checkpointer/internal/item-reader.d.ts +0 -66
  368. package/dist/checkpointer/internal/item-reader.js +0 -113
  369. package/dist/checkpointer/internal/item-writer.d.ts +0 -35
  370. package/dist/checkpointer/internal/item-writer.js +0 -107
  371. package/dist/checkpointer/internal/keys.d.ts +0 -41
  372. package/dist/checkpointer/internal/keys.js +0 -117
  373. package/dist/checkpointer/internal/list-scope.d.ts +0 -61
  374. package/dist/checkpointer/internal/list-scope.js +0 -108
  375. package/dist/checkpointer/internal/pending-sends.d.ts +0 -13
  376. package/dist/checkpointer/internal/pending-sends.js +0 -29
  377. package/dist/checkpointer/internal/query.d.ts +0 -21
  378. package/dist/checkpointer/internal/query.js +0 -42
  379. package/dist/checkpointer/internal/regular-write.d.ts +0 -28
  380. package/dist/checkpointer/internal/regular-write.js +0 -66
  381. package/dist/checkpointer/internal/setup.d.ts +0 -33
  382. package/dist/checkpointer/internal/setup.js +0 -38
  383. package/dist/checkpointer/internal/special-write-cas.d.ts +0 -29
  384. package/dist/checkpointer/internal/special-write-cas.js +0 -104
  385. package/dist/checkpointer/internal/special-write-cleanup.d.ts +0 -23
  386. package/dist/checkpointer/internal/special-write-cleanup.js +0 -50
  387. package/dist/checkpointer/internal/special-write-verify.d.ts +0 -53
  388. package/dist/checkpointer/internal/special-write-verify.js +0 -80
  389. package/dist/checkpointer/internal/stored-channels.d.ts +0 -31
  390. package/dist/checkpointer/internal/stored-channels.js +0 -70
  391. package/dist/checkpointer/internal/validation.d.ts +0 -18
  392. package/dist/checkpointer/internal/validation.js +0 -40
  393. package/dist/checkpointer/internal/write-guard.d.ts +0 -20
  394. package/dist/checkpointer/internal/write-guard.js +0 -48
  395. package/dist/checkpointer/internal/write-index.d.ts +0 -36
  396. package/dist/checkpointer/internal/write-index.js +0 -41
  397. package/dist/checkpointer/saver.d.ts +0 -70
  398. package/dist/checkpointer/saver.js +0 -105
  399. package/dist/checkpointer/types.d.ts +0 -58
  400. package/dist/factory/factory.d.ts +0 -40
  401. package/dist/factory/factory.js +0 -87
  402. package/dist/history/actions/add-messages.d.ts +0 -15
  403. package/dist/history/actions/add-messages.js +0 -77
  404. package/dist/history/actions/clear.d.ts +0 -10
  405. package/dist/history/actions/clear.js +0 -34
  406. package/dist/history/actions/get-messages.d.ts +0 -17
  407. package/dist/history/actions/get-messages.js +0 -79
  408. package/dist/history/actions/list-sessions.d.ts +0 -13
  409. package/dist/history/actions/list-sessions.js +0 -53
  410. package/dist/history/actions/reconcile-count.d.ts +0 -12
  411. package/dist/history/actions/reconcile-count.js +0 -64
  412. package/dist/history/chat-message-history.d.ts +0 -73
  413. package/dist/history/chat-message-history.js +0 -111
  414. package/dist/history/internal/append-saga.d.ts +0 -25
  415. package/dist/history/internal/append-saga.js +0 -79
  416. package/dist/history/internal/compensation.d.ts +0 -25
  417. package/dist/history/internal/compensation.js +0 -92
  418. package/dist/history/internal/item-mapper.d.ts +0 -9
  419. package/dist/history/internal/item-mapper.js +0 -27
  420. package/dist/history/internal/keys.d.ts +0 -16
  421. package/dist/history/internal/keys.js +0 -48
  422. package/dist/history/internal/message-chunker.d.ts +0 -13
  423. package/dist/history/internal/message-chunker.js +0 -67
  424. package/dist/history/internal/message-transaction.d.ts +0 -25
  425. package/dist/history/internal/message-transaction.js +0 -61
  426. package/dist/history/internal/message-window.d.ts +0 -17
  427. package/dist/history/internal/message-window.js +0 -49
  428. package/dist/history/internal/query.d.ts +0 -23
  429. package/dist/history/internal/query.js +0 -39
  430. package/dist/history/internal/session-count.d.ts +0 -47
  431. package/dist/history/internal/session-count.js +0 -115
  432. package/dist/history/internal/session-title.d.ts +0 -19
  433. package/dist/history/internal/session-title.js +0 -43
  434. package/dist/history/internal/session-update.d.ts +0 -27
  435. package/dist/history/internal/session-update.js +0 -69
  436. package/dist/history/internal/setup.d.ts +0 -31
  437. package/dist/history/internal/setup.js +0 -43
  438. package/dist/history/internal/title-generator.d.ts +0 -12
  439. package/dist/history/internal/title-generator.js +0 -41
  440. package/dist/history/internal/ttl-anchor.d.ts +0 -24
  441. package/dist/history/internal/ttl-anchor.js +0 -38
  442. package/dist/history/internal/validation.d.ts +0 -25
  443. package/dist/history/internal/validation.js +0 -53
  444. package/dist/history/session-adapter.d.ts +0 -29
  445. package/dist/history/session-adapter.js +0 -35
  446. package/dist/history/types.d.ts +0 -69
  447. package/dist/index.d.ts +0 -29
  448. package/dist/index.js +0 -32
  449. package/dist/shared/clock.d.ts +0 -8
  450. package/dist/shared/clock.js +0 -16
  451. package/dist/shared/codec/codec.d.ts +0 -53
  452. package/dist/shared/codec/codec.js +0 -66
  453. package/dist/shared/codec/compression.d.ts +0 -24
  454. package/dist/shared/codec/compression.js +0 -48
  455. package/dist/shared/codec/descriptor-keys.d.ts +0 -12
  456. package/dist/shared/codec/descriptor-keys.js +0 -14
  457. package/dist/shared/codec/encode.d.ts +0 -13
  458. package/dist/shared/codec/encode.js +0 -43
  459. package/dist/shared/codec/json-serde.d.ts +0 -7
  460. package/dist/shared/codec/json-serde.js +0 -17
  461. package/dist/shared/codec/payload-loss.d.ts +0 -12
  462. package/dist/shared/codec/payload-loss.js +0 -38
  463. package/dist/shared/codec/s3/adapter-config.d.ts +0 -13
  464. package/dist/shared/codec/s3/adapter-config.js +0 -22
  465. package/dist/shared/codec/s3/bounded-body.d.ts +0 -14
  466. package/dist/shared/codec/s3/bounded-body.js +0 -47
  467. package/dist/shared/codec/s3/client.d.ts +0 -18
  468. package/dist/shared/codec/s3/client.js +0 -46
  469. package/dist/shared/codec/s3/config.d.ts +0 -51
  470. package/dist/shared/codec/s3/config.js +0 -58
  471. package/dist/shared/codec/s3/delete.d.ts +0 -7
  472. package/dist/shared/codec/s3/delete.js +0 -28
  473. package/dist/shared/codec/s3/key-scope.d.ts +0 -23
  474. package/dist/shared/codec/s3/key-scope.js +0 -44
  475. package/dist/shared/codec/s3/lifecycle.d.ts +0 -14
  476. package/dist/shared/codec/s3/lifecycle.js +0 -63
  477. package/dist/shared/codec/s3/offloader.d.ts +0 -44
  478. package/dist/shared/codec/s3/offloader.js +0 -118
  479. package/dist/shared/codec/s3/orphans.d.ts +0 -23
  480. package/dist/shared/codec/s3/orphans.js +0 -71
  481. package/dist/shared/codec/s3/read-write.d.ts +0 -18
  482. package/dist/shared/codec/s3/read-write.js +0 -51
  483. package/dist/shared/codec/s3/retry.d.ts +0 -5
  484. package/dist/shared/codec/s3/retry.js +0 -22
  485. package/dist/shared/concurrency.d.ts +0 -6
  486. package/dist/shared/constants.d.ts +0 -112
  487. package/dist/shared/constants.js +0 -115
  488. package/dist/shared/dynamodb/abort.d.ts +0 -9
  489. package/dist/shared/dynamodb/abort.js +0 -27
  490. package/dist/shared/dynamodb/backoff.d.ts +0 -15
  491. package/dist/shared/dynamodb/backoff.js +0 -48
  492. package/dist/shared/dynamodb/batch-write.d.ts +0 -22
  493. package/dist/shared/dynamodb/batch-write.js +0 -53
  494. package/dist/shared/dynamodb/cancellation.d.ts +0 -6
  495. package/dist/shared/dynamodb/cancellation.js +0 -7
  496. package/dist/shared/dynamodb/client.d.ts +0 -28
  497. package/dist/shared/dynamodb/conditional-put.d.ts +0 -67
  498. package/dist/shared/dynamodb/conditional-put.js +0 -76
  499. package/dist/shared/dynamodb/drain-unprocessed.d.ts +0 -21
  500. package/dist/shared/dynamodb/drain-unprocessed.js +0 -43
  501. package/dist/shared/dynamodb/expiry.d.ts +0 -16
  502. package/dist/shared/dynamodb/expiry.js +0 -29
  503. package/dist/shared/dynamodb/paginate-core.d.ts +0 -24
  504. package/dist/shared/dynamodb/paginate-core.js +0 -82
  505. package/dist/shared/dynamodb/paginate.d.ts +0 -14
  506. package/dist/shared/dynamodb/paginate.js +0 -19
  507. package/dist/shared/dynamodb/partition-delete.d.ts +0 -39
  508. package/dist/shared/dynamodb/partition-delete.js +0 -71
  509. package/dist/shared/dynamodb/retry-classifier.d.ts +0 -17
  510. package/dist/shared/dynamodb/retry-classifier.js +0 -118
  511. package/dist/shared/dynamodb/retry-policy.d.ts +0 -26
  512. package/dist/shared/dynamodb/retry-policy.js +0 -22
  513. package/dist/shared/dynamodb/retry.d.ts +0 -31
  514. package/dist/shared/dynamodb/retry.js +0 -57
  515. package/dist/shared/dynamodb/scan.d.ts +0 -14
  516. package/dist/shared/dynamodb/scan.js +0 -19
  517. package/dist/shared/dynamodb/types.d.ts +0 -23
  518. package/dist/shared/errors/base-error.d.ts +0 -30
  519. package/dist/shared/errors/base-error.js +0 -27
  520. package/dist/shared/errors/boundary.d.ts +0 -18
  521. package/dist/shared/errors/boundary.js +0 -46
  522. package/dist/shared/errors/error-code.d.ts +0 -13
  523. package/dist/shared/errors/errors.d.ts +0 -68
  524. package/dist/shared/errors/errors.js +0 -114
  525. package/dist/shared/errors/upstream-error.d.ts +0 -16
  526. package/dist/shared/errors/upstream-error.js +0 -27
  527. package/dist/shared/errors/wrap-error.d.ts +0 -7
  528. package/dist/shared/errors/wrap-error.js +0 -15
  529. package/dist/shared/logging/logger.d.ts +0 -18
  530. package/dist/shared/logging/logger.js +0 -15
  531. package/dist/shared/logging/redaction-walk.d.ts +0 -23
  532. package/dist/shared/logging/redaction-walk.js +0 -112
  533. package/dist/shared/logging/redaction.d.ts +0 -39
  534. package/dist/shared/logging/redaction.js +0 -75
  535. package/dist/shared/logging/secret-patterns.d.ts +0 -92
  536. package/dist/shared/logging/secret-patterns.js +0 -133
  537. package/dist/shared/options.d.ts +0 -37
  538. package/dist/shared/ulid.d.ts +0 -23
  539. package/dist/shared/validation/options.d.ts +0 -8
  540. package/dist/shared/validation/options.js +0 -90
  541. package/dist/shared/validation/primitives.d.ts +0 -29
  542. package/dist/shared/validation/primitives.js +0 -82
  543. package/dist/shared/validation/ttl.d.ts +0 -28
  544. package/dist/shared/validation/ttl.js +0 -52
  545. package/dist/store/actions/get.d.ts +0 -13
  546. package/dist/store/actions/get.js +0 -73
  547. package/dist/store/actions/list-namespaces.d.ts +0 -8
  548. package/dist/store/actions/list-namespaces.js +0 -59
  549. package/dist/store/actions/put.d.ts +0 -10
  550. package/dist/store/actions/put.js +0 -96
  551. package/dist/store/actions/reconcile-vector-index.d.ts +0 -18
  552. package/dist/store/actions/reconcile-vector-index.js +0 -26
  553. package/dist/store/actions/search.d.ts +0 -9
  554. package/dist/store/actions/search.js +0 -34
  555. package/dist/store/internal/backend-search.d.ts +0 -4
  556. package/dist/store/internal/backend-search.js +0 -74
  557. package/dist/store/internal/batch-plan.d.ts +0 -11
  558. package/dist/store/internal/batch-plan.js +0 -52
  559. package/dist/store/internal/candidates.d.ts +0 -23
  560. package/dist/store/internal/candidates.js +0 -94
  561. package/dist/store/internal/filter.d.ts +0 -9
  562. package/dist/store/internal/filter.js +0 -85
  563. package/dist/store/internal/index-reconcile.d.ts +0 -21
  564. package/dist/store/internal/index-reconcile.js +0 -118
  565. package/dist/store/internal/index-sync.d.ts +0 -10
  566. package/dist/store/internal/index-sync.js +0 -25
  567. package/dist/store/internal/item-mapper.d.ts +0 -27
  568. package/dist/store/internal/item-mapper.js +0 -61
  569. package/dist/store/internal/keys.d.ts +0 -17
  570. package/dist/store/internal/keys.js +0 -41
  571. package/dist/store/internal/namespace-match.d.ts +0 -11
  572. package/dist/store/internal/namespace-match.js +0 -40
  573. package/dist/store/internal/option-validation.d.ts +0 -13
  574. package/dist/store/internal/option-validation.js +0 -77
  575. package/dist/store/internal/overwrite-swap.d.ts +0 -32
  576. package/dist/store/internal/overwrite-swap.js +0 -68
  577. package/dist/store/internal/persist.d.ts +0 -28
  578. package/dist/store/internal/persist.js +0 -64
  579. package/dist/store/internal/query.d.ts +0 -11
  580. package/dist/store/internal/query.js +0 -48
  581. package/dist/store/internal/ranker.d.ts +0 -18
  582. package/dist/store/internal/ranker.js +0 -39
  583. package/dist/store/internal/read-existing.d.ts +0 -23
  584. package/dist/store/internal/read-existing.js +0 -41
  585. package/dist/store/internal/score-direction.d.ts +0 -31
  586. package/dist/store/internal/score-direction.js +0 -38
  587. package/dist/store/internal/search-filter.d.ts +0 -3
  588. package/dist/store/internal/search-filter.js +0 -10
  589. package/dist/store/internal/semantic-search.d.ts +0 -34
  590. package/dist/store/internal/semantic-search.js +0 -87
  591. package/dist/store/internal/setup.d.ts +0 -36
  592. package/dist/store/internal/setup.js +0 -40
  593. package/dist/store/internal/text-path.d.ts +0 -17
  594. package/dist/store/internal/validation.d.ts +0 -18
  595. package/dist/store/internal/validation.js +0 -51
  596. package/dist/store/internal/write-verify.d.ts +0 -42
  597. package/dist/store/internal/write-verify.js +0 -71
  598. package/dist/store/store.d.ts +0 -61
  599. package/dist/store/store.js +0 -107
  600. package/dist/store/types.d.ts +0 -50
  601. package/dist/store/types.js +0 -2
  602. package/dist/store/vector-backend.d.ts +0 -43
  603. package/dist/store/vector-backend.js +0 -2
  604. /package/dist/{checkpointer → cjs/checkpointer}/types.js +0 -0
  605. /package/dist/{factory → cjs/factory}/types.js +0 -0
  606. /package/dist/{history → cjs/history}/types.js +0 -0
  607. /package/dist/{shared → cjs/shared}/options.js +0 -0
  608. /package/dist/{shared/dynamodb → cjs/store}/types.js +0 -0
@@ -0,0 +1,350 @@
1
+ /**
2
+ * Hides the SESSION row: what it carries and how each field changes.
3
+ *
4
+ * A session's metadata — `messageCount`, `title`, `createdAt`, `updatedAt`,
5
+ * `ttl`, the `writeId` of the last append, and the recency-index keys — lives
6
+ * on one row, and `messageCount` is a copy of a fact the message rows hold.
7
+ * Keeping the copy in step is this module's job and nobody else's: the append
8
+ * adds to it in the same transaction that writes the messages, a rolled-back
9
+ * append subtracts exactly what it added (and never from a later incarnation of
10
+ * the session), a repair recomputes it under a compare-and-swap, and a listing
11
+ * reads it back only from a row this release can summarise. The recency-index
12
+ * keys are the one field this module does not write alone: `sessionIndexTarget`
13
+ * below tells `src/backfill/backfill.ts` which row is a SESSION row, and
14
+ * backfill writes the keys onto it directly, for a row that predates the index.
15
+ */
16
+ import type { StoredMessage } from '@langchain/core/messages';
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
+ /**
23
+ * Subtract a count this append already added from the session, leaving it consistent.
24
+ * Guarded so a concurrently-deleted SESSION row is never resurrected as a
25
+ * permanent, ttl-less junk row: if the row is already gone there is nothing
26
+ * to revert, so that specific condition failure is swallowed rather than
27
+ * surfaced — this runs only from an already-in-progress rollback, where a
28
+ * spurious error for a no-op would misrepresent what happened.
29
+ *
30
+ * The same condition also pins the *incarnation*: `createdAt <= createdBefore`
31
+ * (this call's own append timestamp). A session `clear()`-ed and re-created by
32
+ * another caller between this call's commit and its rollback carries a later
33
+ * `createdAt`; decrementing it would corrupt the new incarnation's count, and
34
+ * its rows were never this call's to revert. That rejection is swallowed too,
35
+ * for the same reason as a vanished row.
36
+ *
37
+ * Deliberately does not revert a `forceTtlRefresh`-driven ttl SET from an
38
+ * earlier committed chunk: the healed anchor is never shorter than what
39
+ * was there before, so leaving it in place after a rollback only means the
40
+ * session's metadata row outlives its content a bit longer than ideal —
41
+ * self-healing (the next successful append, or DynamoDB's own TTL sweep,
42
+ * resolves it), unlike reverting, which would need to re-check for a
43
+ * concurrent legitimate extension to avoid regressing it. See README.md's
44
+ * "TTL expiry" section.
45
+ *
46
+ * Accepts: `delta` — how many messages to subtract; `0` is a no-op and spends
47
+ * no write. `createdBefore` — this call's own append timestamp, which pins the
48
+ * incarnation.
49
+ *
50
+ * Returns: nothing, whether the decrement applied or the guard correctly
51
+ * refused it.
52
+ *
53
+ * Throws: whatever the write throws other than its own condition failure. A
54
+ * vanished row and a newer incarnation are both "nothing of mine to revert",
55
+ * not errors — this runs from an in-progress rollback, where a spurious error
56
+ * for a no-op would misrepresent what happened.
57
+ *
58
+ * Guarantees: the decrement is applied at most once, however often the request
59
+ * is re-sent. `ADD #count :neg` is one of the two writes in this package that
60
+ * are not naturally idempotent — the append's own `ADD #count :n` is the
61
+ * other — and applied twice it subtracts twice, with nothing reading the row
62
+ * back afterwards to notice, so a re-sent attempt must be answered from
63
+ * DynamoDB's idempotency cache rather than re-evaluated. Two things hold
64
+ * that together and only together: the `ClientRequestToken`, which makes a
65
+ * re-send a no-op, and the deadline of `MAX_WRITE_LIFETIME_MS`, which
66
+ * stops the retrying while that token is still honoured. Nothing in the token
67
+ * enforces that window — the service honours it for its own ten minutes
68
+ * whatever a caller's retry policy says — so without the deadline a long
69
+ * policy could still be retrying after the window closed, and the re-send
70
+ * would then land as a second subtraction, leaving `messageCount` quietly
71
+ * wrong. `reconcileMessageCount` is the repair if that happens anyway: it
72
+ * recounts the live messages and writes the true total back.
73
+ *
74
+ * The guard is no second line of defence for it. An attempt the condition
75
+ * turns away commits nothing, so DynamoDB caches no result for that attempt's
76
+ * token and a retry is a fresh evaluation rather than a deduplicated one — the
77
+ * exactly-once promise holds for an attempt that **committed**, which is also
78
+ * the only attempt whose re-send could subtract twice.
79
+ */
80
+ export declare function revertSessionCount(context: HistoryContext, sessionId: SessionId, delta: number, createdBefore: string): Promise<void>;
81
+ /** What a rolled-back append had created on the SESSION row, which the revert undoes. */
82
+ export interface CreatedSession {
83
+ /** Messages the append added to `messageCount`. */
84
+ readonly total: number;
85
+ /** The `createdAt` the append stamped, which pins the revert to that incarnation. */
86
+ readonly createdAt: string;
87
+ /** The title the append contributed, if it contributed one. */
88
+ readonly title?: string;
89
+ }
90
+ /**
91
+ * Undo a rolled-back append's effect on the session row.
92
+ *
93
+ * When this call is the one that created the row — `createdAt` still equals
94
+ * this call's timestamp, and the only messages counted on it are the ones
95
+ * being reverted — the whole row is deleted. Without that, a failed first
96
+ * append left a "ghost session": `title`, `createdAt` and `sessionId` are all
97
+ * written via `if_not_exists`, so they were never reverted and never set
98
+ * again, leaving `listSessions()` reporting a session with `messageCount: 0`
99
+ * whose title still held up to 80 characters of a message the caller was told
100
+ * had not persisted, with no API to clear it.
101
+ *
102
+ * Both conditions are load-bearing. `createdAt = :now` establishes that this
103
+ * call created the row; `messageCount = :total` establishes that nothing else
104
+ * has added to it since. A concurrent append to the same brand-new session
105
+ * fails the count check, because deleting the row would destroy that caller's
106
+ * committed messages — so it falls through to the plain decrement, and then
107
+ * strips just the title this call contributed, which is the only part of the
108
+ * row still carrying rolled-back message content.
109
+ *
110
+ * Accepts: `created` — what this call contributed to the row. `created.total`
111
+ * — every message this call counted onto the row; `0` is a no-op.
112
+ * `created.createdAt` — this call's timestamp, which is what "I created this
113
+ * row" means here. `created.title` — the title this call may have contributed.
114
+ *
115
+ * Returns: nothing. The row is deleted, or decremented and stripped of this
116
+ * call's title; both are a complete undo of what this call contributed.
117
+ *
118
+ * Throws: whatever the writes throw other than their own condition failures.
119
+ *
120
+ * Guarantees: the delete is applied at most once, and inside the window its
121
+ * token is honoured for, a re-send of an attempt that **committed** is
122
+ * answered from DynamoDB's idempotency cache rather than re-evaluated. The
123
+ * condition would already stop such a re-send from removing anything it should
124
+ * not; what the token adds is that it comes back as the success it was.
125
+ * Re-evaluated instead, it finds the row gone, fails both equalities, and the
126
+ * cancellation is read below as "a concurrent append has added to this row" —
127
+ * sending a rollback that already completed down the decrement-and-strip path
128
+ * meant for the case where the row survived. Both writes on that path are
129
+ * themselves guarded, and the decrement's incarnation pin refuses a session
130
+ * re-created in the meantime, so the price is two spurious conditional writes
131
+ * rather than a wrong count; the token is what keeps them from being spent.
132
+ *
133
+ * A rejection carries no idempotency forward — a cancelled attempt commits
134
+ * nothing, so nothing is cached for its token — and here that is exactly the
135
+ * wanted behaviour, since the fall-through below is a fresh decision about
136
+ * what to do instead. The deadline drawn beside the token is what keeps the
137
+ * retrying inside that window; the token enforces no window of its own.
138
+ */
139
+ export declare function revertSessionCreation(context: HistoryContext, sessionId: SessionId, created: CreatedSession): Promise<void>;
140
+ /** Fields driving the per-session metadata update inside the append transaction. */
141
+ export interface SessionUpdateFields {
142
+ sessionId: string;
143
+ /** Index partitions, from the adapter's context; see `indexKeys`. */
144
+ indexShards?: number;
145
+ /**
146
+ * The id of the append writing this update, drawn per chunk transaction by
147
+ * {@link writeMessageChunk}. It travels in the fields rather than being
148
+ * minted inside the builder, so an attempt rebuilt for a retry carries the
149
+ * id of the write it retries rather than a new one.
150
+ */
151
+ writeId: string;
152
+ count: number;
153
+ now: string;
154
+ title?: string;
155
+ ttlTimestamp?: number;
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;
166
+ }
167
+ /**
168
+ * Build the metadata `Update` transact-item: `ADD` the message count and `SET`
169
+ * `updatedAt` and the appending write's id every time, while `createdAt`,
170
+ * `sessionId`, `title`, and the `ttl` anchor are written once via
171
+ * `if_not_exists`. Folding the `ttl` anchor in here means the first append
172
+ * fixes one shared expiry atomically with the count, with no separate
173
+ * pre-write that could orphan a metadata-only row. When
174
+ * `forceTtlRefresh` is set (because {@link resolveTtlAnchor} found the persisted
175
+ * anchor missing or already expired), the `ttl` clause instead does a plain
176
+ * `SET`, so the SESSION row's own stale attribute actually heals instead of
177
+ * being permanently blocked by `if_not_exists`. When forceTtlRefresh is set,
178
+ * the SET is additionally guarded by a ConditionExpression so a concurrent
179
+ * caller's already-healed anchor can never be regressed backward — see
180
+ * append.ts for how a lost race is retried without forcing.
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
+ *
190
+ * Accepts: `count` — how many messages this append adds, which `ADD` applies to
191
+ * whatever the row holds, so two concurrent appends both count. `title` —
192
+ * written once and never overwritten, so a session keeps the title its first
193
+ * turn produced. `writeId` — the appending write's own id, rewritten on every
194
+ * append so the row always names the write that last added to it.
195
+ * `ttlTimestamp` — absent leaves the row without an expiry. `forceTtlRefresh`
196
+ * and `restart` — see above.
197
+ *
198
+ * Returns: the `Update` transact-item. It creates the row when there is none:
199
+ * every once-only field is an `if_not_exists`, so the first append and the
200
+ * thousandth build the same item.
201
+ *
202
+ * Throws: nothing. The condition it carries is evaluated by DynamoDB, and a
203
+ * failed condition surfaces from the transaction, not from here.
204
+ */
205
+ export declare function buildSessionUpdate(tableName: string, fields: SessionUpdateFields): TransactAction;
206
+ /**
207
+ * Strip a title this call contributed to a session row it created, when the
208
+ * row itself could not be deleted because a concurrent append has since added
209
+ * messages to it.
210
+ *
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.
216
+ *
217
+ * Both guards are load-bearing. `createdAt = :now` establishes that this call
218
+ * created the row, and `title = :title` that the title on it is still the one
219
+ * this call wrote — so a pre-existing title, or one a concurrent caller won
220
+ * the `if_not_exists` race for, is never removed. A condition rejection means
221
+ * exactly that and is not an error; anything else is.
222
+ *
223
+ * Accepts: `createdAt` — this call's own timestamp. `title` — the exact string
224
+ * this call wrote, compared as a value so nothing else's title is removed.
225
+ *
226
+ * Returns: nothing, whether the title was removed or the guards correctly
227
+ * refused.
228
+ *
229
+ * Throws: whatever the update throws other than its own condition failure.
230
+ */
231
+ export declare function removeRolledBackTitle(context: HistoryContext, sessionId: SessionId, createdAt: string, title: string): Promise<void>;
232
+ /** The resolved ttl anchor plus whether the persisted SESSION-row value must be force-refreshed. */
233
+ export interface TtlAnchorResult {
234
+ ttlTimestamp: number;
235
+ refresh: boolean;
236
+ /** The expired anchor the SESSION row carries, when it carries one: a dead incarnation to start over. */
237
+ expiredAnchor?: number;
238
+ }
239
+ /**
240
+ * Resolve the session's creation-anchored TTL: the value already stored on the
241
+ * SESSION item, if one exists AND is still in the future; otherwise the
242
+ * supplied `candidate`, with `refresh: true` so the caller force-overwrites
243
+ * the stale/missing persisted anchor instead of leaving it stuck (DynamoDB's
244
+ * `if_not_exists` would otherwise never correct an already-expired anchor).
245
+ * This is a strongly-consistent read, never a write, so it cannot leave a
246
+ * metadata-only orphan row when the following append transaction fails.
247
+ *
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.
254
+ *
255
+ * Accepts: `candidate` — the anchor this append would use if the session has
256
+ * none, already computed from the configured ttl.
257
+ *
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.
262
+ *
263
+ * Throws: whatever the read throws after retries.
264
+ *
265
+ * Guarantees: a read, never a write — so a failure of the append that follows
266
+ * cannot leave a metadata-only orphan row behind. Strongly consistent, so an
267
+ * anchor an earlier append committed is always seen. Two appends that start
268
+ * together on a session that has none each propose their own candidate; the
269
+ * append transaction's own condition is what settles which persists, so this
270
+ * read never has to be the arbiter (see {@link buildSessionUpdate}).
271
+ */
272
+ export declare function resolveTtlAnchor(context: HistoryContext, sessionId: SessionId, candidate: number, signal?: AbortSignal): Promise<TtlAnchorResult>;
273
+ /**
274
+ * Derive a session title from the first human message's text content, at most
275
+ * {@link MAX_TITLE_LENGTH} characters including the ellipsis. Returns undefined
276
+ * when there is no usable text.
277
+ *
278
+ * Truncation counts *code points*, not UTF-16 code units: slicing by index
279
+ * could cut a surrogate pair in half, leaving a lone surrogate that no longer
280
+ * round-trips through UTF-8. The ellipsis is also counted against the maximum
281
+ * rather than appended past it.
282
+ *
283
+ * Accepts: `messages` — one append's messages, in order. The first `human` one
284
+ * is the title's source; an append of only AI or tool messages has none, and an
285
+ * append to an existing session produces a title that is then discarded by
286
+ * `if_not_exists`.
287
+ *
288
+ * Returns: the title, or undefined when there is no usable text — no human
289
+ * message, empty content, or a multimodal message carrying no text block.
290
+ * Undefined means "do not write a title", not "write an empty one".
291
+ *
292
+ * Throws: nothing. A title is a convenience; nothing about it may fail an
293
+ * append.
294
+ */
295
+ export declare function deriveTitle(messages: StoredMessage[]): string | undefined;
296
+ /**
297
+ * Recompute `messageCount` from the stored message rows and write it, pinned to
298
+ * the count the row held when the recount began.
299
+ *
300
+ * Accepts: `sessionId` — parsed. `signal` — cancels the reads, the recount and
301
+ * the write.
302
+ *
303
+ * Returns: the count written.
304
+ *
305
+ * Throws: `CONDITION_CONFLICT` when the session does not exist, or when it
306
+ * changed during every one of the compare-and-swap's attempts;
307
+ * `FORMAT_UNSUPPORTED` for a message row a newer release wrote; `VALIDATION`
308
+ * naming `message` for a row in the message key space this package did not
309
+ * write; whatever the reads and the write throw.
310
+ */
311
+ export declare function repairMessageCount(context: HistoryContext, sessionId: SessionId, signal?: AbortSignal): Promise<number>;
312
+ /**
313
+ * The public summary of a SESSION row: the session a row describes, or
314
+ * undefined for a foreign, malformed or expired row.
315
+ *
316
+ * The `sessionId` is bound to the partition the row was found in, as
317
+ * `parseMetaRow`, `parseStoreRow` and `parseMessageRow` bind theirs.
318
+ * Both reads that reach here select rows by something other than the partition
319
+ * — a table scan filtered on the sort key, and a recency-index query — so
320
+ * without the binding a row planted anywhere in the table under this adapter's
321
+ * SESSION sort key was summarised under whatever `sessionId` it claimed, and a
322
+ * caller taking that id to `getMessages` read a partition the row never lived
323
+ * in.
324
+ *
325
+ * Accepts: `raw` — a row a listing read. `atSeconds` — the listing's clock,
326
+ * against which an expired row is absent.
327
+ *
328
+ * Returns: the summary, or `undefined` for a foreign, malformed or expired row.
329
+ *
330
+ * Throws: `FORMAT_UNSUPPORTED` for a row a newer release wrote. It is not a
331
+ * foreign row to skip, and summarising it under this release's rules could
332
+ * return its attributes with a meaning they no longer have. Checked before the
333
+ * shape, the binding and the ttl — as every other read of this package's rows
334
+ * checks it — so a newer row is refused rather than judged against attribute
335
+ * names it may no longer use, and the answer does not depend on the reading
336
+ * machine's clock.
337
+ */
338
+ export declare function summariseSession(raw: AttributeMap, atSeconds: number): SessionMetadata | undefined;
339
+ /**
340
+ * Where a history row sits in the recency index, for a row written before the
341
+ * index existed.
342
+ *
343
+ * Accepts: `row` — any row of the table.
344
+ *
345
+ * Returns: a SESSION row's identity — its session id, at its own `updatedAt` —
346
+ * or `undefined` for a message row or a row of another adapter.
347
+ *
348
+ * Throws: nothing.
349
+ */
350
+ export declare function sessionIndexTarget(row: AttributeMap): IndexTarget | undefined;
@@ -0,0 +1,285 @@
1
+ import { nowSeconds } from '../../shared/clock.js';
2
+ import { conditionFailedAt } from '../../shared/dynamodb/cancellation.js';
3
+ import { OVERWRITE_CAS_MAX_ATTEMPTS, transactIdempotently, WRITE_ID_ATTRIBUTE, } from '../../shared/dynamodb/idempotent-write.js';
4
+ import { backfilledAt, DEFAULT_INDEX_SHARDS, INDEX_PARTITION_ATTRIBUTE, INDEX_SORT_ATTRIBUTE, indexKeys, } from '../../shared/dynamodb/recency-index.js';
5
+ import { withDynamoDBRetry, retryFor } from '../../shared/dynamodb/retry.js';
6
+ import { assertReadableRow, isExpiredRow, PARTITION_KEY_ATTRIBUTE, ROW_FORMAT_VERSION, } from '../../shared/dynamodb/table-schema.js';
7
+ import { classifyAwsError } from '../../shared/errors/classify.js';
8
+ import { ErrorCode } from '../../shared/errors/error-code.js';
9
+ import { conflictError } from '../../shared/errors/errors.js';
10
+ import { countLiveMessages } from './message-read.js';
11
+ import { historyPartitionPrefix, SESSION_SORT_KEY, sessionPartition, sessionRowKey, } from './rows.js';
12
+ function isCancelledByCondition(error) {
13
+ return conditionFailedAt(error, 0);
14
+ }
15
+ export async function revertSessionCount(context, sessionId, delta, createdBefore) {
16
+ if (delta === 0)
17
+ return;
18
+ const update = {
19
+ TableName: context.tableName,
20
+ Key: sessionRowKey(sessionId),
21
+ UpdateExpression: 'ADD #count :neg',
22
+ ConditionExpression: `attribute_exists(${PARTITION_KEY_ATTRIBUTE}) AND #c <= :now`,
23
+ ExpressionAttributeNames: { '#count': 'messageCount', '#c': 'createdAt' },
24
+ ExpressionAttributeValues: { ':neg': -delta, ':now': createdBefore },
25
+ };
26
+ try {
27
+ await transactIdempotently(context, [{ Update: update }]);
28
+ }
29
+ catch (error) {
30
+ if (isCancelledByCondition(error))
31
+ return;
32
+ throw error;
33
+ }
34
+ }
35
+ export async function revertSessionCreation(context, sessionId, created) {
36
+ if (created.total === 0)
37
+ return;
38
+ try {
39
+ await transactIdempotently(context, [
40
+ {
41
+ Delete: {
42
+ TableName: context.tableName,
43
+ Key: sessionRowKey(sessionId),
44
+ ConditionExpression: '#count = :total AND #c = :now',
45
+ ExpressionAttributeNames: { '#count': 'messageCount', '#c': 'createdAt' },
46
+ ExpressionAttributeValues: { ':total': created.total, ':now': created.createdAt },
47
+ },
48
+ },
49
+ ]);
50
+ return;
51
+ }
52
+ catch (error) {
53
+ if (!isCancelledByCondition(error))
54
+ throw error;
55
+ }
56
+ await revertSessionCount(context, sessionId, created.total, created.createdAt);
57
+ if (created.title !== undefined) {
58
+ await removeRolledBackTitle(context, sessionId, created.createdAt, created.title);
59
+ }
60
+ }
61
+ export function buildSessionUpdate(tableName, fields) {
62
+ const index = indexKeys('SESS', fields.sessionId, fields.now, fields.indexShards ?? DEFAULT_INDEX_SHARDS);
63
+ const names = {
64
+ '#count': 'messageCount',
65
+ '#u': 'updatedAt',
66
+ '#c': 'createdAt',
67
+ '#sid': 'sessionId',
68
+ '#wid': WRITE_ID_ATTRIBUTE,
69
+ '#v': 'v',
70
+ '#gpk': INDEX_PARTITION_ATTRIBUTE,
71
+ '#gsk': INDEX_SORT_ATTRIBUTE,
72
+ };
73
+ const values = {
74
+ ':n': fields.count,
75
+ ':u': fields.now,
76
+ ':c': fields.now,
77
+ ':sid': fields.sessionId,
78
+ ':wid': fields.writeId,
79
+ ':v': ROW_FORMAT_VERSION,
80
+ ':gpk': index.gsi1pk,
81
+ ':gsk': index.gsi1sk,
82
+ };
83
+ const restarting = fields.restart !== undefined && fields.ttlTimestamp !== undefined;
84
+ const sets = [
85
+ '#u = :u',
86
+ restarting ? '#c = :c' : '#c = if_not_exists(#c, :c)',
87
+ restarting ? '#sid = :sid' : '#sid = if_not_exists(#sid, :sid)',
88
+ '#wid = :wid',
89
+ '#v = :v',
90
+ '#gpk = :gpk',
91
+ '#gsk = :gsk',
92
+ ];
93
+ let removes = '';
94
+ if (fields.title !== undefined) {
95
+ names['#title'] = 'title';
96
+ values[':title'] = fields.title;
97
+ sets.push(restarting ? '#title = :title' : '#title = if_not_exists(#title, :title)');
98
+ }
99
+ else if (restarting) {
100
+ names['#title'] = 'title';
101
+ removes = ' REMOVE #title';
102
+ }
103
+ let conditionExpression;
104
+ if (fields.ttlTimestamp !== undefined) {
105
+ names['#ttl'] = 'ttl';
106
+ values[':ttl'] = fields.ttlTimestamp;
107
+ if (restarting) {
108
+ sets.push('#ttl = :ttl');
109
+ values[':expired'] = fields.restart;
110
+ conditionExpression = '#ttl = :expired';
111
+ }
112
+ else if (fields.forceTtlRefresh) {
113
+ sets.push('#ttl = :ttl');
114
+ conditionExpression = 'attribute_not_exists(#ttl) OR #ttl <= :ttl';
115
+ }
116
+ else {
117
+ sets.push('#ttl = if_not_exists(#ttl, :ttl)');
118
+ }
119
+ }
120
+ const count = restarting ? 'SET #count = :n, ' : 'ADD #count :n SET ';
121
+ return {
122
+ Update: {
123
+ TableName: tableName,
124
+ Key: sessionRowKey(fields.sessionId),
125
+ UpdateExpression: `${count}${sets.join(', ')}${removes}`,
126
+ ...(conditionExpression ? { ConditionExpression: conditionExpression } : {}),
127
+ ExpressionAttributeNames: names,
128
+ ExpressionAttributeValues: values,
129
+ },
130
+ };
131
+ }
132
+ function isConditionRejected(error) {
133
+ return classifyAwsError(error) === ErrorCode.CONDITION_CONFLICT;
134
+ }
135
+ export async function removeRolledBackTitle(context, sessionId, createdAt, title) {
136
+ try {
137
+ await withDynamoDBRetry((request) => context.client.update({
138
+ TableName: context.tableName,
139
+ Key: sessionRowKey(sessionId),
140
+ UpdateExpression: 'REMOVE #title',
141
+ ConditionExpression: '#c = :now AND #title = :title',
142
+ ExpressionAttributeNames: { '#title': 'title', '#c': 'createdAt' },
143
+ ExpressionAttributeValues: { ':now': createdAt, ':title': title },
144
+ }, request), context.retry);
145
+ }
146
+ catch (error) {
147
+ if (isConditionRejected(error))
148
+ return;
149
+ throw error;
150
+ }
151
+ }
152
+ export async function resolveTtlAnchor(context, sessionId, candidate, signal) {
153
+ const result = await withDynamoDBRetry((request) => context.client.get({
154
+ TableName: context.tableName,
155
+ Key: sessionRowKey(sessionId),
156
+ ConsistentRead: true,
157
+ ProjectionExpression: '#ttl',
158
+ ExpressionAttributeNames: { '#ttl': 'ttl' },
159
+ }, request), retryFor(context, signal));
160
+ const ttl = result.Item?.ttl;
161
+ if (typeof ttl !== 'number')
162
+ return { ttlTimestamp: candidate, refresh: true };
163
+ if (ttl > nowSeconds())
164
+ return { ttlTimestamp: ttl, refresh: false };
165
+ return { ttlTimestamp: candidate, refresh: true, expiredAnchor: ttl };
166
+ }
167
+ const MAX_TITLE_LENGTH = 80;
168
+ function isTextBlock(block) {
169
+ const candidate = block;
170
+ return candidate.type === 'text' && typeof candidate.text === 'string';
171
+ }
172
+ function textOf(content) {
173
+ if (typeof content === 'string')
174
+ return content;
175
+ if (!Array.isArray(content))
176
+ return undefined;
177
+ const block = content.find((entry) => typeof entry === 'object' && entry !== null && isTextBlock(entry));
178
+ return block?.text;
179
+ }
180
+ export function deriveTitle(messages) {
181
+ const firstHuman = messages.find((message) => message.type === 'human');
182
+ const content = firstHuman === undefined ? undefined : textOf(firstHuman.data.content);
183
+ if (content === undefined || content.length === 0)
184
+ return undefined;
185
+ const kept = [];
186
+ for (const codePoint of content) {
187
+ if (kept.length === MAX_TITLE_LENGTH)
188
+ return `${kept.slice(0, MAX_TITLE_LENGTH - 1).join('')}…`;
189
+ kept.push(codePoint);
190
+ }
191
+ return content;
192
+ }
193
+ async function observeCount(context, sessionId, signal) {
194
+ const result = await withDynamoDBRetry((request) => context.client.get({
195
+ TableName: context.tableName,
196
+ Key: sessionRowKey(sessionId),
197
+ ConsistentRead: true,
198
+ ProjectionExpression: '#count',
199
+ ExpressionAttributeNames: { '#count': 'messageCount' },
200
+ }, request), retryFor(context, signal));
201
+ if (!result.Item)
202
+ return { exists: false };
203
+ const count = result.Item.messageCount;
204
+ return typeof count === 'number' ? { exists: true, count } : { exists: true };
205
+ }
206
+ function countGuard(observed) {
207
+ if (observed.count === undefined) {
208
+ return {
209
+ ConditionExpression: `attribute_exists(${PARTITION_KEY_ATTRIBUTE}) AND attribute_not_exists(#count)`,
210
+ };
211
+ }
212
+ return {
213
+ ConditionExpression: `attribute_exists(${PARTITION_KEY_ATTRIBUTE}) AND #count = :expected`,
214
+ ExpressionAttributeValues: { ':expected': observed.count },
215
+ };
216
+ }
217
+ async function writeCount(context, sessionId, repair, signal) {
218
+ const guard = countGuard(repair.observed);
219
+ await withDynamoDBRetry((request) => context.client.update({
220
+ TableName: context.tableName,
221
+ Key: sessionRowKey(sessionId),
222
+ UpdateExpression: 'SET #count = :count',
223
+ ExpressionAttributeNames: { '#count': 'messageCount' },
224
+ ExpressionAttributeValues: { ':count': repair.count, ...guard.ExpressionAttributeValues },
225
+ ConditionExpression: guard.ConditionExpression,
226
+ }, request), retryFor(context, signal));
227
+ }
228
+ export async function repairMessageCount(context, sessionId, signal) {
229
+ for (let attempt = 1; attempt <= OVERWRITE_CAS_MAX_ATTEMPTS; attempt++) {
230
+ const observed = await observeCount(context, sessionId, signal);
231
+ if (!observed.exists) {
232
+ throw conflictError(`Cannot reconcile messageCount: session "${sessionId}" does not exist`);
233
+ }
234
+ const count = await countLiveMessages(context, sessionId, signal);
235
+ try {
236
+ await writeCount(context, sessionId, { count, observed }, signal);
237
+ return count;
238
+ }
239
+ catch (error) {
240
+ if (!isConditionRejected(error))
241
+ throw error;
242
+ }
243
+ }
244
+ throw conflictError(`Cannot reconcile messageCount: session "${sessionId}" changed during every one of ` +
245
+ `${OVERWRITE_CAS_MAX_ATTEMPTS} attempts; retry when it is quieter`);
246
+ }
247
+ function hasReadableTtl(ttl) {
248
+ if (ttl === undefined)
249
+ return true;
250
+ return typeof ttl === 'number' && Number.isFinite(new Date(ttl * 1000).getTime());
251
+ }
252
+ function isSummarisable(raw) {
253
+ return (typeof raw.messageCount === 'number' &&
254
+ typeof raw.createdAt === 'string' &&
255
+ typeof raw.updatedAt === 'string' &&
256
+ (raw.title === undefined || typeof raw.title === 'string') &&
257
+ hasReadableTtl(raw.ttl));
258
+ }
259
+ export function summariseSession(raw, atSeconds) {
260
+ const item = raw;
261
+ assertReadableRow(item, 'session');
262
+ if (item.SK !== SESSION_SORT_KEY || typeof item.sessionId !== 'string')
263
+ return undefined;
264
+ if (item.PK !== sessionPartition(item.sessionId))
265
+ return undefined;
266
+ if (!isSummarisable(raw) || isExpiredRow(item, atSeconds))
267
+ return undefined;
268
+ return {
269
+ sessionId: item.sessionId,
270
+ title: item.title,
271
+ messageCount: item.messageCount,
272
+ createdAt: item.createdAt,
273
+ updatedAt: item.updatedAt,
274
+ expiresAt: item.ttl === undefined ? undefined : new Date(item.ttl * 1000).toISOString(),
275
+ };
276
+ }
277
+ export function sessionIndexTarget(row) {
278
+ const pk = typeof row.PK === 'string' ? row.PK : '';
279
+ const sk = typeof row.SK === 'string' ? row.SK : '';
280
+ if (!pk.startsWith(historyPartitionPrefix()))
281
+ return undefined;
282
+ return sk.endsWith('SESSION') && typeof row.sessionId === 'string'
283
+ ? { tag: 'SESS', id: row.sessionId, at: backfilledAt(row.updatedAt) }
284
+ : undefined;
285
+ }