@farukada/aws-langgraph-dynamodb-ts 0.9.0 → 1.0.0-rc.2
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.
- package/README.md +1720 -154
- package/dist/backfill/backfill.d.ts +168 -0
- package/dist/backfill/backfill.js +393 -0
- package/dist/checkpointer/actions/delete-thread.d.ts +47 -6
- package/dist/checkpointer/actions/delete-thread.js +58 -21
- package/dist/checkpointer/actions/get-tuple.d.ts +29 -4
- package/dist/checkpointer/actions/get-tuple.js +44 -10
- package/dist/checkpointer/actions/list.d.ts +46 -4
- package/dist/checkpointer/actions/list.js +121 -66
- package/dist/checkpointer/actions/put-writes.d.ts +41 -9
- package/dist/checkpointer/actions/put-writes.js +62 -77
- package/dist/checkpointer/actions/put.d.ts +83 -4
- package/dist/checkpointer/actions/put.js +177 -25
- package/dist/checkpointer/internal/delta-history.d.ts +112 -0
- package/dist/checkpointer/internal/delta-history.js +252 -0
- package/dist/checkpointer/internal/listing.d.ts +149 -0
- package/dist/checkpointer/internal/listing.js +245 -0
- package/dist/checkpointer/internal/parse.d.ts +262 -0
- package/dist/checkpointer/internal/parse.js +372 -0
- package/dist/checkpointer/internal/pending-writes.d.ts +275 -0
- package/dist/checkpointer/internal/pending-writes.js +588 -0
- package/dist/checkpointer/internal/read.d.ts +130 -0
- package/dist/checkpointer/internal/read.js +264 -0
- package/dist/checkpointer/internal/rows.d.ts +571 -0
- package/dist/checkpointer/internal/rows.js +834 -0
- package/dist/checkpointer/internal/setup.d.ts +42 -19
- package/dist/checkpointer/internal/setup.js +65 -29
- package/dist/checkpointer/saver.d.ts +256 -16
- package/dist/checkpointer/saver.js +275 -29
- package/dist/checkpointer/types.d.ts +39 -39
- package/dist/checkpointer/types.js +10 -1
- package/dist/factory/factory.d.ts +134 -28
- package/dist/factory/factory.js +240 -21
- package/dist/factory/types.d.ts +76 -0
- package/dist/factory/types.js +10 -0
- package/dist/history/actions/add-messages.d.ts +31 -4
- package/dist/history/actions/add-messages.js +38 -58
- package/dist/history/actions/clear.d.ts +49 -6
- package/dist/history/actions/clear.js +66 -14
- package/dist/history/actions/get-messages.d.ts +54 -6
- package/dist/history/actions/get-messages.js +126 -43
- package/dist/history/actions/list-sessions.d.ts +52 -10
- package/dist/history/actions/list-sessions.js +139 -40
- package/dist/history/actions/reconcile-count.d.ts +42 -10
- package/dist/history/actions/reconcile-count.js +45 -45
- package/dist/history/chat-message-history.d.ts +220 -33
- package/dist/history/chat-message-history.js +240 -43
- package/dist/history/internal/append.d.ts +212 -0
- package/dist/history/internal/append.js +500 -0
- package/dist/history/internal/message-read.d.ts +84 -0
- package/dist/history/internal/message-read.js +204 -0
- package/dist/history/internal/parse.d.ts +153 -0
- package/dist/history/internal/parse.js +252 -0
- package/dist/history/internal/rows.d.ts +195 -0
- package/dist/history/internal/rows.js +250 -0
- package/dist/history/internal/session.d.ts +331 -0
- package/dist/history/internal/session.js +628 -0
- package/dist/history/internal/setup.d.ts +52 -17
- package/dist/history/internal/setup.js +92 -21
- package/dist/history/session-adapter.d.ts +102 -7
- package/dist/history/session-adapter.js +103 -9
- package/dist/history/types.d.ts +80 -29
- package/dist/history/types.js +10 -1
- package/dist/index.d.ts +42 -11
- package/dist/index.js +33 -12
- package/dist/shared/adapter.d.ts +135 -0
- package/dist/shared/adapter.js +143 -0
- package/dist/shared/clock.d.ts +51 -2
- package/dist/shared/clock.js +57 -2
- package/dist/shared/codec/codec.d.ts +288 -13
- package/dist/shared/codec/codec.js +416 -19
- package/dist/shared/codec/compression.d.ts +43 -7
- package/dist/shared/codec/compression.js +53 -13
- package/dist/shared/codec/json-serde.d.ts +76 -4
- package/dist/shared/codec/json-serde.js +181 -8
- package/dist/shared/codec/s3/client-types.d.ts +53 -0
- package/dist/shared/codec/s3/client-types.js +26 -0
- package/dist/shared/codec/s3/client.d.ts +43 -10
- package/dist/shared/codec/s3/client.js +82 -9
- package/dist/shared/codec/s3/config.d.ts +242 -11
- package/dist/shared/codec/s3/config.js +293 -11
- package/dist/shared/codec/s3/lifecycle.d.ts +164 -6
- package/dist/shared/codec/s3/lifecycle.js +335 -27
- package/dist/shared/codec/s3/offloader.d.ts +393 -18
- package/dist/shared/codec/s3/offloader.js +595 -37
- package/dist/shared/concurrency.d.ts +43 -0
- package/dist/shared/concurrency.js +78 -0
- package/dist/shared/dynamodb/abort.d.ts +47 -0
- package/dist/shared/dynamodb/abort.js +59 -0
- package/dist/shared/dynamodb/batch-write.d.ts +77 -14
- package/dist/shared/dynamodb/batch-write.js +146 -27
- package/dist/shared/dynamodb/cancellation.d.ts +121 -4
- package/dist/shared/dynamodb/cancellation.js +147 -3
- package/dist/shared/dynamodb/client.d.ts +162 -8
- package/dist/shared/dynamodb/client.js +153 -5
- package/dist/shared/dynamodb/idempotent-write.d.ts +551 -0
- package/dist/shared/dynamodb/idempotent-write.js +593 -0
- package/dist/shared/dynamodb/paginate.d.ts +105 -9
- package/dist/shared/dynamodb/paginate.js +175 -7
- package/dist/shared/dynamodb/partition-delete.d.ts +185 -14
- package/dist/shared/dynamodb/partition-delete.js +314 -44
- package/dist/shared/dynamodb/recency-index.d.ts +231 -0
- package/dist/shared/dynamodb/recency-index.js +377 -0
- package/dist/shared/dynamodb/retry.d.ts +276 -8
- package/dist/shared/dynamodb/retry.js +433 -23
- package/dist/shared/dynamodb/table-schema.d.ts +190 -0
- package/dist/shared/dynamodb/table-schema.js +209 -0
- package/dist/shared/errors/base-error.d.ts +184 -10
- package/dist/shared/errors/base-error.js +160 -14
- package/dist/shared/errors/boundary.d.ts +71 -0
- package/dist/shared/errors/boundary.js +143 -0
- package/dist/shared/errors/classify.d.ts +97 -0
- package/dist/shared/errors/classify.js +257 -0
- package/dist/shared/errors/error-code.d.ts +77 -2
- package/dist/shared/errors/error-code.js +83 -1
- package/dist/shared/errors/errors.d.ts +158 -59
- package/dist/shared/errors/errors.js +219 -92
- package/dist/shared/logging/logger.d.ts +69 -3
- package/dist/shared/logging/logger.js +97 -3
- package/dist/shared/logging/redaction.d.ts +92 -8
- package/dist/shared/logging/redaction.js +273 -17
- package/dist/shared/logging/secret-patterns.d.ts +149 -19
- package/dist/shared/logging/secret-patterns.js +188 -27
- package/dist/shared/logging/truncate.d.ts +197 -0
- package/dist/shared/logging/truncate.js +231 -0
- package/dist/shared/options.d.ts +59 -7
- package/dist/shared/options.js +9 -1
- package/dist/shared/ulid.d.ts +77 -7
- package/dist/shared/ulid.js +103 -8
- package/dist/shared/validation/collaborators.d.ts +141 -0
- package/dist/shared/validation/collaborators.js +188 -0
- package/dist/shared/validation/option-shape.d.ts +89 -0
- package/dist/shared/validation/option-shape.js +113 -0
- package/dist/shared/validation/options.d.ts +145 -0
- package/dist/shared/validation/options.js +328 -0
- package/dist/shared/validation/primitives.d.ts +288 -21
- package/dist/shared/validation/primitives.js +353 -50
- package/dist/shared/validation/ttl.d.ts +66 -10
- package/dist/shared/validation/ttl.js +113 -15
- package/dist/store/actions/list-namespaces.d.ts +76 -6
- package/dist/store/actions/list-namespaces.js +166 -24
- package/dist/store/actions/put.d.ts +33 -8
- package/dist/store/actions/put.js +53 -60
- package/dist/store/actions/reconcile-vector-index.d.ts +31 -10
- package/dist/store/actions/reconcile-vector-index.js +34 -15
- package/dist/store/actions/search.d.ts +34 -6
- package/dist/store/actions/search.js +56 -51
- package/dist/store/internal/batch-plan.d.ts +26 -0
- package/dist/store/internal/batch-plan.js +109 -0
- package/dist/store/internal/filter.d.ts +36 -3
- package/dist/store/internal/filter.js +66 -15
- package/dist/store/internal/get-item.d.ts +45 -0
- package/dist/store/internal/get-item.js +115 -0
- package/dist/store/internal/item-write.d.ts +230 -0
- package/dist/store/internal/item-write.js +463 -0
- package/dist/store/internal/parse.d.ts +225 -0
- package/dist/store/internal/parse.js +350 -0
- package/dist/store/internal/rows.d.ts +355 -0
- package/dist/store/internal/rows.js +447 -0
- package/dist/store/internal/semantic-search.d.ts +161 -6
- package/dist/store/internal/semantic-search.js +360 -18
- package/dist/store/internal/setup.d.ts +77 -20
- package/dist/store/internal/setup.js +178 -47
- package/dist/store/internal/table-search.d.ts +100 -0
- package/dist/store/internal/table-search.js +213 -0
- package/dist/store/internal/vector-index.d.ts +247 -0
- package/dist/store/internal/vector-index.js +546 -0
- package/dist/store/store.d.ts +270 -17
- package/dist/store/store.js +329 -38
- package/dist/store/types.d.ts +76 -26
- package/dist/store/types.js +13 -1
- package/dist/store/vector-backend.d.ts +64 -4
- package/dist/store/vector-backend.js +15 -1
- package/package.json +58 -36
- package/dist/checkpointer/actions/delete-thread.d.ts.map +0 -1
- package/dist/checkpointer/actions/delete-thread.js.map +0 -1
- package/dist/checkpointer/actions/get-tuple.d.ts.map +0 -1
- package/dist/checkpointer/actions/get-tuple.js.map +0 -1
- package/dist/checkpointer/actions/list.d.ts.map +0 -1
- package/dist/checkpointer/actions/list.js.map +0 -1
- package/dist/checkpointer/actions/put-writes.d.ts.map +0 -1
- package/dist/checkpointer/actions/put-writes.js.map +0 -1
- package/dist/checkpointer/actions/put.d.ts.map +0 -1
- package/dist/checkpointer/actions/put.js.map +0 -1
- package/dist/checkpointer/internal/assemble.d.ts +0 -10
- package/dist/checkpointer/internal/assemble.d.ts.map +0 -1
- package/dist/checkpointer/internal/assemble.js +0 -37
- package/dist/checkpointer/internal/assemble.js.map +0 -1
- package/dist/checkpointer/internal/configurable.d.ts +0 -13
- package/dist/checkpointer/internal/configurable.d.ts.map +0 -1
- package/dist/checkpointer/internal/configurable.js +0 -23
- package/dist/checkpointer/internal/configurable.js.map +0 -1
- package/dist/checkpointer/internal/fetch.d.ts +0 -10
- package/dist/checkpointer/internal/fetch.d.ts.map +0 -1
- package/dist/checkpointer/internal/fetch.js +0 -46
- package/dist/checkpointer/internal/fetch.js.map +0 -1
- package/dist/checkpointer/internal/filter-match.d.ts +0 -12
- package/dist/checkpointer/internal/filter-match.d.ts.map +0 -1
- package/dist/checkpointer/internal/filter-match.js +0 -14
- package/dist/checkpointer/internal/filter-match.js.map +0 -1
- package/dist/checkpointer/internal/item-reader.d.ts +0 -55
- package/dist/checkpointer/internal/item-reader.d.ts.map +0 -1
- package/dist/checkpointer/internal/item-reader.js +0 -88
- package/dist/checkpointer/internal/item-reader.js.map +0 -1
- package/dist/checkpointer/internal/item-writer.d.ts +0 -26
- package/dist/checkpointer/internal/item-writer.d.ts.map +0 -1
- package/dist/checkpointer/internal/item-writer.js +0 -92
- package/dist/checkpointer/internal/item-writer.js.map +0 -1
- package/dist/checkpointer/internal/keys.d.ts +0 -31
- package/dist/checkpointer/internal/keys.d.ts.map +0 -1
- package/dist/checkpointer/internal/keys.js +0 -87
- package/dist/checkpointer/internal/keys.js.map +0 -1
- package/dist/checkpointer/internal/query.d.ts +0 -20
- package/dist/checkpointer/internal/query.d.ts.map +0 -1
- package/dist/checkpointer/internal/query.js +0 -36
- package/dist/checkpointer/internal/query.js.map +0 -1
- package/dist/checkpointer/internal/setup.d.ts.map +0 -1
- package/dist/checkpointer/internal/setup.js.map +0 -1
- package/dist/checkpointer/internal/special-write-cas.d.ts +0 -30
- package/dist/checkpointer/internal/special-write-cas.d.ts.map +0 -1
- package/dist/checkpointer/internal/special-write-cas.js +0 -104
- package/dist/checkpointer/internal/special-write-cas.js.map +0 -1
- package/dist/checkpointer/internal/special-write-cleanup.d.ts +0 -24
- package/dist/checkpointer/internal/special-write-cleanup.d.ts.map +0 -1
- package/dist/checkpointer/internal/special-write-cleanup.js +0 -47
- package/dist/checkpointer/internal/special-write-cleanup.js.map +0 -1
- package/dist/checkpointer/internal/special-write-verify.d.ts +0 -54
- package/dist/checkpointer/internal/special-write-verify.d.ts.map +0 -1
- package/dist/checkpointer/internal/special-write-verify.js +0 -65
- package/dist/checkpointer/internal/special-write-verify.js.map +0 -1
- package/dist/checkpointer/internal/validation.d.ts +0 -13
- package/dist/checkpointer/internal/validation.d.ts.map +0 -1
- package/dist/checkpointer/internal/validation.js +0 -30
- package/dist/checkpointer/internal/validation.js.map +0 -1
- package/dist/checkpointer/internal/write-guard.d.ts +0 -13
- package/dist/checkpointer/internal/write-guard.d.ts.map +0 -1
- package/dist/checkpointer/internal/write-guard.js +0 -39
- package/dist/checkpointer/internal/write-guard.js.map +0 -1
- package/dist/checkpointer/internal/write-index.d.ts +0 -37
- package/dist/checkpointer/internal/write-index.d.ts.map +0 -1
- package/dist/checkpointer/internal/write-index.js +0 -42
- package/dist/checkpointer/internal/write-index.js.map +0 -1
- package/dist/checkpointer/saver.d.ts.map +0 -1
- package/dist/checkpointer/saver.js.map +0 -1
- package/dist/checkpointer/types.d.ts.map +0 -1
- package/dist/checkpointer/types.js.map +0 -1
- package/dist/factory/factory.d.ts.map +0 -1
- package/dist/factory/factory.js.map +0 -1
- package/dist/history/actions/add-messages.d.ts.map +0 -1
- package/dist/history/actions/add-messages.js.map +0 -1
- package/dist/history/actions/clear.d.ts.map +0 -1
- package/dist/history/actions/clear.js.map +0 -1
- package/dist/history/actions/get-messages.d.ts.map +0 -1
- package/dist/history/actions/get-messages.js.map +0 -1
- package/dist/history/actions/list-sessions.d.ts.map +0 -1
- package/dist/history/actions/list-sessions.js.map +0 -1
- package/dist/history/actions/reconcile-count.d.ts.map +0 -1
- package/dist/history/actions/reconcile-count.js.map +0 -1
- package/dist/history/chat-message-history.d.ts.map +0 -1
- package/dist/history/chat-message-history.js.map +0 -1
- package/dist/history/internal/append-saga.d.ts +0 -20
- package/dist/history/internal/append-saga.d.ts.map +0 -1
- package/dist/history/internal/append-saga.js +0 -35
- package/dist/history/internal/append-saga.js.map +0 -1
- package/dist/history/internal/compensation.d.ts +0 -21
- package/dist/history/internal/compensation.d.ts.map +0 -1
- package/dist/history/internal/compensation.js +0 -84
- package/dist/history/internal/compensation.js.map +0 -1
- package/dist/history/internal/item-mapper.d.ts +0 -12
- package/dist/history/internal/item-mapper.d.ts.map +0 -1
- package/dist/history/internal/item-mapper.js +0 -33
- package/dist/history/internal/item-mapper.js.map +0 -1
- package/dist/history/internal/keys.d.ts +0 -17
- package/dist/history/internal/keys.d.ts.map +0 -1
- package/dist/history/internal/keys.js +0 -49
- package/dist/history/internal/keys.js.map +0 -1
- package/dist/history/internal/message-chunker.d.ts +0 -14
- package/dist/history/internal/message-chunker.d.ts.map +0 -1
- package/dist/history/internal/message-chunker.js +0 -68
- package/dist/history/internal/message-chunker.js.map +0 -1
- package/dist/history/internal/message-transaction.d.ts +0 -26
- package/dist/history/internal/message-transaction.d.ts.map +0 -1
- package/dist/history/internal/message-transaction.js +0 -60
- package/dist/history/internal/message-transaction.js.map +0 -1
- package/dist/history/internal/query.d.ts +0 -10
- package/dist/history/internal/query.d.ts.map +0 -1
- package/dist/history/internal/query.js +0 -31
- package/dist/history/internal/query.js.map +0 -1
- package/dist/history/internal/session-count.d.ts +0 -41
- package/dist/history/internal/session-count.d.ts.map +0 -1
- package/dist/history/internal/session-count.js +0 -109
- package/dist/history/internal/session-count.js.map +0 -1
- package/dist/history/internal/session-title.d.ts +0 -20
- package/dist/history/internal/session-title.d.ts.map +0 -1
- package/dist/history/internal/session-title.js +0 -44
- package/dist/history/internal/session-title.js.map +0 -1
- package/dist/history/internal/session-update.d.ts +0 -28
- package/dist/history/internal/session-update.d.ts.map +0 -1
- package/dist/history/internal/session-update.js +0 -70
- package/dist/history/internal/session-update.js.map +0 -1
- package/dist/history/internal/setup.d.ts.map +0 -1
- package/dist/history/internal/setup.js.map +0 -1
- package/dist/history/internal/title-generator.d.ts +0 -13
- package/dist/history/internal/title-generator.d.ts.map +0 -1
- package/dist/history/internal/title-generator.js +0 -25
- package/dist/history/internal/title-generator.js.map +0 -1
- package/dist/history/internal/ttl-anchor.d.ts +0 -25
- package/dist/history/internal/ttl-anchor.d.ts.map +0 -1
- package/dist/history/internal/ttl-anchor.js +0 -38
- package/dist/history/internal/ttl-anchor.js.map +0 -1
- package/dist/history/internal/validation.d.ts +0 -9
- package/dist/history/internal/validation.d.ts.map +0 -1
- package/dist/history/internal/validation.js +0 -16
- package/dist/history/internal/validation.js.map +0 -1
- package/dist/history/session-adapter.d.ts.map +0 -1
- package/dist/history/session-adapter.js.map +0 -1
- package/dist/history/types.d.ts.map +0 -1
- package/dist/history/types.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/shared/clock.d.ts.map +0 -1
- package/dist/shared/clock.js.map +0 -1
- package/dist/shared/codec/codec.d.ts.map +0 -1
- package/dist/shared/codec/codec.js.map +0 -1
- package/dist/shared/codec/compression.d.ts.map +0 -1
- package/dist/shared/codec/compression.js.map +0 -1
- package/dist/shared/codec/descriptor-keys.d.ts +0 -4
- package/dist/shared/codec/descriptor-keys.d.ts.map +0 -1
- package/dist/shared/codec/descriptor-keys.js +0 -14
- package/dist/shared/codec/descriptor-keys.js.map +0 -1
- package/dist/shared/codec/json-serde.d.ts.map +0 -1
- package/dist/shared/codec/json-serde.js.map +0 -1
- package/dist/shared/codec/s3/client.d.ts.map +0 -1
- package/dist/shared/codec/s3/client.js.map +0 -1
- package/dist/shared/codec/s3/config.d.ts.map +0 -1
- package/dist/shared/codec/s3/config.js.map +0 -1
- package/dist/shared/codec/s3/delete.d.ts +0 -8
- package/dist/shared/codec/s3/delete.d.ts.map +0 -1
- package/dist/shared/codec/s3/delete.js +0 -29
- package/dist/shared/codec/s3/delete.js.map +0 -1
- package/dist/shared/codec/s3/lifecycle.d.ts.map +0 -1
- package/dist/shared/codec/s3/lifecycle.js.map +0 -1
- package/dist/shared/codec/s3/offloader.d.ts.map +0 -1
- package/dist/shared/codec/s3/offloader.js.map +0 -1
- package/dist/shared/codec/s3/orphans.d.ts +0 -18
- package/dist/shared/codec/s3/orphans.d.ts.map +0 -1
- package/dist/shared/codec/s3/orphans.js +0 -58
- package/dist/shared/codec/s3/orphans.js.map +0 -1
- package/dist/shared/codec/s3/read-write.d.ts +0 -14
- package/dist/shared/codec/s3/read-write.d.ts.map +0 -1
- package/dist/shared/codec/s3/read-write.js +0 -43
- package/dist/shared/codec/s3/read-write.js.map +0 -1
- package/dist/shared/codec/s3/retry.d.ts +0 -5
- package/dist/shared/codec/s3/retry.d.ts.map +0 -1
- package/dist/shared/codec/s3/retry.js +0 -25
- package/dist/shared/codec/s3/retry.js.map +0 -1
- package/dist/shared/constants.d.ts +0 -64
- package/dist/shared/constants.d.ts.map +0 -1
- package/dist/shared/constants.js +0 -67
- package/dist/shared/constants.js.map +0 -1
- package/dist/shared/dynamodb/backoff.d.ts +0 -15
- package/dist/shared/dynamodb/backoff.d.ts.map +0 -1
- package/dist/shared/dynamodb/backoff.js +0 -48
- package/dist/shared/dynamodb/backoff.js.map +0 -1
- package/dist/shared/dynamodb/batch-write.d.ts.map +0 -1
- package/dist/shared/dynamodb/batch-write.js.map +0 -1
- package/dist/shared/dynamodb/cancellation.d.ts.map +0 -1
- package/dist/shared/dynamodb/cancellation.js.map +0 -1
- package/dist/shared/dynamodb/client.d.ts.map +0 -1
- package/dist/shared/dynamodb/client.js.map +0 -1
- package/dist/shared/dynamodb/conditional-put.d.ts +0 -51
- package/dist/shared/dynamodb/conditional-put.d.ts.map +0 -1
- package/dist/shared/dynamodb/conditional-put.js +0 -59
- package/dist/shared/dynamodb/conditional-put.js.map +0 -1
- package/dist/shared/dynamodb/drain-unprocessed.d.ts +0 -19
- package/dist/shared/dynamodb/drain-unprocessed.d.ts.map +0 -1
- package/dist/shared/dynamodb/drain-unprocessed.js +0 -44
- package/dist/shared/dynamodb/drain-unprocessed.js.map +0 -1
- package/dist/shared/dynamodb/paginate-core.d.ts +0 -22
- package/dist/shared/dynamodb/paginate-core.d.ts.map +0 -1
- package/dist/shared/dynamodb/paginate-core.js +0 -52
- package/dist/shared/dynamodb/paginate-core.js.map +0 -1
- package/dist/shared/dynamodb/paginate.d.ts.map +0 -1
- package/dist/shared/dynamodb/paginate.js.map +0 -1
- package/dist/shared/dynamodb/partition-delete.d.ts.map +0 -1
- package/dist/shared/dynamodb/partition-delete.js.map +0 -1
- package/dist/shared/dynamodb/retry-classifier.d.ts +0 -9
- package/dist/shared/dynamodb/retry-classifier.d.ts.map +0 -1
- package/dist/shared/dynamodb/retry-classifier.js +0 -87
- package/dist/shared/dynamodb/retry-classifier.js.map +0 -1
- package/dist/shared/dynamodb/retry.d.ts.map +0 -1
- package/dist/shared/dynamodb/retry.js.map +0 -1
- package/dist/shared/dynamodb/scan.d.ts +0 -15
- package/dist/shared/dynamodb/scan.d.ts.map +0 -1
- package/dist/shared/dynamodb/scan.js +0 -20
- package/dist/shared/dynamodb/scan.js.map +0 -1
- package/dist/shared/dynamodb/types.d.ts +0 -24
- package/dist/shared/dynamodb/types.d.ts.map +0 -1
- package/dist/shared/dynamodb/types.js +0 -3
- package/dist/shared/dynamodb/types.js.map +0 -1
- package/dist/shared/errors/base-error.d.ts.map +0 -1
- package/dist/shared/errors/base-error.js.map +0 -1
- package/dist/shared/errors/error-code.d.ts.map +0 -1
- package/dist/shared/errors/error-code.js.map +0 -1
- package/dist/shared/errors/errors.d.ts.map +0 -1
- package/dist/shared/errors/errors.js.map +0 -1
- package/dist/shared/errors/wrap-error.d.ts +0 -16
- package/dist/shared/errors/wrap-error.d.ts.map +0 -1
- package/dist/shared/errors/wrap-error.js +0 -30
- package/dist/shared/errors/wrap-error.js.map +0 -1
- package/dist/shared/logging/logger.d.ts.map +0 -1
- package/dist/shared/logging/logger.js.map +0 -1
- package/dist/shared/logging/redaction-walk.d.ts +0 -23
- package/dist/shared/logging/redaction-walk.d.ts.map +0 -1
- package/dist/shared/logging/redaction-walk.js +0 -92
- package/dist/shared/logging/redaction-walk.js.map +0 -1
- package/dist/shared/logging/redaction.d.ts.map +0 -1
- package/dist/shared/logging/redaction.js.map +0 -1
- package/dist/shared/logging/secret-patterns.d.ts.map +0 -1
- package/dist/shared/logging/secret-patterns.js.map +0 -1
- package/dist/shared/options.d.ts.map +0 -1
- package/dist/shared/options.js.map +0 -1
- package/dist/shared/ulid.d.ts.map +0 -1
- package/dist/shared/ulid.js.map +0 -1
- package/dist/shared/validation/primitives.d.ts.map +0 -1
- package/dist/shared/validation/primitives.js.map +0 -1
- package/dist/shared/validation/ttl.d.ts.map +0 -1
- package/dist/shared/validation/ttl.js.map +0 -1
- package/dist/store/actions/get.d.ts +0 -5
- package/dist/store/actions/get.d.ts.map +0 -1
- package/dist/store/actions/get.js +0 -35
- package/dist/store/actions/get.js.map +0 -1
- package/dist/store/actions/list-namespaces.d.ts.map +0 -1
- package/dist/store/actions/list-namespaces.js.map +0 -1
- package/dist/store/actions/put.d.ts.map +0 -1
- package/dist/store/actions/put.js.map +0 -1
- package/dist/store/actions/reconcile-vector-index.d.ts.map +0 -1
- package/dist/store/actions/reconcile-vector-index.js.map +0 -1
- package/dist/store/actions/search.d.ts.map +0 -1
- package/dist/store/actions/search.js.map +0 -1
- package/dist/store/internal/backend-search.d.ts +0 -5
- package/dist/store/internal/backend-search.d.ts.map +0 -1
- package/dist/store/internal/backend-search.js +0 -68
- package/dist/store/internal/backend-search.js.map +0 -1
- package/dist/store/internal/filter.d.ts.map +0 -1
- package/dist/store/internal/filter.js.map +0 -1
- package/dist/store/internal/index-reconcile.d.ts +0 -22
- package/dist/store/internal/index-reconcile.d.ts.map +0 -1
- package/dist/store/internal/index-reconcile.js +0 -105
- package/dist/store/internal/index-reconcile.js.map +0 -1
- package/dist/store/internal/index-sync.d.ts +0 -11
- package/dist/store/internal/index-sync.d.ts.map +0 -1
- package/dist/store/internal/index-sync.js +0 -26
- package/dist/store/internal/index-sync.js.map +0 -1
- package/dist/store/internal/item-mapper.d.ts +0 -25
- package/dist/store/internal/item-mapper.d.ts.map +0 -1
- package/dist/store/internal/item-mapper.js +0 -53
- package/dist/store/internal/item-mapper.js.map +0 -1
- package/dist/store/internal/keys.d.ts +0 -18
- package/dist/store/internal/keys.d.ts.map +0 -1
- package/dist/store/internal/keys.js +0 -42
- package/dist/store/internal/keys.js.map +0 -1
- package/dist/store/internal/namespace-match.d.ts +0 -12
- package/dist/store/internal/namespace-match.d.ts.map +0 -1
- package/dist/store/internal/namespace-match.js +0 -41
- package/dist/store/internal/namespace-match.js.map +0 -1
- package/dist/store/internal/overwrite-swap.d.ts +0 -33
- package/dist/store/internal/overwrite-swap.d.ts.map +0 -1
- package/dist/store/internal/overwrite-swap.js +0 -62
- package/dist/store/internal/overwrite-swap.js.map +0 -1
- package/dist/store/internal/persist.d.ts +0 -27
- package/dist/store/internal/persist.d.ts.map +0 -1
- package/dist/store/internal/persist.js +0 -59
- package/dist/store/internal/persist.js.map +0 -1
- package/dist/store/internal/query.d.ts +0 -6
- package/dist/store/internal/query.d.ts.map +0 -1
- package/dist/store/internal/query.js +0 -32
- package/dist/store/internal/query.js.map +0 -1
- package/dist/store/internal/ranker.d.ts +0 -13
- package/dist/store/internal/ranker.d.ts.map +0 -1
- package/dist/store/internal/ranker.js +0 -31
- package/dist/store/internal/ranker.js.map +0 -1
- package/dist/store/internal/read-existing.d.ts +0 -19
- package/dist/store/internal/read-existing.d.ts.map +0 -1
- package/dist/store/internal/read-existing.js +0 -29
- package/dist/store/internal/read-existing.js.map +0 -1
- package/dist/store/internal/score-direction.d.ts +0 -32
- package/dist/store/internal/score-direction.d.ts.map +0 -1
- package/dist/store/internal/score-direction.js +0 -39
- package/dist/store/internal/score-direction.js.map +0 -1
- package/dist/store/internal/search-filter.d.ts +0 -4
- package/dist/store/internal/search-filter.d.ts.map +0 -1
- package/dist/store/internal/search-filter.js +0 -11
- package/dist/store/internal/search-filter.js.map +0 -1
- package/dist/store/internal/semantic-search.d.ts.map +0 -1
- package/dist/store/internal/semantic-search.js.map +0 -1
- package/dist/store/internal/setup.d.ts.map +0 -1
- package/dist/store/internal/setup.js.map +0 -1
- package/dist/store/internal/validation.d.ts +0 -13
- package/dist/store/internal/validation.d.ts.map +0 -1
- package/dist/store/internal/validation.js +0 -35
- package/dist/store/internal/validation.js.map +0 -1
- package/dist/store/internal/write-verify.d.ts +0 -37
- package/dist/store/internal/write-verify.d.ts.map +0 -1
- package/dist/store/internal/write-verify.js +0 -68
- package/dist/store/internal/write-verify.js.map +0 -1
- package/dist/store/store.d.ts.map +0 -1
- package/dist/store/store.js.map +0 -1
- package/dist/store/types.d.ts.map +0 -1
- package/dist/store/types.js.map +0 -1
- package/dist/store/vector-backend.d.ts.map +0 -1
- package/dist/store/vector-backend.js.map +0 -1
|
@@ -1,24 +1,255 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Hides the S3 key layout: where a row's object lives, and which keys a row may touch.
|
|
3
|
+
*
|
|
4
|
+
* An offloaded object's key is the adapter's prefix, then the row's own
|
|
5
|
+
* identifiers each base64url-encoded, then the id of the write that produced
|
|
6
|
+
* it, so a key read back from a row can be checked against the path that row
|
|
7
|
+
* could have produced before anything is read or deleted. The configuration a
|
|
8
|
+
* caller passes, its checks, the default prefix per adapter and the lifecycle
|
|
9
|
+
* rule ids derived from a prefix are part of the same layout.
|
|
10
|
+
*/
|
|
11
|
+
import type { DynamoDBClientConfig } from '@aws-sdk/client-dynamodb';
|
|
12
|
+
import { type S3ClientConfigLike } from './client-types';
|
|
13
|
+
/** Default S3 key prefix for offloaded payloads. */
|
|
14
|
+
export declare const DEFAULT_S3_KEY_PREFIX = "langgraph-checkpoints/";
|
|
15
|
+
/** S3 cap on an object key, applied to the produced offload key. */
|
|
16
|
+
export declare const MAX_S3_KEY_BYTES = 1024;
|
|
2
17
|
/** Configuration for offloading large payloads to S3. */
|
|
3
18
|
export interface S3OffloadConfig {
|
|
4
19
|
bucketName: string;
|
|
5
20
|
keyPrefix?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Serialized payloads at or above this size are offloaded (default 350 KB).
|
|
23
|
+
* Only the payload counts: the store's inline vectors live on the same item
|
|
24
|
+
* and are not part of it. The store embeds one vector **per configured
|
|
25
|
+
* field** (`index.fields`, one field by default), each about 10 bytes per
|
|
26
|
+
* dimension, so three fields at 1024 dims cost roughly 30 KB, not 10 KB.
|
|
27
|
+
* Keep `thresholdBytes` plus that total under DynamoDB's 400 KB item limit
|
|
28
|
+
* or the put fails, surfaced as `AWS_REJECTED`.
|
|
29
|
+
*/
|
|
6
30
|
thresholdBytes?: number;
|
|
7
31
|
serverSideEncryption?: string;
|
|
8
32
|
sseKmsKeyId?: string;
|
|
9
|
-
|
|
10
|
-
|
|
33
|
+
/** Largest object this adapter will buffer from S3 (default 50 MiB). */
|
|
34
|
+
maxDownloadBytes?: number;
|
|
35
|
+
/**
|
|
36
|
+
* S3 client configuration (an `S3ClientConfig`). `region` defaults to the
|
|
37
|
+
* adapter's DynamoDB region.
|
|
38
|
+
*/
|
|
39
|
+
clientConfig?: S3ClientConfigLike;
|
|
11
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* One key part, base64url-encoded.
|
|
43
|
+
*
|
|
44
|
+
* Accepts: `part` — any string, including empty.
|
|
45
|
+
*
|
|
46
|
+
* Returns: base64url text, whose alphabet (`A-Z a-z 0-9 - _`) contains neither
|
|
47
|
+
* `/` nor `.`, so an encoded part can never be mistaken for a path separator
|
|
48
|
+
* or the `.bin` suffix.
|
|
49
|
+
*
|
|
50
|
+
* Throws: nothing.
|
|
51
|
+
*/
|
|
52
|
+
export declare function encodeKeyPart(part: string): string;
|
|
12
53
|
/**
|
|
13
54
|
* Build a fully-qualified S3 key: `${prefix}${parts, each base64url-encoded,
|
|
14
|
-
* joined with '/'}.bin`.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
55
|
+
* joined with '/'}/${objectId}.bin`.
|
|
56
|
+
*
|
|
57
|
+
* `parts` are the identity of the DynamoDB row that will point at the object,
|
|
58
|
+
* and they are encoded rather than rejected: a namespace element or key may
|
|
59
|
+
* contain '/' (only the DynamoDB '#' separator is forbidden at the validation
|
|
60
|
+
* layer), and base64url's output alphabet never contains '/', so two distinct
|
|
61
|
+
* `parts` arrays can never compose one key.
|
|
62
|
+
*
|
|
63
|
+
* `objectId` names the write that uploads the object and is appended as it
|
|
64
|
+
* is, not encoded, so it must be safe in an S3 key and hold no `/`, or its
|
|
65
|
+
* segments would read as parts. The ids this package passes are both: a UUID
|
|
66
|
+
* (hex digits and `-`) and a ULID (Crockford base-32 digits).
|
|
67
|
+
*
|
|
68
|
+
* Accepts: `prefix` — the offloader's, already validated and separator-
|
|
69
|
+
* terminated. `parts` — at least one; the identity of the row that will point
|
|
70
|
+
* at the object. `objectId` — the uploading write's id: key-safe, with no `/`.
|
|
71
|
+
*
|
|
72
|
+
* Returns: the key. Under one prefix, two distinct `(parts, objectId)` pairs
|
|
73
|
+
* never compose one key, and the same prefix, parts and id always compose the
|
|
74
|
+
* same one.
|
|
75
|
+
*
|
|
76
|
+
* Throws: `VALIDATION` naming `s3Key` for an empty `parts` — an object with
|
|
77
|
+
* no row above it is outside every row's scope and could never be read back —
|
|
78
|
+
* and for a key over the 1024-byte cap. The encoding grows every part by a
|
|
79
|
+
* third, so identifiers that each pass their own length rule can still compose
|
|
80
|
+
* a key S3 would reject with a raw error.
|
|
81
|
+
*/
|
|
82
|
+
export declare function buildS3Key(prefix: string, parts: readonly string[], objectId: string): string;
|
|
83
|
+
/**
|
|
84
|
+
* Refuse a key prefix that does not scope what it is used for.
|
|
85
|
+
*
|
|
86
|
+
* Accepts: `keyPrefix` — must be a string, non-empty, not `/`, and end in `/`.
|
|
87
|
+
* The type is checked here, before any string method is called, so every
|
|
88
|
+
* caller gets it: a number or `null` escaped as a bare `TypeError` from
|
|
89
|
+
* `keyPrefix.endsWith`. Every segment before that final `/` must be a real
|
|
90
|
+
* name: not empty, not `.`, not `..`. The whole prefix must also be free of
|
|
91
|
+
* control characters and well-formed UTF-16, the rules identifiers already
|
|
92
|
+
* meet, since it is written into log lines and into a lifecycle rule's filter.
|
|
93
|
+
*
|
|
94
|
+
* Returns: nothing: the value is kept under its declared type, and this
|
|
95
|
+
* checks it.
|
|
96
|
+
*
|
|
97
|
+
* Throws: `VALIDATION` naming `s3.keyPrefix`. The shape rule is reported
|
|
98
|
+
* before the segment rule, so a prefix breaking both is named by its shape.
|
|
99
|
+
*
|
|
100
|
+
* Guarantees: the prefix scopes both the objects and the lifecycle rule built
|
|
101
|
+
* from it. An empty or root prefix would make that rule expire the whole
|
|
102
|
+
* bucket, and one without a trailing `/` (`app/langgraph`) would also match
|
|
103
|
+
* every sibling starting with the same characters (`app/langgraph-other/`).
|
|
104
|
+
* An accepted prefix also survives path normalisation unchanged, which is what
|
|
105
|
+
* the segment rule buys. An S3 key is a byte string rather than a path, so
|
|
106
|
+
* `a/../b/x.bin` and `b/x.bin` are two different objects — but the IAM
|
|
107
|
+
* object-key condition a deployment writes, the lifecycle rule's
|
|
108
|
+
* `Filter.Prefix`, the console and every tool that resolves a path before
|
|
109
|
+
* matching one disagree about which. A prefix holding `..`, `.` or an empty
|
|
110
|
+
* segment therefore writes objects outside the path the deployment granted and
|
|
111
|
+
* outside the path the lifecycle rule sweeps, which is the whole job of a
|
|
112
|
+
* prefix.
|
|
113
|
+
*/
|
|
114
|
+
export declare function assertScopedKeyPrefix(keyPrefix: string): void;
|
|
115
|
+
/**
|
|
116
|
+
* The lifecycle rule id for `prefix`: `langgraph-ttl-` plus its slug.
|
|
117
|
+
*
|
|
118
|
+
* Accepts: `prefix` — any string; trailing slashes are trimmed, and every
|
|
119
|
+
* character outside `[A-Za-z0-9-]` becomes `-`.
|
|
120
|
+
*
|
|
121
|
+
* Returns: a deterministic id that does not change with the TTL, so raising or
|
|
122
|
+
* lowering the TTL updates one rule rather than adding another. A prefix with
|
|
123
|
+
* no usable characters yields `langgraph-ttl-default`.
|
|
124
|
+
*
|
|
125
|
+
* Throws: nothing.
|
|
126
|
+
*
|
|
127
|
+
* Guarantees: the slug is not injective — `a/b/` and `a-b/` produce one id —
|
|
128
|
+
* and `ensureLifecycleRule` refuses rather than take over a rule that a
|
|
129
|
+
* different prefix already holds.
|
|
18
130
|
*/
|
|
19
|
-
export declare function buildS3Key(prefix: string, parts: readonly string[]): string;
|
|
20
|
-
/** Build a deterministic, TTL-independent lifecycle rule id from the prefix. */
|
|
21
131
|
export declare function buildLifecycleRuleId(prefix: string): string;
|
|
22
|
-
/**
|
|
132
|
+
/**
|
|
133
|
+
* The id of the rule that reclaims this prefix's expired delete markers:
|
|
134
|
+
* {@link buildLifecycleRuleId}'s id with a suffix of its own.
|
|
135
|
+
*
|
|
136
|
+
* Accepts: `prefix` — as {@link buildLifecycleRuleId} takes it.
|
|
137
|
+
*
|
|
138
|
+
* Returns: a second deterministic id, distinct from the expiration rule's.
|
|
139
|
+
* S3 refuses `ExpiredObjectDeleteMarker` inside an `Expiration` that also
|
|
140
|
+
* carries `Days`, so the reclaim cannot be a field on that rule and needs an
|
|
141
|
+
* id to be found by.
|
|
142
|
+
*
|
|
143
|
+
* Throws: nothing.
|
|
144
|
+
*
|
|
145
|
+
* Guarantees: it is *less* injective than the first id rather than merely as
|
|
146
|
+
* injective. On top of the slug collisions that one already has,
|
|
147
|
+
* `buildMarkerRuleId('app/')` and `buildLifecycleRuleId('app-markers/')` are
|
|
148
|
+
* one id — a clash between two prefixes whose letters and digits differ, which
|
|
149
|
+
* the first id alone cannot produce. `ensureLifecycleRule` refuses to take
|
|
150
|
+
* over either id when a different prefix already holds it, and its refusal
|
|
151
|
+
* names the suffix so the remedy fits the case.
|
|
152
|
+
*/
|
|
153
|
+
export declare function buildMarkerRuleId(prefix: string): string;
|
|
154
|
+
/**
|
|
155
|
+
* An adapter's default S3 key prefix.
|
|
156
|
+
*
|
|
157
|
+
* Accepts: `base` — the shared prefix, ending in `/`. `adapter` — the adapter's
|
|
158
|
+
* own segment.
|
|
159
|
+
*
|
|
160
|
+
* Returns: `base` + `adapter` + `/`, so three adapters sharing one bucket write
|
|
161
|
+
* under three paths and one adapter's lifecycle rule never sweeps another's
|
|
162
|
+
* objects.
|
|
163
|
+
*
|
|
164
|
+
* Throws: nothing.
|
|
165
|
+
*/
|
|
23
166
|
export declare function defaultAdapterKeyPrefix(base: string, adapter: string): string;
|
|
24
|
-
|
|
167
|
+
/**
|
|
168
|
+
* The path every key built from `parts` shares.
|
|
169
|
+
*
|
|
170
|
+
* Accepts: `prefix` — the configured key prefix, ending in `/`. `parts` —
|
|
171
|
+
* the row's identifiers; `[]` yields the prefix alone.
|
|
172
|
+
*
|
|
173
|
+
* Returns: the prefix plus the encoded parts joined by `/`, carrying neither
|
|
174
|
+
* `.bin` nor a trailing `/`.
|
|
175
|
+
*
|
|
176
|
+
* Throws: nothing.
|
|
177
|
+
*/
|
|
178
|
+
export declare function s3KeyScope(prefix: string, parts: readonly string[]): string;
|
|
179
|
+
/**
|
|
180
|
+
* Whether `key` lies inside the path `parts` produce.
|
|
181
|
+
*
|
|
182
|
+
* Accepts: `key` — a key read back from a row, or one this package built.
|
|
183
|
+
* `parts` — the row's leading identifiers; `[]` degrades to a prefix-only
|
|
184
|
+
* check.
|
|
185
|
+
*
|
|
186
|
+
* Returns: true when the key continues below the scope (`<scope>/…`, which is
|
|
187
|
+
* every key this release writes, since the write's object id is one segment
|
|
188
|
+
* deeper) or equals it (`<scope>.bin`, the key of a store item offloaded by a
|
|
189
|
+
* release that gave the key no per-write segment).
|
|
190
|
+
*
|
|
191
|
+
* Throws: nothing.
|
|
192
|
+
*
|
|
193
|
+
* Guarantees: an identifier sharing a leading substring with another (`t` and
|
|
194
|
+
* `t1`) never matches its scope — the parts are base64url-encoded and joined
|
|
195
|
+
* by `/`, so the comparison is segment-wise, not textual.
|
|
196
|
+
*/
|
|
197
|
+
export declare function isKeyInScope(key: string, prefix: string, parts: readonly string[]): boolean;
|
|
198
|
+
/**
|
|
199
|
+
* Refuse a row-sourced `s3Key` outside the path the row's own identifiers
|
|
200
|
+
* produce.
|
|
201
|
+
*
|
|
202
|
+
* Accepts: as {@link isKeyInScope}.
|
|
203
|
+
*
|
|
204
|
+
* Returns: nothing: `key` is kept under its declared type, and this checks it
|
|
205
|
+
* against the scope `prefix` and `parts` compose.
|
|
206
|
+
*
|
|
207
|
+
* Throws: `VALIDATION` naming `s3Key`, quoting the key and the path the
|
|
208
|
+
* row may reference, each bounded by {@link truncateForLog}: the key comes off
|
|
209
|
+
* the row and the path is composed from an `s3.keyPrefix` checked for shape
|
|
210
|
+
* and never for length, so neither is bounded by anything this package ran.
|
|
211
|
+
* The key stays named — a bounded prefix still says which object to go and
|
|
212
|
+
* look at. It reaches the caller on all three adapters, including
|
|
213
|
+
* `history.getMessages` under `onCorruptMessage: 'skip'`, because
|
|
214
|
+
* `isPermanentPayloadLoss` does **not** classify it — an out-of-scope key is
|
|
215
|
+
* not the same kind of thing as an unreadable descriptor. An unreadable
|
|
216
|
+
* descriptor condemns the payload itself: nobody can read those bytes, so
|
|
217
|
+
* skipping the row loses nothing that was ever retrievable. An out-of-scope
|
|
218
|
+
* key says only that *this* reader may not follow it — the object is very
|
|
219
|
+
* likely intact, under the prefix that does own it — and what produced it is a
|
|
220
|
+
* `keyPrefix` pointed at the wrong place, a table shared with another tenant,
|
|
221
|
+
* or a planted row. Every one of those is a condition an operator must see and
|
|
222
|
+
* can fix. Classifying it as loss made only `history` answer with a silently
|
|
223
|
+
* shorter conversation — the one adapter that consults the classifier — which
|
|
224
|
+
* the chain then re-persisted as the truth, while the store and the saver
|
|
225
|
+
* raised on the same row. A short answer is the one failure a caller cannot
|
|
226
|
+
* detect, and one row shape must not mean two things across three adapters.
|
|
227
|
+
*
|
|
228
|
+
* Guarantees: a row is trusted for its shape, never for the object it points
|
|
229
|
+
* at. A writer able to place one row in a partition cannot make this library
|
|
230
|
+
* download or delete another tenant's object, nor make it quietly return less.
|
|
231
|
+
*/
|
|
232
|
+
export declare function assertKeyInScope(key: string, prefix: string, parts: readonly string[]): void;
|
|
233
|
+
/** The adapters that share one bucket, each under its own default key prefix. */
|
|
234
|
+
export type AdapterName = 'checkpointer' | 'store' | 'history';
|
|
235
|
+
/**
|
|
236
|
+
* An adapter's `s3` option resolved into the offloader's configuration.
|
|
237
|
+
*
|
|
238
|
+
* Accepts: `s3` — as the caller gave it. `adapter` — names the default key
|
|
239
|
+
* prefix, so three adapters sharing one bucket do not share a path.
|
|
240
|
+
* `clientConfig` — the adapter's DynamoDB client config, read for its region
|
|
241
|
+
* only.
|
|
242
|
+
*
|
|
243
|
+
* Returns: `s3` with `keyPrefix` defaulted to the adapter's own path, and
|
|
244
|
+
* `clientConfig.region` filled in from the DynamoDB side when the S3 config
|
|
245
|
+
* names none. With no region on either side the field is left absent and the
|
|
246
|
+
* SDK resolves it from the environment.
|
|
247
|
+
*
|
|
248
|
+
* Throws: nothing.
|
|
249
|
+
*
|
|
250
|
+
* Guarantees: a bucket reachable only through the region the DynamoDB side was
|
|
251
|
+
* configured with is addressed in that region. The S3 SDK does not follow
|
|
252
|
+
* region redirects, so such a bucket otherwise failed with an opaque
|
|
253
|
+
* `PermanentRedirect` on the first offload.
|
|
254
|
+
*/
|
|
255
|
+
export declare function offloaderConfigFor(s3: S3OffloadConfig, adapter: AdapterName, clientConfig?: DynamoDBClientConfig): S3OffloadConfig;
|
|
@@ -1,26 +1,308 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Hides the S3 key layout: where a row's object lives, and which keys a row may touch.
|
|
4
|
+
*
|
|
5
|
+
* An offloaded object's key is the adapter's prefix, then the row's own
|
|
6
|
+
* identifiers each base64url-encoded, then the id of the write that produced
|
|
7
|
+
* it, so a key read back from a row can be checked against the path that row
|
|
8
|
+
* could have produced before anything is read or deleted. The configuration a
|
|
9
|
+
* caller passes, its checks, the default prefix per adapter and the lifecycle
|
|
10
|
+
* rule ids derived from a prefix are part of the same layout.
|
|
11
|
+
*/
|
|
2
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.MAX_S3_KEY_BYTES = exports.DEFAULT_S3_KEY_PREFIX = void 0;
|
|
14
|
+
exports.encodeKeyPart = encodeKeyPart;
|
|
3
15
|
exports.buildS3Key = buildS3Key;
|
|
16
|
+
exports.assertScopedKeyPrefix = assertScopedKeyPrefix;
|
|
4
17
|
exports.buildLifecycleRuleId = buildLifecycleRuleId;
|
|
18
|
+
exports.buildMarkerRuleId = buildMarkerRuleId;
|
|
5
19
|
exports.defaultAdapterKeyPrefix = defaultAdapterKeyPrefix;
|
|
20
|
+
exports.s3KeyScope = s3KeyScope;
|
|
21
|
+
exports.isKeyInScope = isKeyInScope;
|
|
22
|
+
exports.assertKeyInScope = assertKeyInScope;
|
|
23
|
+
exports.offloaderConfigFor = offloaderConfigFor;
|
|
24
|
+
const errors_1 = require("../../errors/errors");
|
|
25
|
+
const truncate_1 = require("../../logging/truncate");
|
|
26
|
+
const primitives_1 = require("../../validation/primitives");
|
|
27
|
+
const client_types_1 = require("./client-types");
|
|
28
|
+
/** Default S3 key prefix for offloaded payloads. */
|
|
29
|
+
exports.DEFAULT_S3_KEY_PREFIX = 'langgraph-checkpoints/';
|
|
30
|
+
/** S3 cap on an object key, applied to the produced offload key. */
|
|
31
|
+
exports.MAX_S3_KEY_BYTES = 1024;
|
|
32
|
+
/**
|
|
33
|
+
* One key part, base64url-encoded.
|
|
34
|
+
*
|
|
35
|
+
* Accepts: `part` — any string, including empty.
|
|
36
|
+
*
|
|
37
|
+
* Returns: base64url text, whose alphabet (`A-Z a-z 0-9 - _`) contains neither
|
|
38
|
+
* `/` nor `.`, so an encoded part can never be mistaken for a path separator
|
|
39
|
+
* or the `.bin` suffix.
|
|
40
|
+
*
|
|
41
|
+
* Throws: nothing.
|
|
42
|
+
*/
|
|
43
|
+
function encodeKeyPart(part) {
|
|
44
|
+
return Buffer.from(part, 'utf8').toString('base64url');
|
|
45
|
+
}
|
|
6
46
|
/**
|
|
7
47
|
* Build a fully-qualified S3 key: `${prefix}${parts, each base64url-encoded,
|
|
8
|
-
* joined with '/'}.bin`.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
48
|
+
* joined with '/'}/${objectId}.bin`.
|
|
49
|
+
*
|
|
50
|
+
* `parts` are the identity of the DynamoDB row that will point at the object,
|
|
51
|
+
* and they are encoded rather than rejected: a namespace element or key may
|
|
52
|
+
* contain '/' (only the DynamoDB '#' separator is forbidden at the validation
|
|
53
|
+
* layer), and base64url's output alphabet never contains '/', so two distinct
|
|
54
|
+
* `parts` arrays can never compose one key.
|
|
55
|
+
*
|
|
56
|
+
* `objectId` names the write that uploads the object and is appended as it
|
|
57
|
+
* is, not encoded, so it must be safe in an S3 key and hold no `/`, or its
|
|
58
|
+
* segments would read as parts. The ids this package passes are both: a UUID
|
|
59
|
+
* (hex digits and `-`) and a ULID (Crockford base-32 digits).
|
|
60
|
+
*
|
|
61
|
+
* Accepts: `prefix` — the offloader's, already validated and separator-
|
|
62
|
+
* terminated. `parts` — at least one; the identity of the row that will point
|
|
63
|
+
* at the object. `objectId` — the uploading write's id: key-safe, with no `/`.
|
|
64
|
+
*
|
|
65
|
+
* Returns: the key. Under one prefix, two distinct `(parts, objectId)` pairs
|
|
66
|
+
* never compose one key, and the same prefix, parts and id always compose the
|
|
67
|
+
* same one.
|
|
68
|
+
*
|
|
69
|
+
* Throws: `VALIDATION` naming `s3Key` for an empty `parts` — an object with
|
|
70
|
+
* no row above it is outside every row's scope and could never be read back —
|
|
71
|
+
* and for a key over the 1024-byte cap. The encoding grows every part by a
|
|
72
|
+
* third, so identifiers that each pass their own length rule can still compose
|
|
73
|
+
* a key S3 would reject with a raw error.
|
|
74
|
+
*/
|
|
75
|
+
function buildS3Key(prefix, parts, objectId) {
|
|
76
|
+
if (parts.length === 0) {
|
|
77
|
+
throw (0, errors_1.validationError)('an offloaded object needs the identity of the row that points at it; parts was empty', 's3Key');
|
|
78
|
+
}
|
|
79
|
+
const encoded = [...parts.map(encodeKeyPart), objectId];
|
|
80
|
+
const key = `${prefix}${encoded.join('/')}.bin`;
|
|
81
|
+
const bytes = Buffer.byteLength(key, 'utf8');
|
|
82
|
+
if (bytes > exports.MAX_S3_KEY_BYTES) {
|
|
83
|
+
throw (0, errors_1.validationError)(`the offloaded S3 object key would be ${bytes} bytes; S3 caps keys at ` +
|
|
84
|
+
`${exports.MAX_S3_KEY_BYTES} — shorten the identifiers or the keyPrefix`, 's3Key');
|
|
85
|
+
}
|
|
86
|
+
return key;
|
|
87
|
+
}
|
|
88
|
+
/** A path segment that names something other than itself, or nothing at all. */
|
|
89
|
+
const UNSCOPED_SEGMENTS = new Set(['', '.', '..']);
|
|
90
|
+
/**
|
|
91
|
+
* Refuse a key prefix that does not scope what it is used for.
|
|
92
|
+
*
|
|
93
|
+
* Accepts: `keyPrefix` — must be a string, non-empty, not `/`, and end in `/`.
|
|
94
|
+
* The type is checked here, before any string method is called, so every
|
|
95
|
+
* caller gets it: a number or `null` escaped as a bare `TypeError` from
|
|
96
|
+
* `keyPrefix.endsWith`. Every segment before that final `/` must be a real
|
|
97
|
+
* name: not empty, not `.`, not `..`. The whole prefix must also be free of
|
|
98
|
+
* control characters and well-formed UTF-16, the rules identifiers already
|
|
99
|
+
* meet, since it is written into log lines and into a lifecycle rule's filter.
|
|
100
|
+
*
|
|
101
|
+
* Returns: nothing: the value is kept under its declared type, and this
|
|
102
|
+
* checks it.
|
|
103
|
+
*
|
|
104
|
+
* Throws: `VALIDATION` naming `s3.keyPrefix`. The shape rule is reported
|
|
105
|
+
* before the segment rule, so a prefix breaking both is named by its shape.
|
|
106
|
+
*
|
|
107
|
+
* Guarantees: the prefix scopes both the objects and the lifecycle rule built
|
|
108
|
+
* from it. An empty or root prefix would make that rule expire the whole
|
|
109
|
+
* bucket, and one without a trailing `/` (`app/langgraph`) would also match
|
|
110
|
+
* every sibling starting with the same characters (`app/langgraph-other/`).
|
|
111
|
+
* An accepted prefix also survives path normalisation unchanged, which is what
|
|
112
|
+
* the segment rule buys. An S3 key is a byte string rather than a path, so
|
|
113
|
+
* `a/../b/x.bin` and `b/x.bin` are two different objects — but the IAM
|
|
114
|
+
* object-key condition a deployment writes, the lifecycle rule's
|
|
115
|
+
* `Filter.Prefix`, the console and every tool that resolves a path before
|
|
116
|
+
* matching one disagree about which. A prefix holding `..`, `.` or an empty
|
|
117
|
+
* segment therefore writes objects outside the path the deployment granted and
|
|
118
|
+
* outside the path the lifecycle rule sweeps, which is the whole job of a
|
|
119
|
+
* prefix.
|
|
12
120
|
*/
|
|
13
|
-
function
|
|
14
|
-
|
|
15
|
-
|
|
121
|
+
function assertScopedKeyPrefix(keyPrefix) {
|
|
122
|
+
if (typeof keyPrefix !== 'string' ||
|
|
123
|
+
keyPrefix === '' ||
|
|
124
|
+
keyPrefix === '/' ||
|
|
125
|
+
!keyPrefix.endsWith('/')) {
|
|
126
|
+
throw (0, errors_1.validationError)('s3.keyPrefix must be a non-empty path that ends with "/" (for example "langgraph/"): ' +
|
|
127
|
+
'it scopes both the offloaded objects and the S3 lifecycle rule', 's3.keyPrefix');
|
|
128
|
+
}
|
|
129
|
+
(0, primitives_1.assertNoControlChars)(keyPrefix, 's3.keyPrefix');
|
|
130
|
+
(0, primitives_1.assertWellFormed)(keyPrefix, 's3.keyPrefix');
|
|
131
|
+
if (keyPrefix
|
|
132
|
+
.slice(0, -1)
|
|
133
|
+
.split('/')
|
|
134
|
+
.some((segment) => UNSCOPED_SEGMENTS.has(segment))) {
|
|
135
|
+
throw (0, errors_1.validationError)('s3.keyPrefix must name a real path: no empty, "." or ".." segment (for example ' +
|
|
136
|
+
'"langgraph/", not "../langgraph/" or "/langgraph/"). Such a prefix addresses object ' +
|
|
137
|
+
'keys outside the path the IAM policy grants and the lifecycle rule sweeps', 's3.keyPrefix');
|
|
138
|
+
}
|
|
16
139
|
}
|
|
17
|
-
/**
|
|
140
|
+
/**
|
|
141
|
+
* The lifecycle rule id for `prefix`: `langgraph-ttl-` plus its slug.
|
|
142
|
+
*
|
|
143
|
+
* Accepts: `prefix` — any string; trailing slashes are trimmed, and every
|
|
144
|
+
* character outside `[A-Za-z0-9-]` becomes `-`.
|
|
145
|
+
*
|
|
146
|
+
* Returns: a deterministic id that does not change with the TTL, so raising or
|
|
147
|
+
* lowering the TTL updates one rule rather than adding another. A prefix with
|
|
148
|
+
* no usable characters yields `langgraph-ttl-default`.
|
|
149
|
+
*
|
|
150
|
+
* Throws: nothing.
|
|
151
|
+
*
|
|
152
|
+
* Guarantees: the slug is not injective — `a/b/` and `a-b/` produce one id —
|
|
153
|
+
* and `ensureLifecycleRule` refuses rather than take over a rule that a
|
|
154
|
+
* different prefix already holds.
|
|
155
|
+
*/
|
|
18
156
|
function buildLifecycleRuleId(prefix) {
|
|
19
|
-
|
|
157
|
+
let trimmed = prefix;
|
|
158
|
+
while (trimmed.endsWith('/'))
|
|
159
|
+
trimmed = trimmed.slice(0, -1);
|
|
160
|
+
const slug = trimmed.replace(/[^a-zA-Z0-9-]/g, '-') || 'default';
|
|
20
161
|
return `langgraph-ttl-${slug}`;
|
|
21
162
|
}
|
|
22
|
-
/**
|
|
163
|
+
/**
|
|
164
|
+
* The id of the rule that reclaims this prefix's expired delete markers:
|
|
165
|
+
* {@link buildLifecycleRuleId}'s id with a suffix of its own.
|
|
166
|
+
*
|
|
167
|
+
* Accepts: `prefix` — as {@link buildLifecycleRuleId} takes it.
|
|
168
|
+
*
|
|
169
|
+
* Returns: a second deterministic id, distinct from the expiration rule's.
|
|
170
|
+
* S3 refuses `ExpiredObjectDeleteMarker` inside an `Expiration` that also
|
|
171
|
+
* carries `Days`, so the reclaim cannot be a field on that rule and needs an
|
|
172
|
+
* id to be found by.
|
|
173
|
+
*
|
|
174
|
+
* Throws: nothing.
|
|
175
|
+
*
|
|
176
|
+
* Guarantees: it is *less* injective than the first id rather than merely as
|
|
177
|
+
* injective. On top of the slug collisions that one already has,
|
|
178
|
+
* `buildMarkerRuleId('app/')` and `buildLifecycleRuleId('app-markers/')` are
|
|
179
|
+
* one id — a clash between two prefixes whose letters and digits differ, which
|
|
180
|
+
* the first id alone cannot produce. `ensureLifecycleRule` refuses to take
|
|
181
|
+
* over either id when a different prefix already holds it, and its refusal
|
|
182
|
+
* names the suffix so the remedy fits the case.
|
|
183
|
+
*/
|
|
184
|
+
function buildMarkerRuleId(prefix) {
|
|
185
|
+
return `${buildLifecycleRuleId(prefix)}-markers`;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* An adapter's default S3 key prefix.
|
|
189
|
+
*
|
|
190
|
+
* Accepts: `base` — the shared prefix, ending in `/`. `adapter` — the adapter's
|
|
191
|
+
* own segment.
|
|
192
|
+
*
|
|
193
|
+
* Returns: `base` + `adapter` + `/`, so three adapters sharing one bucket write
|
|
194
|
+
* under three paths and one adapter's lifecycle rule never sweeps another's
|
|
195
|
+
* objects.
|
|
196
|
+
*
|
|
197
|
+
* Throws: nothing.
|
|
198
|
+
*/
|
|
23
199
|
function defaultAdapterKeyPrefix(base, adapter) {
|
|
24
200
|
return `${base}${adapter}/`;
|
|
25
201
|
}
|
|
26
|
-
|
|
202
|
+
/**
|
|
203
|
+
* The path every key built from `parts` shares.
|
|
204
|
+
*
|
|
205
|
+
* Accepts: `prefix` — the configured key prefix, ending in `/`. `parts` —
|
|
206
|
+
* the row's identifiers; `[]` yields the prefix alone.
|
|
207
|
+
*
|
|
208
|
+
* Returns: the prefix plus the encoded parts joined by `/`, carrying neither
|
|
209
|
+
* `.bin` nor a trailing `/`.
|
|
210
|
+
*
|
|
211
|
+
* Throws: nothing.
|
|
212
|
+
*/
|
|
213
|
+
function s3KeyScope(prefix, parts) {
|
|
214
|
+
return `${prefix}${parts.map(encodeKeyPart).join('/')}`;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Whether `key` lies inside the path `parts` produce.
|
|
218
|
+
*
|
|
219
|
+
* Accepts: `key` — a key read back from a row, or one this package built.
|
|
220
|
+
* `parts` — the row's leading identifiers; `[]` degrades to a prefix-only
|
|
221
|
+
* check.
|
|
222
|
+
*
|
|
223
|
+
* Returns: true when the key continues below the scope (`<scope>/…`, which is
|
|
224
|
+
* every key this release writes, since the write's object id is one segment
|
|
225
|
+
* deeper) or equals it (`<scope>.bin`, the key of a store item offloaded by a
|
|
226
|
+
* release that gave the key no per-write segment).
|
|
227
|
+
*
|
|
228
|
+
* Throws: nothing.
|
|
229
|
+
*
|
|
230
|
+
* Guarantees: an identifier sharing a leading substring with another (`t` and
|
|
231
|
+
* `t1`) never matches its scope — the parts are base64url-encoded and joined
|
|
232
|
+
* by `/`, so the comparison is segment-wise, not textual.
|
|
233
|
+
*/
|
|
234
|
+
function isKeyInScope(key, prefix, parts) {
|
|
235
|
+
const scope = s3KeyScope(prefix, parts);
|
|
236
|
+
if (parts.length === 0)
|
|
237
|
+
return key.startsWith(scope);
|
|
238
|
+
return key === `${scope}.bin` || key.startsWith(`${scope}/`);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Refuse a row-sourced `s3Key` outside the path the row's own identifiers
|
|
242
|
+
* produce.
|
|
243
|
+
*
|
|
244
|
+
* Accepts: as {@link isKeyInScope}.
|
|
245
|
+
*
|
|
246
|
+
* Returns: nothing: `key` is kept under its declared type, and this checks it
|
|
247
|
+
* against the scope `prefix` and `parts` compose.
|
|
248
|
+
*
|
|
249
|
+
* Throws: `VALIDATION` naming `s3Key`, quoting the key and the path the
|
|
250
|
+
* row may reference, each bounded by {@link truncateForLog}: the key comes off
|
|
251
|
+
* the row and the path is composed from an `s3.keyPrefix` checked for shape
|
|
252
|
+
* and never for length, so neither is bounded by anything this package ran.
|
|
253
|
+
* The key stays named — a bounded prefix still says which object to go and
|
|
254
|
+
* look at. It reaches the caller on all three adapters, including
|
|
255
|
+
* `history.getMessages` under `onCorruptMessage: 'skip'`, because
|
|
256
|
+
* `isPermanentPayloadLoss` does **not** classify it — an out-of-scope key is
|
|
257
|
+
* not the same kind of thing as an unreadable descriptor. An unreadable
|
|
258
|
+
* descriptor condemns the payload itself: nobody can read those bytes, so
|
|
259
|
+
* skipping the row loses nothing that was ever retrievable. An out-of-scope
|
|
260
|
+
* key says only that *this* reader may not follow it — the object is very
|
|
261
|
+
* likely intact, under the prefix that does own it — and what produced it is a
|
|
262
|
+
* `keyPrefix` pointed at the wrong place, a table shared with another tenant,
|
|
263
|
+
* or a planted row. Every one of those is a condition an operator must see and
|
|
264
|
+
* can fix. Classifying it as loss made only `history` answer with a silently
|
|
265
|
+
* shorter conversation — the one adapter that consults the classifier — which
|
|
266
|
+
* the chain then re-persisted as the truth, while the store and the saver
|
|
267
|
+
* raised on the same row. A short answer is the one failure a caller cannot
|
|
268
|
+
* detect, and one row shape must not mean two things across three adapters.
|
|
269
|
+
*
|
|
270
|
+
* Guarantees: a row is trusted for its shape, never for the object it points
|
|
271
|
+
* at. A writer able to place one row in a partition cannot make this library
|
|
272
|
+
* download or delete another tenant's object, nor make it quietly return less.
|
|
273
|
+
*/
|
|
274
|
+
function assertKeyInScope(key, prefix, parts) {
|
|
275
|
+
if (isKeyInScope(key, prefix, parts))
|
|
276
|
+
return;
|
|
277
|
+
throw (0, errors_1.validationError)(`s3Key "${(0, truncate_1.truncateForLog)(key)}" lies outside the S3 path this row may reference ` +
|
|
278
|
+
`("${(0, truncate_1.truncateForLog)(s3KeyScope(prefix, parts))}"); refusing to touch an object the row ` +
|
|
279
|
+
'does not own', 's3Key');
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* An adapter's `s3` option resolved into the offloader's configuration.
|
|
283
|
+
*
|
|
284
|
+
* Accepts: `s3` — as the caller gave it. `adapter` — names the default key
|
|
285
|
+
* prefix, so three adapters sharing one bucket do not share a path.
|
|
286
|
+
* `clientConfig` — the adapter's DynamoDB client config, read for its region
|
|
287
|
+
* only.
|
|
288
|
+
*
|
|
289
|
+
* Returns: `s3` with `keyPrefix` defaulted to the adapter's own path, and
|
|
290
|
+
* `clientConfig.region` filled in from the DynamoDB side when the S3 config
|
|
291
|
+
* names none. With no region on either side the field is left absent and the
|
|
292
|
+
* SDK resolves it from the environment.
|
|
293
|
+
*
|
|
294
|
+
* Throws: nothing.
|
|
295
|
+
*
|
|
296
|
+
* Guarantees: a bucket reachable only through the region the DynamoDB side was
|
|
297
|
+
* configured with is addressed in that region. The S3 SDK does not follow
|
|
298
|
+
* region redirects, so such a bucket otherwise failed with an opaque
|
|
299
|
+
* `PermanentRedirect` on the first offload.
|
|
300
|
+
*/
|
|
301
|
+
function offloaderConfigFor(s3, adapter, clientConfig) {
|
|
302
|
+
const region = (0, client_types_1.s3ClientOptions)(s3.clientConfig).region ?? clientConfig?.region;
|
|
303
|
+
return {
|
|
304
|
+
...s3,
|
|
305
|
+
keyPrefix: s3.keyPrefix ?? defaultAdapterKeyPrefix(exports.DEFAULT_S3_KEY_PREFIX, adapter),
|
|
306
|
+
...(region === undefined ? {} : { clientConfig: { ...s3.clientConfig, region } }),
|
|
307
|
+
};
|
|
308
|
+
}
|