@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
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.matchesStoreFilter = matchesStoreFilter;
|
|
4
4
|
const node_util_1 = require("node:util");
|
|
5
|
+
/**
|
|
6
|
+
* Three-way order for a like-typed pair, or `undefined` when the pair is
|
|
7
|
+
* *unordered*. `NaN` compares `false` against everything including itself, so a
|
|
8
|
+
* bare `===`/`>` ternary silently reports it as "less than" — which let a
|
|
9
|
+
* stored `NaN` satisfy `$lt`/`$lte` against any number, contradicting
|
|
10
|
+
* {@link compareOrdered}'s own contract.
|
|
11
|
+
*/
|
|
12
|
+
function orderOf(actual, expected) {
|
|
13
|
+
if (actual < expected)
|
|
14
|
+
return -1;
|
|
15
|
+
if (actual > expected)
|
|
16
|
+
return 1;
|
|
17
|
+
return actual === expected ? 0 : undefined;
|
|
18
|
+
}
|
|
19
|
+
/** Apply `test` to a resolved order; an unordered pair never matches. */
|
|
20
|
+
function testOrder(order, test) {
|
|
21
|
+
return order !== undefined && test(order);
|
|
22
|
+
}
|
|
5
23
|
/**
|
|
6
24
|
* Ordered comparison over like-typed values only: numbers compare numerically,
|
|
7
25
|
* strings lexicographically, and a mismatched or unordered pair never matches.
|
|
@@ -14,11 +32,13 @@ const node_util_1 = require("node:util");
|
|
|
14
32
|
* directly is well-defined in both cases.
|
|
15
33
|
*/
|
|
16
34
|
function compareOrdered(actual, expected, test) {
|
|
17
|
-
|
|
18
|
-
(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
35
|
+
if (typeof actual === 'number' && typeof expected === 'number') {
|
|
36
|
+
return testOrder(orderOf(actual, expected), test);
|
|
37
|
+
}
|
|
38
|
+
if (typeof actual === 'string' && typeof expected === 'string') {
|
|
39
|
+
return testOrder(orderOf(actual, expected), test);
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
22
42
|
}
|
|
23
43
|
const COMPARATORS = {
|
|
24
44
|
$eq: (actual, expected) => (0, node_util_1.isDeepStrictEqual)(actual, expected),
|
|
@@ -63,4 +83,3 @@ function matchesStoreFilter(value, filter) {
|
|
|
63
83
|
* prototype chain and be compared as if it were stored data. */
|
|
64
84
|
matchesCondition(Object.hasOwn(value, field) ? value[field] : undefined, condition));
|
|
65
85
|
}
|
|
66
|
-
//# sourceMappingURL=filter.js.map
|
|
@@ -7,16 +7,15 @@ export interface ReconcileTarget {
|
|
|
7
7
|
embedding: number[] | undefined;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
* Enumerate
|
|
11
|
-
* embedding rejects the whole reconcile
|
|
12
|
-
*
|
|
13
|
-
* its still-valid
|
|
10
|
+
* Enumerate the live (unexpired) items under `prefix`, then recompute their
|
|
11
|
+
* embeddings in batches. A failed embedding rejects the whole reconcile: a
|
|
12
|
+
* skipped item would leave the live set and {@link selectOrphans} would prune
|
|
13
|
+
* its still-valid vector.
|
|
14
14
|
*/
|
|
15
|
-
export declare function collectReconcileTargets(context: StoreContext, prefix: string[]): Promise<ReconcileTarget[]>;
|
|
15
|
+
export declare function collectReconcileTargets(context: StoreContext, prefix: string[], signal?: AbortSignal): Promise<ReconcileTarget[]>;
|
|
16
16
|
/** Re-push every live embedding to the backend; returns the upsert count. */
|
|
17
17
|
export declare function pushEmbeddings(backend: VectorBackend, targets: ReconcileTarget[]): Promise<number>;
|
|
18
18
|
/** Refs present in the backend but absent from `live` — orphans to prune. */
|
|
19
19
|
export declare function selectOrphans(backendRefs: VectorRef[], live: ReconcileTarget[]): VectorRef[];
|
|
20
20
|
/** Delete backend vectors with no canonical item; returns the prune count. */
|
|
21
21
|
export declare function pruneOrphans(context: StoreContext, backend: VectorBackend, prefix: string[], live: ReconcileTarget[]): Promise<number>;
|
|
22
|
-
//# sourceMappingURL=index-reconcile.d.ts.map
|
|
@@ -4,7 +4,10 @@ exports.collectReconcileTargets = collectReconcileTargets;
|
|
|
4
4
|
exports.pushEmbeddings = pushEmbeddings;
|
|
5
5
|
exports.selectOrphans = selectOrphans;
|
|
6
6
|
exports.pruneOrphans = pruneOrphans;
|
|
7
|
+
const clock_1 = require("../../shared/clock");
|
|
8
|
+
const expiry_1 = require("../../shared/dynamodb/expiry");
|
|
7
9
|
const paginate_1 = require("../../shared/dynamodb/paginate");
|
|
10
|
+
const retry_policy_1 = require("../../shared/dynamodb/retry-policy");
|
|
8
11
|
const item_mapper_1 = require("./item-mapper");
|
|
9
12
|
const keys_1 = require("./keys");
|
|
10
13
|
const query_1 = require("./query");
|
|
@@ -15,27 +18,44 @@ function refIdentity(namespace, key) {
|
|
|
15
18
|
return JSON.stringify([...namespace, key]);
|
|
16
19
|
}
|
|
17
20
|
/**
|
|
18
|
-
* Enumerate
|
|
19
|
-
* embedding rejects the whole reconcile
|
|
20
|
-
*
|
|
21
|
-
* its still-valid
|
|
21
|
+
* Enumerate the live (unexpired) items under `prefix`, then recompute their
|
|
22
|
+
* embeddings in batches. A failed embedding rejects the whole reconcile: a
|
|
23
|
+
* skipped item would leave the live set and {@link selectOrphans} would prune
|
|
24
|
+
* its still-valid vector.
|
|
22
25
|
*/
|
|
23
|
-
async function collectReconcileTargets(context, prefix) {
|
|
24
|
-
const
|
|
26
|
+
async function collectReconcileTargets(context, prefix, signal) {
|
|
27
|
+
const now = (0, clock_1.nowSeconds)();
|
|
28
|
+
const live = [];
|
|
25
29
|
const source = (0, paginate_1.paginateQuery)({
|
|
30
|
+
retry: (0, retry_policy_1.retryFor)(context, signal),
|
|
31
|
+
signal,
|
|
26
32
|
client: context.client,
|
|
27
|
-
params: (0, query_1.scopedQuery)(context.tableName, prefix),
|
|
33
|
+
params: (0, expiry_1.withoutExpired)((0, query_1.scopedQuery)(context.tableName, prefix), now),
|
|
28
34
|
maxItems: context.maxScanItems,
|
|
29
35
|
});
|
|
30
36
|
for await (const raw of source) {
|
|
31
|
-
const record = raw;
|
|
32
|
-
if (!record
|
|
37
|
+
const record = (0, item_mapper_1.narrowStoreRecord)(raw);
|
|
38
|
+
if (!record) {
|
|
39
|
+
context.logger.warn('reconcileVectorIndex: skipped a row that is not a store item', {
|
|
40
|
+
sortKey: raw.SK,
|
|
41
|
+
});
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if ((0, expiry_1.isExpiredRow)(record, now) || !(0, keys_1.namespaceMatchesPrefix)(record.namespace, prefix))
|
|
33
45
|
continue;
|
|
34
46
|
const item = await (0, item_mapper_1.readStoreItem)(context, record);
|
|
35
|
-
|
|
36
|
-
|
|
47
|
+
live.push({
|
|
48
|
+
namespace: record.namespace,
|
|
49
|
+
key: record.key,
|
|
50
|
+
value: item.value,
|
|
51
|
+
});
|
|
37
52
|
}
|
|
38
|
-
|
|
53
|
+
const embeddings = await (0, semantic_search_1.embedValues)(context, live.map((entry) => entry.value));
|
|
54
|
+
return live.map((entry, i) => ({
|
|
55
|
+
namespace: entry.namespace,
|
|
56
|
+
key: entry.key,
|
|
57
|
+
embedding: embeddings[i],
|
|
58
|
+
}));
|
|
39
59
|
}
|
|
40
60
|
/** Re-push every live embedding to the backend; returns the upsert count. */
|
|
41
61
|
async function pushEmbeddings(backend, targets) {
|
|
@@ -96,4 +116,3 @@ async function pruneOrphans(context, backend, prefix, live) {
|
|
|
96
116
|
}
|
|
97
117
|
return pruned;
|
|
98
118
|
}
|
|
99
|
-
//# sourceMappingURL=index-reconcile.js.map
|
|
@@ -8,4 +8,3 @@ import type { VectorBackend } from '../vector-backend';
|
|
|
8
8
|
* drift — so a backend hiccup never fails an otherwise-successful put.
|
|
9
9
|
*/
|
|
10
10
|
export declare function syncVectorIndex(backend: VectorBackend, namespace: string[], key: string, embedding: number[] | undefined, logger: Logger): Promise<void>;
|
|
11
|
-
//# sourceMappingURL=index-sync.d.ts.map
|
|
@@ -5,8 +5,11 @@ import type { JsonValue } from './filter';
|
|
|
5
5
|
import type { StoreContext } from './setup';
|
|
6
6
|
/**
|
|
7
7
|
* Narrow a raw scanned row to a {@link StoreItemRecord}, or `undefined` for a
|
|
8
|
-
* foreign row on a shared table (no `namespace`)
|
|
9
|
-
*
|
|
8
|
+
* foreign row on a shared table (no `namespace`) — and for a row whose
|
|
9
|
+
* `namespace`/`key` attributes disagree with the DynamoDB key it was found at.
|
|
10
|
+
* The attributes name the S3 path the row may reference, so they must be bound
|
|
11
|
+
* to the partition the row actually lives in: a writer confined to its own
|
|
12
|
+
* partition can then never make a row speak for another tenant's objects.
|
|
10
13
|
*/
|
|
11
14
|
export declare function narrowStoreRecord(raw: DocItem): StoreItemRecord | undefined;
|
|
12
15
|
/** Fields controlling a stored item's timestamps, embedding, ttl, and S3 key nonce. */
|
|
@@ -15,10 +18,10 @@ export interface BuildItemOptions {
|
|
|
15
18
|
updatedAt: string;
|
|
16
19
|
embedding?: number[];
|
|
17
20
|
ttlTimestamp?: number;
|
|
21
|
+
/** Per-call nonce: uniquifies the S3 key and becomes the row's revision token. */
|
|
18
22
|
nonce?: string;
|
|
19
23
|
}
|
|
20
24
|
/** Encode a value into the DynamoDB record for a stored item. */
|
|
21
25
|
export declare function buildStoreItem(context: StoreContext, namespace: string[], key: string, value: Record<string, JsonValue>, options: BuildItemOptions): Promise<StoreItemRecord>;
|
|
22
26
|
/** Decode a DynamoDB record back into a store {@link Item}. */
|
|
23
27
|
export declare function readStoreItem(context: StoreContext, record: StoreItemRecord): Promise<Item>;
|
|
24
|
-
//# sourceMappingURL=item-mapper.d.ts.map
|
|
@@ -4,14 +4,23 @@ exports.narrowStoreRecord = narrowStoreRecord;
|
|
|
4
4
|
exports.buildStoreItem = buildStoreItem;
|
|
5
5
|
exports.readStoreItem = readStoreItem;
|
|
6
6
|
const codec_1 = require("../../shared/codec/codec");
|
|
7
|
+
const encode_1 = require("../../shared/codec/encode");
|
|
7
8
|
const keys_1 = require("./keys");
|
|
8
9
|
/**
|
|
9
10
|
* Narrow a raw scanned row to a {@link StoreItemRecord}, or `undefined` for a
|
|
10
|
-
* foreign row on a shared table (no `namespace`)
|
|
11
|
-
*
|
|
11
|
+
* foreign row on a shared table (no `namespace`) — and for a row whose
|
|
12
|
+
* `namespace`/`key` attributes disagree with the DynamoDB key it was found at.
|
|
13
|
+
* The attributes name the S3 path the row may reference, so they must be bound
|
|
14
|
+
* to the partition the row actually lives in: a writer confined to its own
|
|
15
|
+
* partition can then never make a row speak for another tenant's objects.
|
|
12
16
|
*/
|
|
13
17
|
function narrowStoreRecord(raw) {
|
|
14
|
-
|
|
18
|
+
if (!Array.isArray(raw.namespace) || typeof raw.key !== 'string')
|
|
19
|
+
return undefined;
|
|
20
|
+
const record = raw;
|
|
21
|
+
const consistent = record.PK === (0, keys_1.partitionKey)(record.namespace) &&
|
|
22
|
+
record.SK === (0, keys_1.sortKey)(record.namespace, record.key);
|
|
23
|
+
return consistent ? record : undefined;
|
|
15
24
|
}
|
|
16
25
|
/** Map a store context to the codec collaborators. */
|
|
17
26
|
function storeCodecDeps(context) {
|
|
@@ -19,7 +28,7 @@ function storeCodecDeps(context) {
|
|
|
19
28
|
}
|
|
20
29
|
/** Encode a value into the DynamoDB record for a stored item. */
|
|
21
30
|
async function buildStoreItem(context, namespace, key, value, options) {
|
|
22
|
-
const descriptor = await (0,
|
|
31
|
+
const descriptor = await (0, encode_1.encodePayload)(value, storeCodecDeps(context), {
|
|
23
32
|
keyParts: options.nonce === undefined ? [...namespace, key] : [...namespace, key, options.nonce],
|
|
24
33
|
});
|
|
25
34
|
const record = {
|
|
@@ -35,11 +44,13 @@ async function buildStoreItem(context, namespace, key, value, options) {
|
|
|
35
44
|
record.embedding = options.embedding;
|
|
36
45
|
if (options.ttlTimestamp !== undefined)
|
|
37
46
|
record.ttl = options.ttlTimestamp;
|
|
47
|
+
if (options.nonce !== undefined)
|
|
48
|
+
record.rev = options.nonce;
|
|
38
49
|
return record;
|
|
39
50
|
}
|
|
40
51
|
/** Decode a DynamoDB record back into a store {@link Item}. */
|
|
41
52
|
async function readStoreItem(context, record) {
|
|
42
|
-
const value = await (0, codec_1.decodePayload)(record.value, storeCodecDeps(context));
|
|
53
|
+
const value = await (0, codec_1.decodePayload)(record.value, storeCodecDeps(context), [...record.namespace, record.key]);
|
|
43
54
|
return {
|
|
44
55
|
namespace: record.namespace,
|
|
45
56
|
key: record.key,
|
|
@@ -48,4 +59,3 @@ async function readStoreItem(context, record) {
|
|
|
48
59
|
updatedAt: new Date(record.updatedAt),
|
|
49
60
|
};
|
|
50
61
|
}
|
|
51
|
-
//# sourceMappingURL=item-mapper.js.map
|
|
@@ -15,4 +15,3 @@ export declare function sortKeyPrefix(prefix: string[]): string;
|
|
|
15
15
|
* as a string prefix, so ["userspace"] does not match prefix ["users"]).
|
|
16
16
|
*/
|
|
17
17
|
export declare function namespaceMatchesPrefix(namespace: string[], prefix: string[]): boolean;
|
|
18
|
-
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DynamoDBStoreOptions } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Validate every store option at construction, shared options first.
|
|
4
|
+
*
|
|
5
|
+
* A `vectorBackend` without an `index` is rejected outright rather than
|
|
6
|
+
* silently degrading: with no embeddings configured, every `put` would compute
|
|
7
|
+
* no vector and instruct the backend to *delete* the item's entry instead of
|
|
8
|
+
* indexing it, and `search()` would fall through to an unranked scan-order
|
|
9
|
+
* listing with no `.score` field and no error — a semantic query returning a
|
|
10
|
+
* normal-looking but meaningless response. `reconcileVectorIndex` already
|
|
11
|
+
* refused this exact misconfiguration.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateStoreOptions(options: DynamoDBStoreOptions): void;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateStoreOptions = validateStoreOptions;
|
|
4
|
+
const errors_1 = require("../../shared/errors/errors");
|
|
5
|
+
const options_1 = require("../../shared/validation/options");
|
|
6
|
+
const primitives_1 = require("../../shared/validation/primitives");
|
|
7
|
+
const score_direction_1 = require("./score-direction");
|
|
8
|
+
/**
|
|
9
|
+
* Reject an `index` that cannot actually embed. `IndexConfig` mandates
|
|
10
|
+
* `embeddings`, but a JavaScript caller can omit it or pass the wrong shape,
|
|
11
|
+
* and the failure then surfaced as a raw `TypeError` deep inside the first
|
|
12
|
+
* `put()`/`search()` rather than this library's typed error at construction.
|
|
13
|
+
*
|
|
14
|
+
* Both methods are required: documents are embedded with `embedDocuments()`
|
|
15
|
+
* on `put()` and queries with `embedQuery()` on `search()`. `dims` is only
|
|
16
|
+
* compared against returned vectors when it is a positive integer, so a
|
|
17
|
+
* configuration that omits it keeps working.
|
|
18
|
+
*/
|
|
19
|
+
function assertUsableIndex(index) {
|
|
20
|
+
if (!index)
|
|
21
|
+
return;
|
|
22
|
+
const embeddings = index.embeddings;
|
|
23
|
+
const missing = ['embedQuery', 'embedDocuments'].find((method) => typeof embeddings?.[method] !== 'function');
|
|
24
|
+
if (missing === undefined)
|
|
25
|
+
return;
|
|
26
|
+
throw new errors_1.ValidationError(`\`index.embeddings\` must be an Embeddings implementation exposing ${missing}(); ` +
|
|
27
|
+
'documents are embedded with embedDocuments() on put() and queries with embedQuery() ' +
|
|
28
|
+
'on search()', 'index');
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Reject a `vectorScoreDirection` outside the declared union.
|
|
32
|
+
*
|
|
33
|
+
* {@link toRelevanceScores} treats anything it does not recognise as a no-op —
|
|
34
|
+
* the only safe default, since guessing would invert a ranking — so a mistyped
|
|
35
|
+
* or config-file-sourced value would otherwise leave a distance backend ranked
|
|
36
|
+
* backwards with no error and no warning anywhere. Same premise as
|
|
37
|
+
* {@link assertUsableIndex}: a JavaScript caller can pass a string the type
|
|
38
|
+
* never admits.
|
|
39
|
+
*/
|
|
40
|
+
function assertScoreDirection(direction) {
|
|
41
|
+
if (direction === undefined || score_direction_1.VECTOR_SCORE_DIRECTIONS.includes(direction))
|
|
42
|
+
return;
|
|
43
|
+
throw new errors_1.ValidationError(`vectorScoreDirection must be one of ${score_direction_1.VECTOR_SCORE_DIRECTIONS.join(' | ')}; received ` +
|
|
44
|
+
`${JSON.stringify(direction)}, which would be left in the backend's own direction and ` +
|
|
45
|
+
'could rank a distance backend backwards', 'vectorScoreDirection');
|
|
46
|
+
}
|
|
47
|
+
/** Both in-memory caps must be positive integers; 0 would silently return nothing. */
|
|
48
|
+
function validateLimits(options) {
|
|
49
|
+
if (options.maxScanItems !== undefined) {
|
|
50
|
+
(0, primitives_1.validateInteger)(options.maxScanItems, 'maxScanItems', { min: 1 });
|
|
51
|
+
}
|
|
52
|
+
if (options.maxSearchCandidates !== undefined) {
|
|
53
|
+
(0, primitives_1.validateInteger)(options.maxSearchCandidates, 'maxSearchCandidates', { min: 1 });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Validate every store option at construction, shared options first.
|
|
58
|
+
*
|
|
59
|
+
* A `vectorBackend` without an `index` is rejected outright rather than
|
|
60
|
+
* silently degrading: with no embeddings configured, every `put` would compute
|
|
61
|
+
* no vector and instruct the backend to *delete* the item's entry instead of
|
|
62
|
+
* indexing it, and `search()` would fall through to an unranked scan-order
|
|
63
|
+
* listing with no `.score` field and no error — a semantic query returning a
|
|
64
|
+
* normal-looking but meaningless response. `reconcileVectorIndex` already
|
|
65
|
+
* refused this exact misconfiguration.
|
|
66
|
+
*/
|
|
67
|
+
function validateStoreOptions(options) {
|
|
68
|
+
(0, options_1.validateBaseAdapterOptions)(options);
|
|
69
|
+
validateLimits(options);
|
|
70
|
+
if (options.vectorBackend && !options.index) {
|
|
71
|
+
throw new errors_1.ValidationError('vectorBackend requires a configured `index` (embeddings); without one no embedding ' +
|
|
72
|
+
'is computed, every put would clear the item vector, and search would silently return ' +
|
|
73
|
+
'unranked, score-less results', 'vectorBackend');
|
|
74
|
+
}
|
|
75
|
+
assertUsableIndex(options.index);
|
|
76
|
+
assertScoreDirection(options.vectorScoreDirection);
|
|
77
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { StoreItemRecord } from '../types';
|
|
2
|
+
import { type ExistingRecordMeta } from './read-existing';
|
|
3
|
+
import type { StoreContext } from './setup';
|
|
4
|
+
/**
|
|
5
|
+
* Commit `record`, re-reading and retrying while another writer holds the row,
|
|
6
|
+
* and return the state this write actually superseded — the only descriptor
|
|
7
|
+
* safe to delete afterwards.
|
|
8
|
+
*
|
|
9
|
+
* Without the swap both racers read the same previous descriptor, both commit,
|
|
10
|
+
* and both delete it, orphaning the loser's own upload. Retrying against the
|
|
11
|
+
* *re-read* state is what makes each writer supersede exactly one payload.
|
|
12
|
+
*
|
|
13
|
+
* A rejection is not proof a competitor won: `withDynamoDBRetry` retries
|
|
14
|
+
* transient errors, so an attempt can commit server-side, its response can be
|
|
15
|
+
* lost, and the retried put can hit the row it just wrote and fail the same
|
|
16
|
+
* guard — indistinguishable from a competitor's win by the rejection alone.
|
|
17
|
+
* Each attempt's pinned observation is captured in `attempted` before the
|
|
18
|
+
* put, so that when a re-read finds the row already holding *this call's
|
|
19
|
+
* own* `rev`, the swap returns whatever `attempted` held — never this
|
|
20
|
+
* record's own just-committed value, which would strand the live row
|
|
21
|
+
* pointing at a deleted object. That comparison is guarded on `rev` being
|
|
22
|
+
* set: `rev` is optional on the record type, and an unnonced record against a
|
|
23
|
+
* pre-0.9.0 revision-less row would otherwise match `undefined === undefined`
|
|
24
|
+
* and claim a race it never entered.
|
|
25
|
+
*
|
|
26
|
+
* On exhaustion the write proceeds unconditionally and warns. That is
|
|
27
|
+
* deliberate: the fallback is precisely the pre-0.9.0 behaviour — one possible
|
|
28
|
+
* orphan, reclaimed by a lifecycle rule — so pathological contention degrades
|
|
29
|
+
* instead of turning a working put into an error. `createdAt` is refreshed from
|
|
30
|
+
* each re-read so a row created by whoever won keeps its true creation time.
|
|
31
|
+
*/
|
|
32
|
+
export declare function putWithRevisionSwap(context: StoreContext, record: StoreItemRecord, existing: ExistingRecordMeta): Promise<ExistingRecordMeta>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.putWithRevisionSwap = putWithRevisionSwap;
|
|
4
|
+
const conditional_put_1 = require("../../shared/dynamodb/conditional-put");
|
|
5
|
+
const retry_1 = require("../../shared/dynamodb/retry");
|
|
6
|
+
const read_existing_1 = require("./read-existing");
|
|
7
|
+
/** Put the record, optionally pinned to the revision the caller observed. */
|
|
8
|
+
async function put(context, record, observed) {
|
|
9
|
+
const guard = observed ? (0, conditional_put_1.revisionGuard)(conditional_put_1.REVISION_ATTRIBUTE, observed) : {};
|
|
10
|
+
await (0, retry_1.withDynamoDBRetry)(() => context.client.put({ TableName: context.tableName, Item: record, ...guard }), context.retry);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Commit `record`, re-reading and retrying while another writer holds the row,
|
|
14
|
+
* and return the state this write actually superseded — the only descriptor
|
|
15
|
+
* safe to delete afterwards.
|
|
16
|
+
*
|
|
17
|
+
* Without the swap both racers read the same previous descriptor, both commit,
|
|
18
|
+
* and both delete it, orphaning the loser's own upload. Retrying against the
|
|
19
|
+
* *re-read* state is what makes each writer supersede exactly one payload.
|
|
20
|
+
*
|
|
21
|
+
* A rejection is not proof a competitor won: `withDynamoDBRetry` retries
|
|
22
|
+
* transient errors, so an attempt can commit server-side, its response can be
|
|
23
|
+
* lost, and the retried put can hit the row it just wrote and fail the same
|
|
24
|
+
* guard — indistinguishable from a competitor's win by the rejection alone.
|
|
25
|
+
* Each attempt's pinned observation is captured in `attempted` before the
|
|
26
|
+
* put, so that when a re-read finds the row already holding *this call's
|
|
27
|
+
* own* `rev`, the swap returns whatever `attempted` held — never this
|
|
28
|
+
* record's own just-committed value, which would strand the live row
|
|
29
|
+
* pointing at a deleted object. That comparison is guarded on `rev` being
|
|
30
|
+
* set: `rev` is optional on the record type, and an unnonced record against a
|
|
31
|
+
* pre-0.9.0 revision-less row would otherwise match `undefined === undefined`
|
|
32
|
+
* and claim a race it never entered.
|
|
33
|
+
*
|
|
34
|
+
* On exhaustion the write proceeds unconditionally and warns. That is
|
|
35
|
+
* deliberate: the fallback is precisely the pre-0.9.0 behaviour — one possible
|
|
36
|
+
* orphan, reclaimed by a lifecycle rule — so pathological contention degrades
|
|
37
|
+
* instead of turning a working put into an error. `createdAt` is refreshed from
|
|
38
|
+
* each re-read so a row created by whoever won keeps its true creation time.
|
|
39
|
+
*/
|
|
40
|
+
async function putWithRevisionSwap(context, record, existing) {
|
|
41
|
+
let observed = existing;
|
|
42
|
+
for (let attempt = 1; attempt <= conditional_put_1.OVERWRITE_CAS_MAX_ATTEMPTS; attempt++) {
|
|
43
|
+
const attempted = observed;
|
|
44
|
+
try {
|
|
45
|
+
await put(context, record, attempted);
|
|
46
|
+
return attempted;
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (!(0, conditional_put_1.isConditionalCheckFailed)(error))
|
|
50
|
+
throw error;
|
|
51
|
+
/** The rejection carries the row that turned it away; the read is spent only when it does not. */
|
|
52
|
+
const rejected = (0, conditional_put_1.rejectedItem)(error);
|
|
53
|
+
observed = rejected
|
|
54
|
+
? (0, read_existing_1.existingFrom)(rejected)
|
|
55
|
+
: await (0, read_existing_1.readExisting)(context, record.PK, record.SK);
|
|
56
|
+
if (record.rev !== undefined && observed.revision === record.rev)
|
|
57
|
+
return attempted;
|
|
58
|
+
/** A row that vanished between attempts (a concurrent delete) makes this a fresh creation. */
|
|
59
|
+
record.createdAt = observed.exists
|
|
60
|
+
? (observed.createdAt ?? record.createdAt)
|
|
61
|
+
: record.updatedAt;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
context.logger.warn('store.put: compare-and-swap exhausted; overwriting unconditionally, which can orphan one ' +
|
|
65
|
+
'S3 object under a concurrent put (reclaimed by ensureS3LifecycleRule)', { namespace: record.namespace, key: record.key, attempts: conditional_put_1.OVERWRITE_CAS_MAX_ATTEMPTS });
|
|
66
|
+
await put(context, record);
|
|
67
|
+
return observed;
|
|
68
|
+
}
|
|
@@ -1,11 +1,28 @@
|
|
|
1
|
-
import { type PayloadDescriptor } from '../../shared/codec/codec';
|
|
2
1
|
import type { StoreItemRecord } from '../types';
|
|
2
|
+
import type { ExistingRecordMeta } from './read-existing';
|
|
3
3
|
import type { StoreContext } from './setup';
|
|
4
4
|
/**
|
|
5
|
-
* Put the record
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* Put the record and clean up whichever side is now dead.
|
|
6
|
+
*
|
|
7
|
+
* The compare-and-swap path runs **only when an offloader is configured**:
|
|
8
|
+
* without one there is no S3 object to orphan, so a plain last-write-wins put
|
|
9
|
+
* stays correct and costs no extra write capacity (DynamoDB charges for a
|
|
10
|
+
* failed conditional write too). With one, the swap is what lets this call
|
|
11
|
+
* delete exactly the payload it superseded rather than a descriptor a racer may
|
|
12
|
+
* already have replaced.
|
|
13
|
+
*
|
|
14
|
+
* Every failure reaching the catch arrives after at least one put was issued —
|
|
15
|
+
* `putWithRevisionSwap` only re-reads from inside its own catch — so none of
|
|
16
|
+
* them proves a non-commit on its own: a put can commit server-side and lose
|
|
17
|
+
* its response, and a `ConditionalCheckFailedException` is as consistent with
|
|
18
|
+
* hitting the row this call just wrote as with a competitor's win. The row is
|
|
19
|
+
* therefore read back (`verifyWriteLanded`) before anything is deleted. Only a
|
|
20
|
+
* confirmed `'not-landed'` deletes this record's own nonced object; a confirmed
|
|
21
|
+
* `'landed'` cleans up the previous object like the success path and swallows
|
|
22
|
+
* the error, and an `'unverified'` read deletes nothing and rethrows — leaking
|
|
23
|
+
* one object at worst rather than stranding a live row pointing at a deleted
|
|
24
|
+
* one. The verification compares the per-call `rev`, so an inline record is
|
|
25
|
+
* verified too: a lost acknowledgement of an inline overwrite used to be
|
|
26
|
+
* reported as a failure while the previous offloaded object was never cleaned.
|
|
9
27
|
*/
|
|
10
|
-
export declare function persistRecord(context: StoreContext, record: StoreItemRecord,
|
|
11
|
-
//# sourceMappingURL=persist.d.ts.map
|
|
28
|
+
export declare function persistRecord(context: StoreContext, record: StoreItemRecord, existing: ExistingRecordMeta): Promise<void>;
|
|
@@ -1,34 +1,64 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.persistRecord = persistRecord;
|
|
4
|
-
const codec_1 = require("../../shared/codec/codec");
|
|
5
4
|
const descriptor_keys_1 = require("../../shared/codec/descriptor-keys");
|
|
6
5
|
const orphans_1 = require("../../shared/codec/s3/orphans");
|
|
7
6
|
const retry_1 = require("../../shared/dynamodb/retry");
|
|
7
|
+
const overwrite_swap_1 = require("./overwrite-swap");
|
|
8
8
|
const write_verify_1 = require("./write-verify");
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* *previous* row's object instead, like the ordinary success path.
|
|
10
|
+
* Best-effort delete of one descriptor's S3 object. `scope` is passed for a
|
|
11
|
+
* descriptor read back from the row (the superseded value) and omitted for
|
|
12
|
+
* this call's own upload.
|
|
14
13
|
*/
|
|
15
|
-
async function
|
|
14
|
+
async function cleanUp(context, descriptor, label, scope) {
|
|
15
|
+
if (!context.offloader || !descriptor)
|
|
16
|
+
return;
|
|
17
|
+
await (0, orphans_1.cleanUpS3Orphans)(context.offloader, (0, descriptor_keys_1.collectS3Keys)([descriptor]), label, context.logger, scope === undefined ? {} : { scope });
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Put the record and clean up whichever side is now dead.
|
|
21
|
+
*
|
|
22
|
+
* The compare-and-swap path runs **only when an offloader is configured**:
|
|
23
|
+
* without one there is no S3 object to orphan, so a plain last-write-wins put
|
|
24
|
+
* stays correct and costs no extra write capacity (DynamoDB charges for a
|
|
25
|
+
* failed conditional write too). With one, the swap is what lets this call
|
|
26
|
+
* delete exactly the payload it superseded rather than a descriptor a racer may
|
|
27
|
+
* already have replaced.
|
|
28
|
+
*
|
|
29
|
+
* Every failure reaching the catch arrives after at least one put was issued —
|
|
30
|
+
* `putWithRevisionSwap` only re-reads from inside its own catch — so none of
|
|
31
|
+
* them proves a non-commit on its own: a put can commit server-side and lose
|
|
32
|
+
* its response, and a `ConditionalCheckFailedException` is as consistent with
|
|
33
|
+
* hitting the row this call just wrote as with a competitor's win. The row is
|
|
34
|
+
* therefore read back (`verifyWriteLanded`) before anything is deleted. Only a
|
|
35
|
+
* confirmed `'not-landed'` deletes this record's own nonced object; a confirmed
|
|
36
|
+
* `'landed'` cleans up the previous object like the success path and swallows
|
|
37
|
+
* the error, and an `'unverified'` read deletes nothing and rethrows — leaking
|
|
38
|
+
* one object at worst rather than stranding a live row pointing at a deleted
|
|
39
|
+
* one. The verification compares the per-call `rev`, so an inline record is
|
|
40
|
+
* verified too: a lost acknowledgement of an inline overwrite used to be
|
|
41
|
+
* reported as a failure while the previous offloaded object was never cleaned.
|
|
42
|
+
*/
|
|
43
|
+
async function persistRecord(context, record, existing) {
|
|
44
|
+
let superseded = existing;
|
|
16
45
|
try {
|
|
17
|
-
|
|
46
|
+
if (context.offloader) {
|
|
47
|
+
superseded = await (0, overwrite_swap_1.putWithRevisionSwap)(context, record, existing);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
await (0, retry_1.withDynamoDBRetry)(() => context.client.put({ TableName: context.tableName, Item: record }), context.retry);
|
|
51
|
+
}
|
|
18
52
|
}
|
|
19
53
|
catch (error) {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if (
|
|
24
|
-
if (context.offloader) {
|
|
25
|
-
await (0, orphans_1.cleanUpS3Orphans)(context.offloader, (0, descriptor_keys_1.collectS3Keys)([record.value]), 'store.put', context.logger);
|
|
26
|
-
}
|
|
54
|
+
const verdict = await (0, write_verify_1.verifyWriteLanded)(context, record);
|
|
55
|
+
if (verdict === 'not-landed')
|
|
56
|
+
await cleanUp(context, record.value, 'store.put');
|
|
57
|
+
if (verdict !== 'landed')
|
|
27
58
|
throw error;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
if (context.offloader && previousValue) {
|
|
31
|
-
await (0, orphans_1.cleanUpS3Orphans)(context.offloader, (0, descriptor_keys_1.collectS3Keys)([previousValue]), 'store.put.overwrite', context.logger);
|
|
32
59
|
}
|
|
60
|
+
await cleanUp(context, superseded.value, 'store.put.overwrite', [
|
|
61
|
+
...record.namespace,
|
|
62
|
+
record.key,
|
|
63
|
+
]);
|
|
33
64
|
}
|
|
34
|
-
//# sourceMappingURL=persist.js.map
|
|
@@ -3,4 +3,9 @@ import type { QueryCommandInput, ScanCommandInput } from '@aws-sdk/lib-dynamodb'
|
|
|
3
3
|
export declare function scopedQuery(tableName: string, prefix: string[]): QueryCommandInput;
|
|
4
4
|
/** Scan input for the rootless case, filtered to store items only. */
|
|
5
5
|
export declare function storeScan(tableName: string): ScanCommandInput;
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Restrict a Query/Scan to the attributes `narrowStoreRecord` needs, leaving the
|
|
8
|
+
* payload behind: a namespace listing never reads a value. RCU is billed on
|
|
9
|
+
* the stored size regardless, so the saving is transfer and unmarshalling.
|
|
10
|
+
*/
|
|
11
|
+
export declare function projectKeys<T extends QueryCommandInput | ScanCommandInput>(params: T): T;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.scopedQuery = scopedQuery;
|
|
4
4
|
exports.storeScan = storeScan;
|
|
5
|
+
exports.projectKeys = projectKeys;
|
|
5
6
|
const keys_1 = require("./keys");
|
|
6
7
|
/** Query input for a scoped prefix (PK = prefix[0], optional SK begins_with). */
|
|
7
8
|
function scopedQuery(tableName, prefix) {
|
|
@@ -29,4 +30,19 @@ function storeScan(tableName) {
|
|
|
29
30
|
ExpressionAttributeNames: { '#ns': 'namespace' },
|
|
30
31
|
};
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Restrict a Query/Scan to the attributes `narrowStoreRecord` needs, leaving the
|
|
35
|
+
* payload behind: a namespace listing never reads a value. RCU is billed on
|
|
36
|
+
* the stored size regardless, so the saving is transfer and unmarshalling.
|
|
37
|
+
*/
|
|
38
|
+
function projectKeys(params) {
|
|
39
|
+
return {
|
|
40
|
+
...params,
|
|
41
|
+
ProjectionExpression: 'PK, SK, #ns, #key',
|
|
42
|
+
ExpressionAttributeNames: {
|
|
43
|
+
...params.ExpressionAttributeNames,
|
|
44
|
+
'#ns': 'namespace',
|
|
45
|
+
'#key': 'key',
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -8,6 +8,11 @@ export interface RankCandidate {
|
|
|
8
8
|
* Rank candidates by cosine similarity to `queryVector`, descending. Throws a
|
|
9
9
|
* {@link ValidationError} when the candidate count exceeds `maxCandidates`
|
|
10
10
|
* (steer large corpora to an external VectorBackend).
|
|
11
|
+
*
|
|
12
|
+
* A stored embedding whose length differs from the query vector's cannot be
|
|
13
|
+
* scored — it was written by a different embeddings model — and is ranked
|
|
14
|
+
* last with an undefined score. `onDimensionMismatch` is invoked once with
|
|
15
|
+
* how many candidates that affected, so the caller can say so instead of
|
|
16
|
+
* silently returning a ranking that quietly omits them.
|
|
11
17
|
*/
|
|
12
|
-
export declare function rankInMemory(candidates: RankCandidate[], queryVector: number[], maxCandidates: number): SearchItem[];
|
|
13
|
-
//# sourceMappingURL=ranker.d.ts.map
|
|
18
|
+
export declare function rankInMemory(candidates: RankCandidate[], queryVector: number[], maxCandidates: number, onDimensionMismatch?: (count: number) => void): SearchItem[];
|