@farukada/aws-langgraph-dynamodb-ts 0.8.0 → 1.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +282 -49
- package/dist/checkpointer/actions/delete-thread.d.ts +3 -2
- package/dist/checkpointer/actions/delete-thread.js +5 -2
- package/dist/checkpointer/actions/get-tuple.d.ts +3 -2
- package/dist/checkpointer/actions/get-tuple.js +10 -4
- package/dist/checkpointer/actions/list.d.ts +14 -4
- package/dist/checkpointer/actions/list.js +94 -61
- package/dist/checkpointer/actions/put-writes.d.ts +5 -5
- package/dist/checkpointer/actions/put-writes.js +12 -40
- package/dist/checkpointer/actions/put.d.ts +10 -3
- package/dist/checkpointer/actions/put.js +42 -12
- package/dist/checkpointer/internal/assemble.d.ts +10 -3
- package/dist/checkpointer/internal/assemble.js +7 -6
- package/dist/checkpointer/internal/checkpoint-write-verify.d.ts +24 -0
- package/dist/checkpointer/internal/checkpoint-write-verify.js +67 -0
- package/dist/checkpointer/internal/configurable.d.ts +0 -1
- package/dist/checkpointer/internal/configurable.js +10 -9
- package/dist/checkpointer/internal/fetch.d.ts +14 -5
- package/dist/checkpointer/internal/fetch.js +56 -14
- package/dist/checkpointer/internal/filter-match.d.ts +3 -2
- package/dist/checkpointer/internal/filter-match.js +4 -3
- package/dist/checkpointer/internal/item-reader.d.ts +31 -6
- package/dist/checkpointer/internal/item-reader.js +54 -15
- package/dist/checkpointer/internal/item-writer.d.ts +12 -3
- package/dist/checkpointer/internal/item-writer.js +26 -10
- package/dist/checkpointer/internal/keys.d.ts +11 -1
- package/dist/checkpointer/internal/keys.js +33 -3
- package/dist/checkpointer/internal/list-scope.d.ts +61 -0
- package/dist/checkpointer/internal/list-scope.js +108 -0
- package/dist/checkpointer/internal/pending-sends.d.ts +13 -0
- package/dist/checkpointer/internal/pending-sends.js +29 -0
- package/dist/checkpointer/internal/query.d.ts +2 -1
- package/dist/checkpointer/internal/query.js +9 -3
- package/dist/checkpointer/internal/regular-write.d.ts +28 -0
- package/dist/checkpointer/internal/regular-write.js +66 -0
- package/dist/checkpointer/internal/setup.d.ts +3 -1
- package/dist/checkpointer/internal/setup.js +10 -8
- package/dist/checkpointer/internal/special-write-cas.d.ts +29 -0
- package/dist/checkpointer/internal/special-write-cas.js +104 -0
- package/dist/checkpointer/internal/special-write-cleanup.d.ts +19 -14
- package/dist/checkpointer/internal/special-write-cleanup.js +35 -87
- package/dist/checkpointer/internal/special-write-verify.d.ts +53 -0
- package/dist/checkpointer/internal/special-write-verify.js +80 -0
- package/dist/checkpointer/internal/stored-channels.d.ts +31 -0
- package/dist/checkpointer/internal/stored-channels.js +70 -0
- package/dist/checkpointer/internal/validation.d.ts +11 -6
- package/dist/checkpointer/internal/validation.js +19 -9
- package/dist/checkpointer/internal/write-guard.d.ts +8 -9
- package/dist/checkpointer/internal/write-guard.js +16 -16
- package/dist/checkpointer/internal/write-index.d.ts +8 -1
- package/dist/checkpointer/internal/write-index.js +6 -3
- package/dist/checkpointer/saver.d.ts +50 -10
- package/dist/checkpointer/saver.js +59 -17
- package/dist/checkpointer/types.d.ts +14 -1
- package/dist/checkpointer/types.js +0 -1
- package/dist/factory/factory.d.ts +22 -25
- package/dist/factory/factory.js +58 -18
- package/dist/factory/types.d.ts +57 -0
- package/dist/factory/types.js +2 -0
- package/dist/history/actions/add-messages.d.ts +1 -2
- package/dist/history/actions/add-messages.js +4 -4
- package/dist/history/actions/clear.d.ts +3 -2
- package/dist/history/actions/clear.js +5 -2
- package/dist/history/actions/get-messages.d.ts +13 -6
- package/dist/history/actions/get-messages.js +63 -42
- package/dist/history/actions/list-sessions.d.ts +1 -1
- package/dist/history/actions/list-sessions.js +8 -12
- package/dist/history/actions/reconcile-count.d.ts +1 -2
- package/dist/history/actions/reconcile-count.js +20 -7
- package/dist/history/chat-message-history.d.ts +51 -26
- package/dist/history/chat-message-history.js +60 -30
- package/dist/history/internal/append-saga.d.ts +7 -2
- package/dist/history/internal/append-saga.js +58 -14
- package/dist/history/internal/compensation.d.ts +6 -2
- package/dist/history/internal/compensation.js +14 -6
- package/dist/history/internal/item-mapper.d.ts +0 -3
- package/dist/history/internal/item-mapper.js +2 -8
- package/dist/history/internal/keys.d.ts +0 -1
- package/dist/history/internal/keys.js +0 -1
- package/dist/history/internal/message-chunker.d.ts +0 -1
- package/dist/history/internal/message-chunker.js +0 -1
- package/dist/history/internal/message-transaction.d.ts +0 -1
- package/dist/history/internal/message-transaction.js +3 -2
- package/dist/history/internal/message-window.d.ts +17 -0
- package/dist/history/internal/message-window.js +49 -0
- package/dist/history/internal/query.d.ts +16 -3
- package/dist/history/internal/query.js +13 -5
- package/dist/history/internal/session-count.d.ts +8 -2
- package/dist/history/internal/session-count.js +14 -8
- package/dist/history/internal/session-title.d.ts +0 -1
- package/dist/history/internal/session-title.js +1 -2
- package/dist/history/internal/session-update.d.ts +0 -1
- package/dist/history/internal/session-update.js +0 -1
- package/dist/history/internal/setup.d.ts +3 -1
- package/dist/history/internal/setup.js +16 -8
- package/dist/history/internal/title-generator.d.ts +0 -1
- package/dist/history/internal/title-generator.js +19 -3
- package/dist/history/internal/ttl-anchor.d.ts +1 -2
- package/dist/history/internal/ttl-anchor.js +5 -5
- package/dist/history/internal/validation.d.ts +19 -3
- package/dist/history/internal/validation.js +41 -4
- package/dist/history/session-adapter.d.ts +9 -3
- package/dist/history/session-adapter.js +6 -3
- package/dist/history/types.d.ts +23 -2
- package/dist/history/types.js +0 -1
- package/dist/index.d.ts +12 -5
- package/dist/index.js +5 -3
- package/dist/shared/clock.d.ts +6 -1
- package/dist/shared/clock.js +9 -1
- package/dist/shared/codec/codec.d.ts +26 -17
- package/dist/shared/codec/codec.js +46 -24
- package/dist/shared/codec/compression.d.ts +1 -2
- package/dist/shared/codec/compression.js +2 -3
- package/dist/shared/codec/descriptor-keys.d.ts +11 -3
- package/dist/shared/codec/descriptor-keys.js +2 -2
- package/dist/shared/codec/encode.d.ts +13 -0
- package/dist/shared/codec/encode.js +43 -0
- package/dist/shared/codec/json-serde.d.ts +0 -1
- package/dist/shared/codec/json-serde.js +0 -1
- package/dist/shared/codec/payload-loss.d.ts +12 -0
- package/dist/shared/codec/payload-loss.js +38 -0
- package/dist/shared/codec/s3/adapter-config.d.ts +13 -0
- package/dist/shared/codec/s3/adapter-config.js +22 -0
- package/dist/shared/codec/s3/bounded-body.d.ts +14 -0
- package/dist/shared/codec/s3/bounded-body.js +47 -0
- package/dist/shared/codec/s3/client-types.d.ts +34 -0
- package/dist/shared/codec/s3/client-types.js +7 -0
- package/dist/shared/codec/s3/client.d.ts +11 -5
- package/dist/shared/codec/s3/client.js +25 -3
- package/dist/shared/codec/s3/config.d.ts +32 -5
- package/dist/shared/codec/s3/config.js +37 -5
- package/dist/shared/codec/s3/delete.d.ts +0 -1
- package/dist/shared/codec/s3/delete.js +0 -1
- package/dist/shared/codec/s3/key-scope.d.ts +23 -0
- package/dist/shared/codec/s3/key-scope.js +44 -0
- package/dist/shared/codec/s3/lifecycle.d.ts +11 -5
- package/dist/shared/codec/s3/lifecycle.js +32 -16
- package/dist/shared/codec/s3/offloader.d.ts +6 -2
- package/dist/shared/codec/s3/offloader.js +21 -3
- package/dist/shared/codec/s3/orphans.d.ts +6 -1
- package/dist/shared/codec/s3/orphans.js +15 -2
- package/dist/shared/codec/s3/read-write.d.ts +7 -3
- package/dist/shared/codec/s3/read-write.js +16 -8
- package/dist/shared/codec/s3/retry.d.ts +4 -4
- package/dist/shared/codec/s3/retry.js +13 -16
- package/dist/shared/concurrency.d.ts +6 -0
- package/dist/shared/concurrency.js +30 -0
- package/dist/shared/constants.d.ts +68 -5
- package/dist/shared/constants.js +70 -7
- package/dist/shared/dynamodb/abort.d.ts +9 -0
- package/dist/shared/dynamodb/abort.js +27 -0
- package/dist/shared/dynamodb/backoff.d.ts +4 -4
- package/dist/shared/dynamodb/backoff.js +7 -7
- package/dist/shared/dynamodb/batch-write.d.ts +0 -1
- package/dist/shared/dynamodb/batch-write.js +0 -1
- package/dist/shared/dynamodb/cancellation.d.ts +0 -1
- package/dist/shared/dynamodb/cancellation.js +0 -1
- package/dist/shared/dynamodb/client.d.ts +9 -2
- package/dist/shared/dynamodb/client.js +24 -1
- package/dist/shared/dynamodb/conditional-put.d.ts +67 -0
- package/dist/shared/dynamodb/conditional-put.js +76 -0
- package/dist/shared/dynamodb/drain-unprocessed.d.ts +3 -1
- package/dist/shared/dynamodb/drain-unprocessed.js +1 -2
- package/dist/shared/dynamodb/expiry.d.ts +16 -0
- package/dist/shared/dynamodb/expiry.js +29 -0
- package/dist/shared/dynamodb/paginate-core.d.ts +5 -3
- package/dist/shared/dynamodb/paginate-core.js +47 -17
- package/dist/shared/dynamodb/paginate.d.ts +0 -1
- package/dist/shared/dynamodb/paginate.js +1 -2
- package/dist/shared/dynamodb/partition-delete.d.ts +7 -1
- package/dist/shared/dynamodb/partition-delete.js +4 -3
- package/dist/shared/dynamodb/retry-classifier.d.ts +10 -2
- package/dist/shared/dynamodb/retry-classifier.js +42 -11
- package/dist/shared/dynamodb/retry-policy.d.ts +26 -0
- package/dist/shared/dynamodb/retry-policy.js +22 -0
- package/dist/shared/dynamodb/retry.d.ts +14 -1
- package/dist/shared/dynamodb/retry.js +11 -7
- package/dist/shared/dynamodb/scan.d.ts +0 -1
- package/dist/shared/dynamodb/scan.js +1 -2
- package/dist/shared/dynamodb/types.d.ts +1 -2
- package/dist/shared/dynamodb/types.js +0 -1
- package/dist/shared/errors/base-error.d.ts +14 -6
- package/dist/shared/errors/base-error.js +8 -9
- package/dist/shared/errors/boundary.d.ts +18 -0
- package/dist/shared/errors/boundary.js +46 -0
- package/dist/shared/errors/error-code.d.ts +2 -2
- package/dist/shared/errors/error-code.js +1 -1
- package/dist/shared/errors/errors.d.ts +13 -13
- package/dist/shared/errors/errors.js +18 -16
- package/dist/shared/errors/upstream-error.d.ts +16 -0
- package/dist/shared/errors/upstream-error.js +27 -0
- package/dist/shared/errors/wrap-error.d.ts +0 -9
- package/dist/shared/errors/wrap-error.js +0 -15
- package/dist/shared/logging/logger.d.ts +6 -2
- package/dist/shared/logging/logger.js +0 -1
- package/dist/shared/logging/redaction-walk.d.ts +2 -2
- package/dist/shared/logging/redaction-walk.js +38 -18
- package/dist/shared/logging/redaction.d.ts +14 -6
- package/dist/shared/logging/redaction.js +19 -4
- package/dist/shared/logging/secret-patterns.d.ts +54 -3
- package/dist/shared/logging/secret-patterns.js +67 -8
- package/dist/shared/options.d.ts +9 -4
- package/dist/shared/options.js +0 -1
- package/dist/shared/ulid.d.ts +15 -2
- package/dist/shared/ulid.js +35 -3
- package/dist/shared/validation/options.d.ts +8 -0
- package/dist/shared/validation/options.js +90 -0
- package/dist/shared/validation/primitives.d.ts +14 -10
- package/dist/shared/validation/primitives.js +23 -25
- package/dist/shared/validation/ttl.d.ts +14 -7
- package/dist/shared/validation/ttl.js +29 -11
- package/dist/store/actions/get.d.ts +11 -3
- package/dist/store/actions/get.js +52 -14
- package/dist/store/actions/list-namespaces.d.ts +0 -1
- package/dist/store/actions/list-namespaces.js +10 -6
- package/dist/store/actions/put.d.ts +0 -1
- package/dist/store/actions/put.js +27 -28
- package/dist/store/actions/reconcile-vector-index.d.ts +3 -2
- package/dist/store/actions/reconcile-vector-index.js +2 -3
- package/dist/store/actions/search.d.ts +1 -2
- package/dist/store/actions/search.js +11 -38
- package/dist/store/internal/backend-search.d.ts +1 -2
- package/dist/store/internal/backend-search.js +14 -7
- package/dist/store/internal/batch-plan.d.ts +11 -0
- package/dist/store/internal/batch-plan.js +52 -0
- package/dist/store/internal/candidates.d.ts +23 -0
- package/dist/store/internal/candidates.js +94 -0
- package/dist/store/internal/filter.d.ts +0 -1
- package/dist/store/internal/filter.js +25 -6
- package/dist/store/internal/index-reconcile.d.ts +5 -6
- package/dist/store/internal/index-reconcile.js +32 -13
- package/dist/store/internal/index-sync.d.ts +0 -1
- package/dist/store/internal/index-sync.js +0 -1
- package/dist/store/internal/item-mapper.d.ts +6 -3
- package/dist/store/internal/item-mapper.js +16 -6
- package/dist/store/internal/keys.d.ts +0 -1
- package/dist/store/internal/keys.js +0 -1
- package/dist/store/internal/namespace-match.d.ts +0 -1
- package/dist/store/internal/namespace-match.js +0 -1
- package/dist/store/internal/option-validation.d.ts +13 -0
- package/dist/store/internal/option-validation.js +77 -0
- package/dist/store/internal/overwrite-swap.d.ts +32 -0
- package/dist/store/internal/overwrite-swap.js +68 -0
- package/dist/store/internal/persist.d.ts +24 -7
- package/dist/store/internal/persist.js +49 -19
- package/dist/store/internal/query.d.ts +6 -1
- package/dist/store/internal/query.js +17 -1
- package/dist/store/internal/ranker.d.ts +7 -2
- package/dist/store/internal/ranker.js +10 -2
- package/dist/store/internal/read-existing.d.ts +23 -0
- package/dist/store/internal/read-existing.js +41 -0
- package/dist/store/internal/score-direction.d.ts +31 -0
- package/dist/store/internal/score-direction.js +38 -0
- package/dist/store/internal/search-filter.d.ts +0 -1
- package/dist/store/internal/search-filter.js +0 -1
- package/dist/store/internal/semantic-search.d.ts +26 -5
- package/dist/store/internal/semantic-search.js +59 -19
- package/dist/store/internal/setup.d.ts +6 -12
- package/dist/store/internal/setup.js +12 -24
- package/dist/store/internal/text-path.d.ts +17 -0
- package/dist/store/internal/text-path.js +147 -0
- package/dist/store/internal/validation.d.ts +8 -3
- package/dist/store/internal/validation.js +21 -5
- package/dist/store/internal/write-verify.d.ts +27 -9
- package/dist/store/internal/write-verify.js +35 -19
- package/dist/store/store.d.ts +37 -9
- package/dist/store/store.js +52 -17
- package/dist/store/types.d.ts +22 -2
- package/dist/store/types.js +0 -1
- package/dist/store/vector-backend.d.ts +6 -7
- package/dist/store/vector-backend.js +0 -1
- package/package.json +21 -15
- 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.map +0 -1
- package/dist/checkpointer/internal/assemble.js.map +0 -1
- package/dist/checkpointer/internal/configurable.d.ts.map +0 -1
- package/dist/checkpointer/internal/configurable.js.map +0 -1
- package/dist/checkpointer/internal/fetch.d.ts.map +0 -1
- package/dist/checkpointer/internal/fetch.js.map +0 -1
- package/dist/checkpointer/internal/filter-match.d.ts.map +0 -1
- package/dist/checkpointer/internal/filter-match.js.map +0 -1
- package/dist/checkpointer/internal/item-reader.d.ts.map +0 -1
- package/dist/checkpointer/internal/item-reader.js.map +0 -1
- package/dist/checkpointer/internal/item-writer.d.ts.map +0 -1
- package/dist/checkpointer/internal/item-writer.js.map +0 -1
- package/dist/checkpointer/internal/keys.d.ts.map +0 -1
- package/dist/checkpointer/internal/keys.js.map +0 -1
- package/dist/checkpointer/internal/query.d.ts.map +0 -1
- 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-cleanup.d.ts.map +0 -1
- package/dist/checkpointer/internal/special-write-cleanup.js.map +0 -1
- package/dist/checkpointer/internal/validation.d.ts.map +0 -1
- package/dist/checkpointer/internal/validation.js.map +0 -1
- package/dist/checkpointer/internal/write-guard.d.ts.map +0 -1
- package/dist/checkpointer/internal/write-guard.js.map +0 -1
- package/dist/checkpointer/internal/write-index.d.ts.map +0 -1
- 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.map +0 -1
- package/dist/history/internal/append-saga.js.map +0 -1
- package/dist/history/internal/compensation.d.ts.map +0 -1
- package/dist/history/internal/compensation.js.map +0 -1
- package/dist/history/internal/item-mapper.d.ts.map +0 -1
- package/dist/history/internal/item-mapper.js.map +0 -1
- package/dist/history/internal/keys.d.ts.map +0 -1
- package/dist/history/internal/keys.js.map +0 -1
- package/dist/history/internal/message-chunker.d.ts.map +0 -1
- package/dist/history/internal/message-chunker.js.map +0 -1
- package/dist/history/internal/message-transaction.d.ts.map +0 -1
- package/dist/history/internal/message-transaction.js.map +0 -1
- package/dist/history/internal/query.d.ts.map +0 -1
- package/dist/history/internal/query.js.map +0 -1
- package/dist/history/internal/session-count.d.ts.map +0 -1
- package/dist/history/internal/session-count.js.map +0 -1
- package/dist/history/internal/session-title.d.ts.map +0 -1
- package/dist/history/internal/session-title.js.map +0 -1
- package/dist/history/internal/session-update.d.ts.map +0 -1
- 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.map +0 -1
- package/dist/history/internal/title-generator.js.map +0 -1
- package/dist/history/internal/ttl-anchor.d.ts.map +0 -1
- package/dist/history/internal/ttl-anchor.js.map +0 -1
- package/dist/history/internal/validation.d.ts.map +0 -1
- 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.map +0 -1
- 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.map +0 -1
- 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.map +0 -1
- package/dist/shared/codec/s3/orphans.js.map +0 -1
- package/dist/shared/codec/s3/read-write.d.ts.map +0 -1
- package/dist/shared/codec/s3/read-write.js.map +0 -1
- package/dist/shared/codec/s3/retry.d.ts.map +0 -1
- package/dist/shared/codec/s3/retry.js.map +0 -1
- package/dist/shared/constants.d.ts.map +0 -1
- package/dist/shared/constants.js.map +0 -1
- package/dist/shared/dynamodb/backoff.d.ts.map +0 -1
- 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/drain-unprocessed.d.ts.map +0 -1
- package/dist/shared/dynamodb/drain-unprocessed.js.map +0 -1
- package/dist/shared/dynamodb/paginate-core.d.ts.map +0 -1
- 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.map +0 -1
- 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.map +0 -1
- package/dist/shared/dynamodb/scan.js.map +0 -1
- package/dist/shared/dynamodb/types.d.ts.map +0 -1
- 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.map +0 -1
- 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.map +0 -1
- 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.map +0 -1
- 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.map +0 -1
- 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.map +0 -1
- package/dist/store/internal/index-reconcile.js.map +0 -1
- package/dist/store/internal/index-sync.d.ts.map +0 -1
- package/dist/store/internal/index-sync.js.map +0 -1
- package/dist/store/internal/item-mapper.d.ts.map +0 -1
- package/dist/store/internal/item-mapper.js.map +0 -1
- package/dist/store/internal/keys.d.ts.map +0 -1
- package/dist/store/internal/keys.js.map +0 -1
- package/dist/store/internal/namespace-match.d.ts.map +0 -1
- package/dist/store/internal/namespace-match.js.map +0 -1
- package/dist/store/internal/persist.d.ts.map +0 -1
- package/dist/store/internal/persist.js.map +0 -1
- package/dist/store/internal/query.d.ts.map +0 -1
- package/dist/store/internal/query.js.map +0 -1
- package/dist/store/internal/ranker.d.ts.map +0 -1
- package/dist/store/internal/ranker.js.map +0 -1
- package/dist/store/internal/search-filter.d.ts.map +0 -1
- 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.map +0 -1
- package/dist/store/internal/validation.js.map +0 -1
- package/dist/store/internal/write-verify.d.ts.map +0 -1
- 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,5 +1,13 @@
|
|
|
1
1
|
import type { Item } from '@langchain/langgraph-checkpoint';
|
|
2
2
|
import type { StoreContext } from '../internal/setup';
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Retrieve a single item by namespace and key (strongly consistent), or null.
|
|
5
|
+
*
|
|
6
|
+
* An offloaded item can lose a race with a concurrent overwrite: between the
|
|
7
|
+
* row read and the S3 download the writer commits a new descriptor and deletes
|
|
8
|
+
* the object this read was about to fetch. That surfaces as `NoSuchKey`, and
|
|
9
|
+
* one strongly-consistent re-read settles it — the row now points at the new
|
|
10
|
+
* object (return that), is gone (null), or still points at the same missing
|
|
11
|
+
* object (a genuine loss, rethrown). Any other download failure propagates.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getItem(context: StoreContext, namespace: string[], key: string, signal?: AbortSignal): Promise<Item | null>;
|
|
@@ -1,35 +1,73 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getItem = getItem;
|
|
4
|
+
const clock_1 = require("../../shared/clock");
|
|
5
|
+
const codec_1 = require("../../shared/codec/codec");
|
|
6
|
+
const payload_loss_1 = require("../../shared/codec/payload-loss");
|
|
7
|
+
const expiry_1 = require("../../shared/dynamodb/expiry");
|
|
4
8
|
const retry_1 = require("../../shared/dynamodb/retry");
|
|
9
|
+
const retry_policy_1 = require("../../shared/dynamodb/retry-policy");
|
|
5
10
|
const item_mapper_1 = require("../internal/item-mapper");
|
|
6
11
|
const keys_1 = require("../internal/keys");
|
|
7
12
|
const validation_1 = require("../internal/validation");
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Read the row strongly consistently and narrow it rather than cast. A
|
|
15
|
+
* foreign row sharing this key has no `namespace`, and one carrying a `value`
|
|
16
|
+
* PayloadDescriptor in the same shape a store item uses (a checkpointer WRITE
|
|
17
|
+
* row) would otherwise decode cleanly and be handed back as the caller's own
|
|
18
|
+
* value.
|
|
19
|
+
*/
|
|
20
|
+
async function readRow(context, namespace, key, signal) {
|
|
12
21
|
const result = await (0, retry_1.withDynamoDBRetry)(() => context.client.get({
|
|
13
22
|
TableName: context.tableName,
|
|
14
23
|
Key: { PK: (0, keys_1.partitionKey)(namespace), SK: (0, keys_1.sortKey)(namespace, key) },
|
|
15
24
|
ConsistentRead: true,
|
|
16
|
-
}));
|
|
25
|
+
}), (0, retry_policy_1.retryFor)(context, signal));
|
|
17
26
|
if (!result.Item)
|
|
18
|
-
return
|
|
19
|
-
/**
|
|
20
|
-
* Narrow rather than cast. A foreign row sharing this key has no
|
|
21
|
-
* `namespace`, and one carrying a `value` PayloadDescriptor in the same
|
|
22
|
-
* shape a store item uses (a checkpointer WRITE row) would otherwise decode
|
|
23
|
-
* cleanly and be handed back as the caller's own value.
|
|
24
|
-
*/
|
|
27
|
+
return undefined;
|
|
25
28
|
const record = (0, item_mapper_1.narrowStoreRecord)(result.Item);
|
|
26
29
|
if (!record) {
|
|
27
30
|
context.logger.warn('store.get: ignored a row that is not a store item', {
|
|
28
31
|
partitionKey: (0, keys_1.partitionKey)(namespace),
|
|
29
32
|
sortKey: (0, keys_1.sortKey)(namespace, key),
|
|
30
33
|
});
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
/** A row past its ttl is absent to every reader, however long DynamoDB's sweep lags. */
|
|
37
|
+
return (0, expiry_1.isExpiredRow)(record, (0, clock_1.nowSeconds)()) ? undefined : record;
|
|
38
|
+
}
|
|
39
|
+
/** True when both records point at the same offloaded object. */
|
|
40
|
+
function sameObject(a, b) {
|
|
41
|
+
return (a.value.location === codec_1.PayloadLocation.S3 &&
|
|
42
|
+
b.value.location === codec_1.PayloadLocation.S3 &&
|
|
43
|
+
a.value.s3Key === b.value.s3Key);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Retrieve a single item by namespace and key (strongly consistent), or null.
|
|
47
|
+
*
|
|
48
|
+
* An offloaded item can lose a race with a concurrent overwrite: between the
|
|
49
|
+
* row read and the S3 download the writer commits a new descriptor and deletes
|
|
50
|
+
* the object this read was about to fetch. That surfaces as `NoSuchKey`, and
|
|
51
|
+
* one strongly-consistent re-read settles it — the row now points at the new
|
|
52
|
+
* object (return that), is gone (null), or still points at the same missing
|
|
53
|
+
* object (a genuine loss, rethrown). Any other download failure propagates.
|
|
54
|
+
*/
|
|
55
|
+
async function getItem(context, namespace, key, signal) {
|
|
56
|
+
(0, validation_1.validateStoreKey)(namespace, key);
|
|
57
|
+
const record = await readRow(context, namespace, key, signal);
|
|
58
|
+
if (!record)
|
|
31
59
|
return null;
|
|
60
|
+
try {
|
|
61
|
+
return await (0, item_mapper_1.readStoreItem)(context, record);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (!(0, payload_loss_1.isMissingObjectError)(error))
|
|
65
|
+
throw error;
|
|
66
|
+
const fresh = await readRow(context, namespace, key, signal);
|
|
67
|
+
if (!fresh)
|
|
68
|
+
return null;
|
|
69
|
+
if (sameObject(record, fresh))
|
|
70
|
+
throw error;
|
|
71
|
+
return (0, item_mapper_1.readStoreItem)(context, fresh);
|
|
32
72
|
}
|
|
33
|
-
return (0, item_mapper_1.readStoreItem)(context, record);
|
|
34
73
|
}
|
|
35
|
-
//# sourceMappingURL=get.js.map
|
|
@@ -6,4 +6,3 @@ import type { StoreContext } from '../internal/setup';
|
|
|
6
6
|
* the read to a native Query; otherwise it falls back to a filtered Scan.
|
|
7
7
|
*/
|
|
8
8
|
export declare function listNamespaces(context: StoreContext, op: ListNamespacesOperation): Promise<string[][]>;
|
|
9
|
-
//# sourceMappingURL=list-namespaces.d.ts.map
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.listNamespaces = listNamespaces;
|
|
4
|
+
const clock_1 = require("../../shared/clock");
|
|
5
|
+
const expiry_1 = require("../../shared/dynamodb/expiry");
|
|
4
6
|
const paginate_1 = require("../../shared/dynamodb/paginate");
|
|
5
7
|
const scan_1 = require("../../shared/dynamodb/scan");
|
|
6
8
|
const item_mapper_1 = require("../internal/item-mapper");
|
|
@@ -8,18 +10,20 @@ const keys_1 = require("../internal/keys");
|
|
|
8
10
|
const namespace_match_1 = require("../internal/namespace-match");
|
|
9
11
|
const query_1 = require("../internal/query");
|
|
10
12
|
const validation_1 = require("../internal/validation");
|
|
11
|
-
function namespaceSource(context, op) {
|
|
13
|
+
function namespaceSource(context, op, now) {
|
|
12
14
|
const root = (0, namespace_match_1.prefixRoot)(op.matchConditions);
|
|
13
15
|
if (root.length > 0) {
|
|
14
16
|
return (0, paginate_1.paginateQuery)({
|
|
17
|
+
retry: context.retry,
|
|
15
18
|
client: context.client,
|
|
16
|
-
params: (0, query_1.scopedQuery)(context.tableName, root),
|
|
19
|
+
params: (0, expiry_1.withoutExpired)((0, query_1.projectKeys)((0, query_1.scopedQuery)(context.tableName, root)), now),
|
|
17
20
|
maxItems: context.maxScanItems,
|
|
18
21
|
});
|
|
19
22
|
}
|
|
20
23
|
return (0, scan_1.paginateScan)({
|
|
24
|
+
retry: context.retry,
|
|
21
25
|
client: context.client,
|
|
22
|
-
params: (0, query_1.storeScan)(context.tableName),
|
|
26
|
+
params: (0, expiry_1.withoutExpired)((0, query_1.projectKeys)((0, query_1.storeScan)(context.tableName)), now),
|
|
23
27
|
maxItems: context.maxScanItems,
|
|
24
28
|
});
|
|
25
29
|
}
|
|
@@ -31,11 +35,12 @@ function namespaceSource(context, op) {
|
|
|
31
35
|
async function listNamespaces(context, op) {
|
|
32
36
|
(0, validation_1.validatePaging)(op.offset, op.limit);
|
|
33
37
|
(0, validation_1.validateMaxDepth)(op.maxDepth);
|
|
38
|
+
const now = (0, clock_1.nowSeconds)();
|
|
34
39
|
const seen = new Set();
|
|
35
40
|
const namespaces = [];
|
|
36
|
-
for await (const raw of namespaceSource(context, op)) {
|
|
41
|
+
for await (const raw of namespaceSource(context, op, now)) {
|
|
37
42
|
const record = (0, item_mapper_1.narrowStoreRecord)(raw);
|
|
38
|
-
if (!record)
|
|
43
|
+
if (!record || (0, expiry_1.isExpiredRow)(record, now))
|
|
39
44
|
continue;
|
|
40
45
|
const namespace = record.namespace;
|
|
41
46
|
if (op.matchConditions &&
|
|
@@ -52,4 +57,3 @@ async function listNamespaces(context, op) {
|
|
|
52
57
|
namespaces.sort((a, b) => a.join(keys_1.NAMESPACE_SEPARATOR).localeCompare(b.join(keys_1.NAMESPACE_SEPARATOR)));
|
|
53
58
|
return namespaces.slice(op.offset, op.offset + op.limit);
|
|
54
59
|
}
|
|
55
|
-
//# sourceMappingURL=list-namespaces.js.map
|
|
@@ -11,45 +11,46 @@ const index_sync_1 = require("../internal/index-sync");
|
|
|
11
11
|
const item_mapper_1 = require("../internal/item-mapper");
|
|
12
12
|
const keys_1 = require("../internal/keys");
|
|
13
13
|
const persist_1 = require("../internal/persist");
|
|
14
|
+
const read_existing_1 = require("../internal/read-existing");
|
|
14
15
|
const semantic_search_1 = require("../internal/semantic-search");
|
|
15
16
|
const validation_1 = require("../internal/validation");
|
|
16
17
|
const write_verify_1 = require("../internal/write-verify");
|
|
17
|
-
async function readExisting(context, pk, sk) {
|
|
18
|
-
const existing = await (0, retry_1.withDynamoDBRetry)(() => context.client.get({
|
|
19
|
-
TableName: context.tableName,
|
|
20
|
-
Key: { PK: pk, SK: sk },
|
|
21
|
-
ConsistentRead: true,
|
|
22
|
-
ProjectionExpression: '#c, #v',
|
|
23
|
-
ExpressionAttributeNames: { '#c': 'createdAt', '#v': 'value' },
|
|
24
|
-
}));
|
|
25
|
-
return {
|
|
26
|
-
createdAt: existing.Item?.createdAt,
|
|
27
|
-
value: existing.Item?.value,
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
18
|
/**
|
|
31
19
|
* Delete the item and, when a vector backend is configured, drop its vector.
|
|
32
20
|
*
|
|
21
|
+
* The delete asks DynamoDB for the row it removed (`ReturnValues: 'ALL_OLD'`),
|
|
22
|
+
* so S3 cleanup targets the descriptor that was actually removed rather than
|
|
23
|
+
* one read a moment earlier — a concurrent put between a pre-read and the
|
|
24
|
+
* delete used to leave its just-written object orphaned — and the delete costs
|
|
25
|
+
* one request instead of two.
|
|
26
|
+
*
|
|
33
27
|
* A retry-exhausted failure is *ambiguous*: the delete may have landed
|
|
34
|
-
* server-side with only its acknowledgement lost. Mirroring `persistRecord
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
28
|
+
* server-side with only its acknowledgement lost. Mirroring `persistRecord`,
|
|
29
|
+
* that case is resolved with a strongly-consistent read — if the row is gone
|
|
30
|
+
* the delete succeeded and the vector-backend delete must still run. The
|
|
31
|
+
* removed descriptor travelled with the lost response, so that one object, if
|
|
32
|
+
* any, is left to the lifecycle rule. Any other failure, or a row still
|
|
33
|
+
* present, propagates unchanged.
|
|
40
34
|
*/
|
|
41
35
|
async function deleteStoreItem(context, op, pk, sk) {
|
|
42
|
-
|
|
36
|
+
let removed;
|
|
43
37
|
try {
|
|
44
|
-
await (0, retry_1.withDynamoDBRetry)(() => context.client.delete({
|
|
38
|
+
const result = await (0, retry_1.withDynamoDBRetry)(() => context.client.delete({
|
|
39
|
+
TableName: context.tableName,
|
|
40
|
+
Key: { PK: pk, SK: sk },
|
|
41
|
+
ReturnValues: 'ALL_OLD',
|
|
42
|
+
}), context.retry);
|
|
43
|
+
removed = result.Attributes?.value;
|
|
45
44
|
}
|
|
46
45
|
catch (error) {
|
|
47
46
|
const landed = (0, write_verify_1.isRetryExhausted)(error) && (await (0, write_verify_1.rowIsAbsent)(context, { PK: pk, SK: sk }));
|
|
48
47
|
if (!landed)
|
|
49
48
|
throw error;
|
|
50
49
|
}
|
|
51
|
-
if (context.offloader) {
|
|
52
|
-
await (0, orphans_1.cleanUpS3Orphans)(context.offloader, (0, descriptor_keys_1.collectS3Keys)(
|
|
50
|
+
if (context.offloader && removed) {
|
|
51
|
+
await (0, orphans_1.cleanUpS3Orphans)(context.offloader, (0, descriptor_keys_1.collectS3Keys)([removed]), 'store.delete', context.logger, {
|
|
52
|
+
scope: [...op.namespace, op.key],
|
|
53
|
+
});
|
|
53
54
|
}
|
|
54
55
|
if (context.vectorBackend) {
|
|
55
56
|
await (0, index_sync_1.syncVectorIndex)(context.vectorBackend, op.namespace, op.key, undefined, context.logger);
|
|
@@ -69,8 +70,7 @@ async function resolveEmbedding(context, op, value) {
|
|
|
69
70
|
* stored on the item — DynamoDB always holds the canonical item.
|
|
70
71
|
*/
|
|
71
72
|
async function putItem(context, op) {
|
|
72
|
-
(0, validation_1.
|
|
73
|
-
(0, validation_1.validateKey)(op.key);
|
|
73
|
+
(0, validation_1.validateStoreKey)(op.namespace, op.key);
|
|
74
74
|
const pk = (0, keys_1.partitionKey)(op.namespace);
|
|
75
75
|
const sk = (0, keys_1.sortKey)(op.namespace, op.key);
|
|
76
76
|
if (op.value === null) {
|
|
@@ -79,7 +79,7 @@ async function putItem(context, op) {
|
|
|
79
79
|
}
|
|
80
80
|
const value = op.value;
|
|
81
81
|
const timestamp = (0, clock_1.nowIso)();
|
|
82
|
-
const existing = await readExisting(context, pk, sk);
|
|
82
|
+
const existing = await (0, read_existing_1.readExisting)(context, pk, sk);
|
|
83
83
|
const embedding = await resolveEmbedding(context, op, value);
|
|
84
84
|
const ttlTimestamp = context.ttl ? (0, ttl_1.calculateTtlTimestamp)(context.ttl) : undefined;
|
|
85
85
|
const record = await (0, item_mapper_1.buildStoreItem)(context, op.namespace, op.key, value, {
|
|
@@ -89,9 +89,8 @@ async function putItem(context, op) {
|
|
|
89
89
|
ttlTimestamp,
|
|
90
90
|
nonce: (0, node_crypto_1.randomUUID)(),
|
|
91
91
|
});
|
|
92
|
-
await (0, persist_1.persistRecord)(context, record, existing
|
|
92
|
+
await (0, persist_1.persistRecord)(context, record, existing);
|
|
93
93
|
if (context.vectorBackend) {
|
|
94
94
|
await (0, index_sync_1.syncVectorIndex)(context.vectorBackend, op.namespace, op.key, embedding, context.logger);
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
-
//# sourceMappingURL=put.js.map
|
|
@@ -13,5 +13,6 @@ export interface VectorReconcileResult {
|
|
|
13
13
|
* overrides are not reproduced. Requires a configured `index` and
|
|
14
14
|
* `vectorBackend`; the prefix must be a non-empty namespace.
|
|
15
15
|
*/
|
|
16
|
-
export declare function reconcileVectorIndex(context: StoreContext, namespacePrefix: string[]
|
|
17
|
-
|
|
16
|
+
export declare function reconcileVectorIndex(context: StoreContext, namespacePrefix: string[], options?: {
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
}): Promise<VectorReconcileResult>;
|
|
@@ -13,15 +13,14 @@ const validation_1 = require("../internal/validation");
|
|
|
13
13
|
* overrides are not reproduced. Requires a configured `index` and
|
|
14
14
|
* `vectorBackend`; the prefix must be a non-empty namespace.
|
|
15
15
|
*/
|
|
16
|
-
async function reconcileVectorIndex(context, namespacePrefix) {
|
|
16
|
+
async function reconcileVectorIndex(context, namespacePrefix, options = {}) {
|
|
17
17
|
(0, validation_1.validateNamespace)(namespacePrefix);
|
|
18
18
|
if (!context.index || !context.vectorBackend) {
|
|
19
19
|
throw new errors_1.ValidationError('reconcileVectorIndex requires a configured index and vectorBackend');
|
|
20
20
|
}
|
|
21
21
|
const backend = context.vectorBackend;
|
|
22
|
-
const targets = await (0, index_reconcile_1.collectReconcileTargets)(context, namespacePrefix);
|
|
22
|
+
const targets = await (0, index_reconcile_1.collectReconcileTargets)(context, namespacePrefix, options.signal);
|
|
23
23
|
const upserted = await (0, index_reconcile_1.pushEmbeddings)(backend, targets);
|
|
24
24
|
const pruned = await (0, index_reconcile_1.pruneOrphans)(context, backend, namespacePrefix, targets);
|
|
25
25
|
return { upserted, pruned };
|
|
26
26
|
}
|
|
27
|
-
//# sourceMappingURL=reconcile-vector-index.js.map
|
|
@@ -6,5 +6,4 @@ import type { StoreContext } from '../internal/setup';
|
|
|
6
6
|
* falls back to a (filtered) Scan. Semantic ranking uses the configured
|
|
7
7
|
* VectorBackend when present, else an in-memory cosine ranking (capped).
|
|
8
8
|
*/
|
|
9
|
-
export declare function searchItems(context: StoreContext, op: SearchOperation): Promise<SearchItem[]>;
|
|
10
|
-
//# sourceMappingURL=search.d.ts.map
|
|
9
|
+
export declare function searchItems(context: StoreContext, op: SearchOperation, signal?: AbortSignal): Promise<SearchItem[]>;
|
|
@@ -1,61 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.searchItems = searchItems;
|
|
4
|
-
const paginate_1 = require("../../shared/dynamodb/paginate");
|
|
5
|
-
const scan_1 = require("../../shared/dynamodb/scan");
|
|
6
4
|
const backend_search_1 = require("../internal/backend-search");
|
|
7
|
-
const
|
|
8
|
-
const keys_1 = require("../internal/keys");
|
|
9
|
-
const query_1 = require("../internal/query");
|
|
5
|
+
const candidates_1 = require("../internal/candidates");
|
|
10
6
|
const ranker_1 = require("../internal/ranker");
|
|
11
|
-
const
|
|
7
|
+
const semantic_search_1 = require("../internal/semantic-search");
|
|
12
8
|
const validation_1 = require("../internal/validation");
|
|
13
9
|
const DEFAULT_LIMIT = 10;
|
|
14
|
-
async function collectCandidates(context, op) {
|
|
15
|
-
const source = op.namespacePrefix.length > 0
|
|
16
|
-
? (0, paginate_1.paginateQuery)({
|
|
17
|
-
client: context.client,
|
|
18
|
-
params: (0, query_1.scopedQuery)(context.tableName, op.namespacePrefix),
|
|
19
|
-
maxItems: context.maxScanItems,
|
|
20
|
-
})
|
|
21
|
-
: (0, scan_1.paginateScan)({
|
|
22
|
-
client: context.client,
|
|
23
|
-
params: (0, query_1.storeScan)(context.tableName),
|
|
24
|
-
maxItems: context.maxScanItems,
|
|
25
|
-
});
|
|
26
|
-
const candidates = [];
|
|
27
|
-
for await (const raw of source) {
|
|
28
|
-
const record = (0, item_mapper_1.narrowStoreRecord)(raw);
|
|
29
|
-
if (!record)
|
|
30
|
-
continue;
|
|
31
|
-
if (!(0, keys_1.namespaceMatchesPrefix)(record.namespace, op.namespacePrefix))
|
|
32
|
-
continue;
|
|
33
|
-
const item = await (0, item_mapper_1.readStoreItem)(context, record);
|
|
34
|
-
if (!(0, search_filter_1.passesFilter)(item, op))
|
|
35
|
-
continue;
|
|
36
|
-
candidates.push({ item, embedding: record.embedding });
|
|
37
|
-
}
|
|
38
|
-
return candidates;
|
|
39
|
-
}
|
|
40
10
|
/**
|
|
41
11
|
* Search items under a namespace prefix: metadata filtering plus optional
|
|
42
12
|
* semantic ranking. A non-empty prefix uses a native Query; an empty prefix
|
|
43
13
|
* falls back to a (filtered) Scan. Semantic ranking uses the configured
|
|
44
14
|
* VectorBackend when present, else an in-memory cosine ranking (capped).
|
|
45
15
|
*/
|
|
46
|
-
async function searchItems(context, op) {
|
|
16
|
+
async function searchItems(context, op, signal) {
|
|
47
17
|
const offset = op.offset ?? 0;
|
|
48
18
|
const limit = op.limit ?? DEFAULT_LIMIT;
|
|
49
19
|
(0, validation_1.validatePaging)(offset, limit);
|
|
50
20
|
if (op.query && context.index && context.vectorBackend) {
|
|
51
|
-
const ranked = await (0, backend_search_1.searchViaBackend)(context, context.vectorBackend, context.index, op, offset, limit);
|
|
21
|
+
const ranked = await (0, backend_search_1.searchViaBackend)(context, context.vectorBackend, context.index, op, offset, limit, signal);
|
|
52
22
|
return ranked.slice(offset, offset + limit);
|
|
53
23
|
}
|
|
54
|
-
const candidates = await collectCandidates(context, op);
|
|
55
24
|
if (!op.query || !context.index) {
|
|
56
|
-
|
|
25
|
+
const page = await (0, candidates_1.collectCandidates)(context, op, { kind: 'page', need: offset + limit }, signal);
|
|
26
|
+
return page.map(({ item }) => ({ ...item })).slice(offset, offset + limit);
|
|
57
27
|
}
|
|
28
|
+
const candidates = await (0, candidates_1.collectCandidates)(context, op, { kind: 'semantic', cap: context.maxSearchCandidates }, signal);
|
|
58
29
|
const queryVector = await context.index.embeddings.embedQuery(op.query);
|
|
59
|
-
|
|
30
|
+
(0, semantic_search_1.assertVectorDims)(context.index, queryVector, 'query');
|
|
31
|
+
const ranked = (0, ranker_1.rankInMemory)(candidates, queryVector, context.maxSearchCandidates, (count) => context.logger.warn('search: some candidates carry an embedding of a different dimension than the query and ' +
|
|
32
|
+
'were ranked unscored; re-embed them with reconcileVectorIndex or a re-put', { namespacePrefix: op.namespacePrefix, count }));
|
|
33
|
+
return ranked.slice(offset, offset + limit);
|
|
60
34
|
}
|
|
61
|
-
//# sourceMappingURL=search.js.map
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { IndexConfig, SearchItem, SearchOperation } from '@langchain/langgraph-checkpoint';
|
|
2
2
|
import type { VectorBackend } from '../vector-backend';
|
|
3
3
|
import type { StoreContext } from './setup';
|
|
4
|
-
export declare function searchViaBackend(context: StoreContext, backend: VectorBackend, index: IndexConfig, op: SearchOperation, offset: number, limit: number): Promise<SearchItem[]>;
|
|
5
|
-
//# sourceMappingURL=backend-search.d.ts.map
|
|
4
|
+
export declare function searchViaBackend(context: StoreContext, backend: VectorBackend, index: IndexConfig, op: SearchOperation, offset: number, limit: number, signal?: AbortSignal): Promise<SearchItem[]>;
|
|
@@ -4,7 +4,9 @@ exports.searchViaBackend = searchViaBackend;
|
|
|
4
4
|
const errors_1 = require("../../shared/errors/errors");
|
|
5
5
|
const get_1 = require("../actions/get");
|
|
6
6
|
const keys_1 = require("./keys");
|
|
7
|
+
const score_direction_1 = require("./score-direction");
|
|
7
8
|
const search_filter_1 = require("./search-filter");
|
|
9
|
+
const semantic_search_1 = require("./semantic-search");
|
|
8
10
|
/**
|
|
9
11
|
* Warn when a backend's own ordering disagrees with its scores. A backend
|
|
10
12
|
* returning a raw distance still hands back nearest-first, so the order looks
|
|
@@ -25,9 +27,9 @@ function warnOnNonDescendingScores(context, matches, namespacePrefix) {
|
|
|
25
27
|
* element containing the reserved separator would otherwise turn the whole
|
|
26
28
|
* search into a ValidationError instead of dropping the one bad match.
|
|
27
29
|
*/
|
|
28
|
-
async function fetchMatch(context, match) {
|
|
30
|
+
async function fetchMatch(context, match, signal) {
|
|
29
31
|
try {
|
|
30
|
-
return await (0, get_1.getItem)(context, match.namespace, match.key);
|
|
32
|
+
return await (0, get_1.getItem)(context, match.namespace, match.key, signal);
|
|
31
33
|
}
|
|
32
34
|
catch (error) {
|
|
33
35
|
context.logger.warn('search: skipped an unusable vectorBackend match', {
|
|
@@ -38,8 +40,9 @@ async function fetchMatch(context, match) {
|
|
|
38
40
|
return null;
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
|
-
async function searchViaBackend(context, backend, index, op, offset, limit) {
|
|
43
|
+
async function searchViaBackend(context, backend, index, op, offset, limit, signal) {
|
|
42
44
|
const queryVector = await index.embeddings.embedQuery(op.query);
|
|
45
|
+
(0, semantic_search_1.assertVectorDims)(index, queryVector, 'query');
|
|
43
46
|
const need = offset + limit;
|
|
44
47
|
if (need > context.maxSearchCandidates) {
|
|
45
48
|
throw new errors_1.ValidationError(`Requested page (offset ${offset} + limit ${limit} = ${need}) exceeds maxSearchCandidates ` +
|
|
@@ -48,20 +51,24 @@ async function searchViaBackend(context, backend, index, op, offset, limit) {
|
|
|
48
51
|
let topK = Math.min(need, context.maxSearchCandidates);
|
|
49
52
|
let results;
|
|
50
53
|
for (;;) {
|
|
51
|
-
const matches = await backend.query(op.namespacePrefix, queryVector, topK);
|
|
54
|
+
const matches = (0, score_direction_1.toRelevanceScores)(await backend.query(op.namespacePrefix, queryVector, topK), context.vectorScoreDirection);
|
|
52
55
|
warnOnNonDescendingScores(context, matches, op.namespacePrefix);
|
|
53
56
|
results = [];
|
|
54
57
|
for (const match of matches) {
|
|
55
58
|
if (!(0, keys_1.namespaceMatchesPrefix)(match.namespace, op.namespacePrefix))
|
|
56
59
|
continue;
|
|
57
|
-
const item = await fetchMatch(context, match);
|
|
60
|
+
const item = await fetchMatch(context, match, signal);
|
|
58
61
|
if (item && (0, search_filter_1.passesFilter)(item, op))
|
|
59
62
|
results.push({ ...item, score: match.score });
|
|
60
63
|
}
|
|
61
|
-
if (results.length >= need || matches.length < topK
|
|
64
|
+
if (results.length >= need || matches.length < topK)
|
|
62
65
|
break;
|
|
66
|
+
if (topK >= context.maxSearchCandidates) {
|
|
67
|
+
/** The backend still holds matches, but the filter left the page short at the cap: the same answer the in-DB ranker gives, not a silently short page. */
|
|
68
|
+
throw new errors_1.ValidationError(`Semantic search collected ${results.length} of ${need} matches within maxSearchCandidates ` +
|
|
69
|
+
`(${context.maxSearchCandidates}); narrow the filter or raise maxSearchCandidates`, 'maxSearchCandidates');
|
|
70
|
+
}
|
|
63
71
|
topK = Math.min(topK * 2, context.maxSearchCandidates);
|
|
64
72
|
}
|
|
65
73
|
return results;
|
|
66
74
|
}
|
|
67
|
-
//# sourceMappingURL=backend-search.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Operation } from '@langchain/langgraph-checkpoint';
|
|
2
|
+
/**
|
|
3
|
+
* Run a batch: every write group serially within itself and groups
|
|
4
|
+
* concurrently with each other, then every read concurrently, at most
|
|
5
|
+
* {@link DEFAULT_READ_CONCURRENCY} operations in flight at a time. Results
|
|
6
|
+
* come back in operation order. Writes complete before any read starts, so a
|
|
7
|
+
* get or search in the same batch observes the puts beside it. Any failure
|
|
8
|
+
* rejects the whole batch: no further operation is started, the ones already
|
|
9
|
+
* in flight settle, and the first error propagates.
|
|
10
|
+
*/
|
|
11
|
+
export declare function runBatch<R>(operations: readonly Operation[], dispatch: (operation: Operation) => Promise<R>): Promise<R[]>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runBatch = runBatch;
|
|
4
|
+
const concurrency_1 = require("../../shared/concurrency");
|
|
5
|
+
const constants_1 = require("../../shared/constants");
|
|
6
|
+
function itemOf(op) {
|
|
7
|
+
return JSON.stringify([op.namespace, op.key]);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Group a batch so that dependent operations stay ordered while independent
|
|
11
|
+
* ones can run side by side. Two writes to the same item must land in the
|
|
12
|
+
* order given, since the later one wins; writes to different items and all
|
|
13
|
+
* reads are independent of each other.
|
|
14
|
+
*/
|
|
15
|
+
function planBatch(operations) {
|
|
16
|
+
const groups = new Map();
|
|
17
|
+
const reads = [];
|
|
18
|
+
operations.forEach((op, index) => {
|
|
19
|
+
if (!('value' in op)) {
|
|
20
|
+
reads.push(index);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const item = itemOf(op);
|
|
24
|
+
const group = groups.get(item);
|
|
25
|
+
if (group)
|
|
26
|
+
group.push(index);
|
|
27
|
+
else
|
|
28
|
+
groups.set(item, [index]);
|
|
29
|
+
});
|
|
30
|
+
return { writeGroups: [...groups.values()], reads };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Run a batch: every write group serially within itself and groups
|
|
34
|
+
* concurrently with each other, then every read concurrently, at most
|
|
35
|
+
* {@link DEFAULT_READ_CONCURRENCY} operations in flight at a time. Results
|
|
36
|
+
* come back in operation order. Writes complete before any read starts, so a
|
|
37
|
+
* get or search in the same batch observes the puts beside it. Any failure
|
|
38
|
+
* rejects the whole batch: no further operation is started, the ones already
|
|
39
|
+
* in flight settle, and the first error propagates.
|
|
40
|
+
*/
|
|
41
|
+
async function runBatch(operations, dispatch) {
|
|
42
|
+
const plan = planBatch(operations);
|
|
43
|
+
const results = [];
|
|
44
|
+
await (0, concurrency_1.mapWithConcurrency)(plan.writeGroups, constants_1.DEFAULT_READ_CONCURRENCY, async (group) => {
|
|
45
|
+
for (const index of group)
|
|
46
|
+
results[index] = await dispatch(operations[index]);
|
|
47
|
+
});
|
|
48
|
+
await (0, concurrency_1.mapWithConcurrency)(plan.reads, constants_1.DEFAULT_READ_CONCURRENCY, async (index) => {
|
|
49
|
+
results[index] = await dispatch(operations[index]);
|
|
50
|
+
});
|
|
51
|
+
return results;
|
|
52
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SearchOperation } from '@langchain/langgraph-checkpoint';
|
|
2
|
+
import type { RankCandidate } from './ranker';
|
|
3
|
+
import type { StoreContext } from './setup';
|
|
4
|
+
/**
|
|
5
|
+
* How far a collection must go. A plain page is complete once `need`
|
|
6
|
+
* (`offset + limit`) matching items are in hand, so rows past it are never
|
|
7
|
+
* read or decoded; a semantic ranking needs every candidate but is refused as
|
|
8
|
+
* soon as more than `cap` rows exist, before a single decode or embedding.
|
|
9
|
+
*/
|
|
10
|
+
export type CollectBound = {
|
|
11
|
+
kind: 'page';
|
|
12
|
+
need: number;
|
|
13
|
+
} | {
|
|
14
|
+
kind: 'semantic';
|
|
15
|
+
cap: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Collect the live rows under the prefix and decode them within `bound`. A
|
|
19
|
+
* page decodes rows in batches of {@link DEFAULT_READ_CONCURRENCY} and closes
|
|
20
|
+
* the paginator as soon as the page is full, so a namespace far larger than the
|
|
21
|
+
* page costs neither a full decode nor a truncation error.
|
|
22
|
+
*/
|
|
23
|
+
export declare function collectCandidates(context: StoreContext, op: SearchOperation, bound: CollectBound, signal?: AbortSignal): Promise<RankCandidate[]>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.collectCandidates = collectCandidates;
|
|
4
|
+
const clock_1 = require("../../shared/clock");
|
|
5
|
+
const concurrency_1 = require("../../shared/concurrency");
|
|
6
|
+
const constants_1 = require("../../shared/constants");
|
|
7
|
+
const expiry_1 = require("../../shared/dynamodb/expiry");
|
|
8
|
+
const paginate_1 = require("../../shared/dynamodb/paginate");
|
|
9
|
+
const retry_policy_1 = require("../../shared/dynamodb/retry-policy");
|
|
10
|
+
const scan_1 = require("../../shared/dynamodb/scan");
|
|
11
|
+
const errors_1 = require("../../shared/errors/errors");
|
|
12
|
+
const item_mapper_1 = require("./item-mapper");
|
|
13
|
+
const keys_1 = require("./keys");
|
|
14
|
+
const query_1 = require("./query");
|
|
15
|
+
const search_filter_1 = require("./search-filter");
|
|
16
|
+
function candidateSource(context, op, signal, now) {
|
|
17
|
+
return op.namespacePrefix.length > 0
|
|
18
|
+
? (0, paginate_1.paginateQuery)({
|
|
19
|
+
retry: (0, retry_policy_1.retryFor)(context, signal),
|
|
20
|
+
signal,
|
|
21
|
+
client: context.client,
|
|
22
|
+
params: (0, expiry_1.withoutExpired)((0, query_1.scopedQuery)(context.tableName, op.namespacePrefix), now),
|
|
23
|
+
maxItems: context.maxScanItems,
|
|
24
|
+
})
|
|
25
|
+
: (0, scan_1.paginateScan)({
|
|
26
|
+
retry: (0, retry_policy_1.retryFor)(context, signal),
|
|
27
|
+
signal,
|
|
28
|
+
client: context.client,
|
|
29
|
+
params: (0, expiry_1.withoutExpired)((0, query_1.storeScan)(context.tableName), now),
|
|
30
|
+
maxItems: context.maxScanItems,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/** The store record a raw row denotes, or undefined for a foreign, expired or out-of-prefix row. */
|
|
34
|
+
function liveRecord(raw, op, now) {
|
|
35
|
+
const record = (0, item_mapper_1.narrowStoreRecord)(raw);
|
|
36
|
+
if (!record || (0, expiry_1.isExpiredRow)(record, now))
|
|
37
|
+
return undefined;
|
|
38
|
+
return (0, keys_1.namespaceMatchesPrefix)(record.namespace, op.namespacePrefix) ? record : undefined;
|
|
39
|
+
}
|
|
40
|
+
/** Decode the pending rows concurrently (each offloaded row is one S3 GET) and keep the ones passing the filter. */
|
|
41
|
+
async function flush(context, op, state) {
|
|
42
|
+
if (state.pending.length === 0)
|
|
43
|
+
return;
|
|
44
|
+
const batch = state.pending;
|
|
45
|
+
state.pending = [];
|
|
46
|
+
const items = await (0, concurrency_1.mapWithConcurrency)(batch, constants_1.DEFAULT_READ_CONCURRENCY, (record) => (0, item_mapper_1.readStoreItem)(context, record));
|
|
47
|
+
batch.forEach((record, index) => {
|
|
48
|
+
if ((0, search_filter_1.passesFilter)(items[index], op)) {
|
|
49
|
+
state.collected.push({ item: items[index], embedding: record.embedding });
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Rows to gather before the next decode. With a filter every batch is a full
|
|
55
|
+
* one, since any row may be dropped; without one every decoded row is a match,
|
|
56
|
+
* so the batch never exceeds what the page still needs.
|
|
57
|
+
*/
|
|
58
|
+
function batchSize(op, need, collected) {
|
|
59
|
+
return op.filter === undefined
|
|
60
|
+
? Math.min(constants_1.DEFAULT_READ_CONCURRENCY, need - collected)
|
|
61
|
+
: constants_1.DEFAULT_READ_CONCURRENCY;
|
|
62
|
+
}
|
|
63
|
+
function tooManyCandidates(count, cap) {
|
|
64
|
+
return new errors_1.ValidationError(`Semantic search candidate set (${count}) exceeds maxSearchCandidates (${cap}); ` +
|
|
65
|
+
'use a dedicated VectorBackend for large corpora', 'maxSearchCandidates');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Collect the live rows under the prefix and decode them within `bound`. A
|
|
69
|
+
* page decodes rows in batches of {@link DEFAULT_READ_CONCURRENCY} and closes
|
|
70
|
+
* the paginator as soon as the page is full, so a namespace far larger than the
|
|
71
|
+
* page costs neither a full decode nor a truncation error.
|
|
72
|
+
*/
|
|
73
|
+
async function collectCandidates(context, op, bound, signal) {
|
|
74
|
+
const now = (0, clock_1.nowSeconds)();
|
|
75
|
+
const state = { pending: [], collected: [] };
|
|
76
|
+
for await (const raw of candidateSource(context, op, signal, now)) {
|
|
77
|
+
const record = liveRecord(raw, op, now);
|
|
78
|
+
if (!record)
|
|
79
|
+
continue;
|
|
80
|
+
state.pending.push(record);
|
|
81
|
+
if (bound.kind === 'semantic') {
|
|
82
|
+
if (state.pending.length > bound.cap)
|
|
83
|
+
throw tooManyCandidates(state.pending.length, bound.cap);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (state.pending.length < batchSize(op, bound.need, state.collected.length))
|
|
87
|
+
continue;
|
|
88
|
+
await flush(context, op, state);
|
|
89
|
+
if (state.collected.length >= bound.need)
|
|
90
|
+
return state.collected;
|
|
91
|
+
}
|
|
92
|
+
await flush(context, op, state);
|
|
93
|
+
return state.collected;
|
|
94
|
+
}
|
|
@@ -7,4 +7,3 @@ export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
|
7
7
|
* is exact-match ($eq); an operator object ({ $gt: 4 }) applies comparisons.
|
|
8
8
|
*/
|
|
9
9
|
export declare function matchesStoreFilter(value: Record<string, JsonValue>, filter: Record<string, JsonValue>): boolean;
|
|
10
|
-
//# sourceMappingURL=filter.d.ts.map
|