@farukada/aws-langgraph-dynamodb-ts 1.0.0-rc.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +390 -193
- package/dist/{backfill → cjs/backfill}/backfill.d.ts +15 -12
- package/dist/cjs/backfill/backfill.js +177 -0
- package/dist/{checkpointer → cjs/checkpointer}/actions/delete-thread.d.ts +1 -1
- package/dist/cjs/checkpointer/actions/delete-thread.js +26 -0
- package/dist/{checkpointer → cjs/checkpointer}/actions/get-tuple.d.ts +4 -3
- package/dist/cjs/checkpointer/actions/get-tuple.js +22 -0
- package/dist/{checkpointer → cjs/checkpointer}/actions/list.d.ts +7 -4
- package/dist/cjs/checkpointer/actions/list.js +70 -0
- package/dist/{checkpointer → cjs/checkpointer}/actions/put-writes.d.ts +8 -6
- package/dist/cjs/checkpointer/actions/put-writes.js +21 -0
- package/dist/{checkpointer → cjs/checkpointer}/actions/put.d.ts +21 -15
- package/dist/cjs/checkpointer/actions/put.js +79 -0
- package/dist/{checkpointer → cjs/checkpointer}/internal/delta-history.d.ts +38 -26
- package/dist/cjs/checkpointer/internal/delta-history.js +131 -0
- package/dist/{checkpointer → cjs/checkpointer}/internal/listing.d.ts +4 -4
- package/dist/cjs/checkpointer/internal/listing.js +104 -0
- package/dist/{checkpointer → cjs/checkpointer}/internal/parse.d.ts +51 -15
- package/dist/cjs/checkpointer/internal/parse.js +184 -0
- package/dist/{checkpointer → cjs/checkpointer}/internal/pending-writes.d.ts +64 -25
- package/dist/cjs/checkpointer/internal/pending-writes.js +241 -0
- package/dist/{checkpointer → cjs/checkpointer}/internal/read.d.ts +15 -10
- package/dist/cjs/checkpointer/internal/read.js +132 -0
- package/dist/{checkpointer → cjs/checkpointer}/internal/rows.d.ts +94 -21
- package/dist/cjs/checkpointer/internal/rows.js +356 -0
- package/dist/{checkpointer → cjs/checkpointer}/internal/setup.d.ts +13 -20
- package/dist/cjs/checkpointer/internal/setup.js +25 -0
- package/dist/{checkpointer → cjs/checkpointer}/saver.d.ts +72 -36
- package/dist/cjs/checkpointer/saver.js +56 -0
- package/dist/{checkpointer → cjs/checkpointer}/types.d.ts +1 -1
- package/dist/cjs/checkpointer/types.js +2 -0
- package/dist/{factory → cjs/factory}/factory.d.ts +25 -20
- package/dist/cjs/factory/factory.js +137 -0
- package/dist/{factory → cjs/factory}/types.d.ts +12 -12
- package/dist/cjs/factory/types.js +2 -0
- package/dist/{history → cjs/history}/actions/add-messages.d.ts +18 -10
- package/dist/cjs/history/actions/add-messages.js +17 -0
- package/dist/{history → cjs/history}/actions/clear.d.ts +1 -1
- package/dist/cjs/history/actions/clear.js +29 -0
- package/dist/{history → cjs/history}/actions/get-messages.d.ts +11 -9
- package/dist/cjs/history/actions/get-messages.js +58 -0
- package/dist/{history → cjs/history}/actions/list-sessions.d.ts +3 -3
- package/dist/cjs/history/actions/list-sessions.js +67 -0
- package/dist/{history → cjs/history}/actions/reconcile-count.d.ts +13 -9
- package/dist/cjs/history/actions/reconcile-count.js +8 -0
- package/dist/{history → cjs/history}/chat-message-history.d.ts +62 -30
- package/dist/cjs/history/chat-message-history.js +61 -0
- package/dist/{history → cjs/history}/internal/append.d.ts +64 -32
- package/dist/cjs/history/internal/append.js +267 -0
- package/dist/{history → cjs/history}/internal/message-read.d.ts +3 -3
- package/dist/cjs/history/internal/message-read.js +93 -0
- package/dist/{history → cjs/history}/internal/parse.d.ts +2 -2
- package/dist/cjs/history/internal/parse.js +113 -0
- package/dist/{history → cjs/history}/internal/rows.d.ts +11 -10
- package/dist/cjs/history/internal/rows.js +96 -0
- package/dist/{history → cjs/history}/internal/session.d.ts +41 -22
- package/dist/cjs/history/internal/session.js +296 -0
- package/dist/{history → cjs/history}/internal/setup.d.ts +2 -2
- package/dist/cjs/history/internal/setup.js +60 -0
- package/dist/{history → cjs/history}/session-adapter.d.ts +0 -6
- package/dist/cjs/history/session-adapter.js +38 -0
- package/dist/{history → cjs/history}/types.d.ts +18 -15
- package/dist/cjs/history/types.js +2 -0
- package/dist/{index.d.ts → cjs/index.d.ts} +27 -27
- package/dist/cjs/index.js +25 -0
- package/dist/cjs/package.json +1 -0
- package/dist/{shared → cjs/shared}/adapter.d.ts +27 -16
- package/dist/cjs/shared/adapter.js +70 -0
- package/dist/cjs/shared/clock.js +14 -0
- package/dist/{shared → cjs/shared}/codec/codec.d.ts +37 -20
- package/dist/cjs/shared/codec/codec.js +162 -0
- package/dist/{shared → cjs/shared}/codec/compression.d.ts +9 -4
- package/dist/cjs/shared/codec/compression.js +45 -0
- package/dist/cjs/shared/codec/json-serde.js +58 -0
- package/dist/{shared → cjs/shared}/codec/s3/client-types.d.ts +2 -1
- package/dist/cjs/shared/codec/s3/client-types.js +6 -0
- package/dist/{shared → cjs/shared}/codec/s3/client.d.ts +25 -7
- package/dist/cjs/shared/codec/s3/client.js +78 -0
- package/dist/{shared → cjs/shared}/codec/s3/config.d.ts +12 -7
- package/dist/cjs/shared/codec/s3/config.js +92 -0
- package/dist/{shared → cjs/shared}/codec/s3/lifecycle.d.ts +71 -17
- package/dist/cjs/shared/codec/s3/lifecycle.js +223 -0
- package/dist/{shared → cjs/shared}/codec/s3/offloader.d.ts +42 -29
- package/dist/cjs/shared/codec/s3/offloader.js +289 -0
- package/dist/cjs/shared/concurrency.js +31 -0
- package/dist/{shared → cjs/shared}/dynamodb/abort.d.ts +2 -2
- package/dist/cjs/shared/dynamodb/abort.js +16 -0
- package/dist/{shared → cjs/shared}/dynamodb/batch-write.d.ts +2 -2
- package/dist/cjs/shared/dynamodb/batch-write.js +79 -0
- package/dist/cjs/shared/dynamodb/cancellation.js +37 -0
- package/dist/{shared → cjs/shared}/dynamodb/client.d.ts +24 -22
- package/dist/cjs/shared/dynamodb/client.js +40 -0
- package/dist/{shared → cjs/shared}/dynamodb/idempotent-write.d.ts +64 -19
- package/dist/cjs/shared/dynamodb/idempotent-write.js +173 -0
- package/dist/{shared → cjs/shared}/dynamodb/paginate.d.ts +2 -2
- package/dist/cjs/shared/dynamodb/paginate.js +90 -0
- package/dist/{shared → cjs/shared}/dynamodb/partition-delete.d.ts +6 -6
- package/dist/cjs/shared/dynamodb/partition-delete.js +177 -0
- package/dist/{shared → cjs/shared}/dynamodb/recency-index.d.ts +27 -15
- package/dist/cjs/shared/dynamodb/recency-index.js +146 -0
- package/dist/{shared → cjs/shared}/dynamodb/retry.d.ts +37 -6
- package/dist/cjs/shared/dynamodb/retry.js +193 -0
- package/dist/cjs/shared/dynamodb/row-size.d.ts +33 -0
- package/dist/cjs/shared/dynamodb/row-size.js +30 -0
- package/dist/{shared → cjs/shared}/dynamodb/table-schema.d.ts +27 -18
- package/dist/cjs/shared/dynamodb/table-schema.js +52 -0
- package/dist/{shared → cjs/shared}/errors/base-error.d.ts +42 -7
- package/dist/cjs/shared/errors/base-error.js +73 -0
- package/dist/{shared → cjs/shared}/errors/boundary.d.ts +29 -14
- package/dist/cjs/shared/errors/boundary.js +61 -0
- package/dist/cjs/shared/errors/classify.d.ts +206 -0
- package/dist/cjs/shared/errors/classify.js +232 -0
- package/dist/{shared → cjs/shared}/errors/error-code.d.ts +17 -10
- package/dist/cjs/shared/errors/error-code.js +27 -0
- package/dist/{shared → cjs/shared}/errors/errors.d.ts +75 -9
- package/dist/cjs/shared/errors/errors.js +123 -0
- package/dist/cjs/shared/logging/logger.js +30 -0
- package/dist/{shared → cjs/shared}/logging/redaction.d.ts +8 -4
- package/dist/cjs/shared/logging/redaction.js +145 -0
- package/dist/{shared → cjs/shared}/logging/secret-patterns.d.ts +30 -7
- package/dist/cjs/shared/logging/secret-patterns.js +93 -0
- package/dist/cjs/shared/logging/truncate.js +31 -0
- package/dist/{shared → cjs/shared}/options.d.ts +27 -11
- package/dist/cjs/shared/options.js +2 -0
- package/dist/cjs/shared/ulid.js +83 -0
- package/dist/{shared → cjs/shared}/validation/collaborators.d.ts +21 -2
- package/dist/cjs/shared/validation/collaborators.js +79 -0
- package/dist/{shared → cjs/shared}/validation/option-shape.d.ts +7 -5
- package/dist/cjs/shared/validation/option-shape.js +31 -0
- package/dist/{shared → cjs/shared}/validation/options.d.ts +4 -4
- package/dist/cjs/shared/validation/options.js +166 -0
- package/dist/cjs/shared/validation/primitives.js +114 -0
- package/dist/{shared → cjs/shared}/validation/ttl.d.ts +26 -9
- package/dist/cjs/shared/validation/ttl.js +52 -0
- package/dist/{store → cjs/store}/actions/list-namespaces.d.ts +5 -5
- package/dist/cjs/store/actions/list-namespaces.js +92 -0
- package/dist/{store → cjs/store}/actions/put.d.ts +11 -4
- package/dist/cjs/store/actions/put.js +49 -0
- package/dist/{store → cjs/store}/actions/reconcile-vector-index.d.ts +5 -5
- package/dist/cjs/store/actions/reconcile-vector-index.js +13 -0
- package/dist/{store → cjs/store}/actions/search.d.ts +2 -2
- package/dist/cjs/store/actions/search.js +26 -0
- package/dist/cjs/store/internal/batch-plan.d.ts +56 -0
- package/dist/cjs/store/internal/batch-plan.js +32 -0
- package/dist/{store → cjs/store}/internal/filter.d.ts +3 -3
- package/dist/cjs/store/internal/filter.js +64 -0
- package/dist/cjs/store/internal/get-item.d.ts +77 -0
- package/dist/cjs/store/internal/get-item.js +58 -0
- package/dist/{store → cjs/store}/internal/item-write.d.ts +72 -32
- package/dist/cjs/store/internal/item-write.js +181 -0
- package/dist/{store → cjs/store}/internal/parse.d.ts +15 -10
- package/dist/cjs/store/internal/parse.js +180 -0
- package/dist/{store → cjs/store}/internal/rows.d.ts +38 -34
- package/dist/cjs/store/internal/rows.js +166 -0
- package/dist/{store → cjs/store}/internal/semantic-search.d.ts +2 -2
- package/dist/cjs/store/internal/semantic-search.js +211 -0
- package/dist/{store → cjs/store}/internal/setup.d.ts +10 -15
- package/dist/cjs/store/internal/setup.js +103 -0
- package/dist/{store → cjs/store}/internal/table-search.d.ts +5 -5
- package/dist/cjs/store/internal/table-search.js +123 -0
- package/dist/{store → cjs/store}/internal/vector-index.d.ts +26 -15
- package/dist/cjs/store/internal/vector-index.js +269 -0
- package/dist/{store → cjs/store}/store.d.ts +82 -39
- package/dist/cjs/store/store.js +97 -0
- package/dist/{store → cjs/store}/types.d.ts +25 -10
- package/dist/cjs/store/types.js +2 -0
- package/dist/cjs/store/vector-backend.js +4 -0
- package/dist/esm/backfill/backfill.d.ts +171 -0
- package/dist/esm/backfill/backfill.js +170 -0
- package/dist/{checkpointer/actions/delete-thread.js → esm/checkpointer/actions/delete-thread.d.ts} +4 -26
- package/dist/esm/checkpointer/actions/delete-thread.js +23 -0
- package/dist/{checkpointer/actions/get-tuple.js → esm/checkpointer/actions/get-tuple.d.ts} +7 -24
- package/dist/esm/checkpointer/actions/get-tuple.js +19 -0
- package/dist/esm/checkpointer/actions/list.d.ts +55 -0
- package/dist/esm/checkpointer/actions/list.js +67 -0
- package/dist/{checkpointer/actions/put-writes.js → esm/checkpointer/actions/put-writes.d.ts} +10 -37
- package/dist/esm/checkpointer/actions/put-writes.js +18 -0
- package/dist/esm/checkpointer/actions/put.d.ts +95 -0
- package/dist/esm/checkpointer/actions/put.js +75 -0
- package/dist/esm/checkpointer/internal/delta-history.d.ts +124 -0
- package/dist/esm/checkpointer/internal/delta-history.js +126 -0
- package/dist/{checkpointer/internal/listing.js → esm/checkpointer/internal/listing.d.ts} +22 -118
- package/dist/esm/checkpointer/internal/listing.js +95 -0
- package/dist/esm/checkpointer/internal/parse.d.ts +298 -0
- package/dist/esm/checkpointer/internal/parse.js +169 -0
- package/dist/esm/checkpointer/internal/pending-writes.d.ts +314 -0
- package/dist/esm/checkpointer/internal/pending-writes.js +229 -0
- package/dist/esm/checkpointer/internal/read.d.ts +135 -0
- package/dist/esm/checkpointer/internal/read.js +125 -0
- package/dist/esm/checkpointer/internal/rows.d.ts +644 -0
- package/dist/esm/checkpointer/internal/rows.js +323 -0
- package/dist/esm/checkpointer/internal/setup.d.ts +47 -0
- package/dist/esm/checkpointer/internal/setup.js +21 -0
- package/dist/{checkpointer/saver.js → esm/checkpointer/saver.d.ts} +84 -87
- package/dist/esm/checkpointer/saver.js +52 -0
- package/dist/esm/checkpointer/types.d.ts +51 -0
- package/dist/esm/checkpointer/types.js +1 -0
- package/dist/esm/factory/factory.d.ts +154 -0
- package/dist/esm/factory/factory.js +133 -0
- package/dist/esm/factory/types.d.ts +76 -0
- package/dist/esm/factory/types.js +1 -0
- package/dist/{history/actions/add-messages.js → esm/history/actions/add-messages.d.ts} +20 -26
- package/dist/esm/history/actions/add-messages.js +14 -0
- package/dist/{history/actions/clear.js → esm/history/actions/clear.d.ts} +4 -35
- package/dist/esm/history/actions/clear.js +26 -0
- package/dist/esm/history/actions/get-messages.d.ts +60 -0
- package/dist/esm/history/actions/get-messages.js +55 -0
- package/dist/esm/history/actions/list-sessions.d.ts +55 -0
- package/dist/esm/history/actions/list-sessions.js +64 -0
- package/dist/{history/actions/reconcile-count.js → esm/history/actions/reconcile-count.d.ts} +14 -16
- package/dist/esm/history/actions/reconcile-count.js +5 -0
- package/dist/{history/chat-message-history.js → esm/history/chat-message-history.d.ts} +76 -87
- package/dist/esm/history/chat-message-history.js +57 -0
- package/dist/esm/history/internal/append.d.ts +244 -0
- package/dist/esm/history/internal/append.js +259 -0
- package/dist/esm/history/internal/message-read.d.ts +84 -0
- package/dist/esm/history/internal/message-read.js +89 -0
- package/dist/esm/history/internal/parse.d.ts +153 -0
- package/dist/esm/history/internal/parse.js +105 -0
- package/dist/{history/internal/rows.js → esm/history/internal/rows.d.ts} +58 -112
- package/dist/esm/history/internal/rows.js +83 -0
- package/dist/esm/history/internal/session.d.ts +350 -0
- package/dist/esm/history/internal/session.js +285 -0
- package/dist/esm/history/internal/setup.d.ts +64 -0
- package/dist/esm/history/internal/setup.js +56 -0
- package/dist/{history/session-adapter.js → esm/history/session-adapter.d.ts} +25 -39
- package/dist/esm/history/session-adapter.js +34 -0
- package/dist/esm/history/types.d.ts +102 -0
- package/dist/esm/history/types.js +1 -0
- package/dist/esm/index.d.ts +53 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/shared/adapter.d.ts +146 -0
- package/dist/esm/shared/adapter.js +65 -0
- package/dist/{shared/clock.js → esm/shared/clock.d.ts} +3 -14
- package/dist/esm/shared/clock.js +9 -0
- package/dist/esm/shared/codec/codec.d.ts +336 -0
- package/dist/esm/shared/codec/codec.js +150 -0
- package/dist/esm/shared/codec/compression.d.ts +66 -0
- package/dist/esm/shared/codec/compression.js +40 -0
- package/dist/esm/shared/codec/json-serde.d.ts +80 -0
- package/dist/esm/shared/codec/json-serde.js +54 -0
- package/dist/esm/shared/codec/s3/client-types.d.ts +54 -0
- package/dist/esm/shared/codec/s3/client-types.js +3 -0
- package/dist/esm/shared/codec/s3/client.d.ts +63 -0
- package/dist/esm/shared/codec/s3/client.js +40 -0
- package/dist/{shared/codec/s3/config.js → esm/shared/codec/s3/config.d.ts} +45 -93
- package/dist/esm/shared/codec/s3/config.js +79 -0
- package/dist/esm/shared/codec/s3/lifecycle.d.ts +220 -0
- package/dist/esm/shared/codec/s3/lifecycle.js +214 -0
- package/dist/esm/shared/codec/s3/offloader.d.ts +428 -0
- package/dist/esm/shared/codec/s3/offloader.js +278 -0
- package/dist/{shared/concurrency.js → esm/shared/concurrency.d.ts} +2 -37
- package/dist/esm/shared/concurrency.js +27 -0
- package/dist/{shared/dynamodb/abort.js → esm/shared/dynamodb/abort.d.ts} +4 -16
- package/dist/esm/shared/dynamodb/abort.js +12 -0
- package/dist/esm/shared/dynamodb/batch-write.d.ts +86 -0
- package/dist/esm/shared/dynamodb/batch-write.js +74 -0
- package/dist/{shared/dynamodb/cancellation.js → esm/shared/dynamodb/cancellation.d.ts} +25 -53
- package/dist/esm/shared/dynamodb/cancellation.js +30 -0
- package/dist/{shared/dynamodb/client.js → esm/shared/dynamodb/client.d.ts} +74 -64
- package/dist/esm/shared/dynamodb/client.js +35 -0
- package/dist/{shared/dynamodb/idempotent-write.js → esm/shared/dynamodb/idempotent-write.d.ts} +172 -169
- package/dist/esm/shared/dynamodb/idempotent-write.js +153 -0
- package/dist/esm/shared/dynamodb/paginate.d.ts +111 -0
- package/dist/esm/shared/dynamodb/paginate.js +84 -0
- package/dist/esm/shared/dynamodb/partition-delete.d.ts +204 -0
- package/dist/esm/shared/dynamodb/partition-delete.js +171 -0
- package/dist/esm/shared/dynamodb/recency-index.d.ts +243 -0
- package/dist/esm/shared/dynamodb/recency-index.js +136 -0
- package/dist/esm/shared/dynamodb/retry.d.ts +317 -0
- package/dist/esm/shared/dynamodb/retry.js +180 -0
- package/dist/esm/shared/dynamodb/row-size.d.ts +33 -0
- package/dist/esm/shared/dynamodb/row-size.js +26 -0
- package/dist/{shared/dynamodb/table-schema.js → esm/shared/dynamodb/table-schema.d.ts} +57 -67
- package/dist/esm/shared/dynamodb/table-schema.js +43 -0
- package/dist/esm/shared/errors/base-error.d.ts +231 -0
- package/dist/esm/shared/errors/base-error.js +64 -0
- package/dist/esm/shared/errors/boundary.d.ts +86 -0
- package/dist/esm/shared/errors/boundary.js +54 -0
- package/dist/esm/shared/errors/classify.d.ts +206 -0
- package/dist/esm/shared/errors/classify.js +220 -0
- package/dist/{shared/errors/error-code.js → esm/shared/errors/error-code.d.ts} +39 -43
- package/dist/esm/shared/errors/error-code.js +24 -0
- package/dist/{shared/errors/errors.js → esm/shared/errors/errors.d.ts} +92 -98
- package/dist/esm/shared/errors/errors.js +110 -0
- package/dist/{shared/logging/logger.js → esm/shared/logging/logger.d.ts} +22 -52
- package/dist/esm/shared/logging/logger.js +25 -0
- package/dist/esm/shared/logging/redaction.d.ts +123 -0
- package/dist/esm/shared/logging/redaction.js +140 -0
- package/dist/{shared/logging/secret-patterns.js → esm/shared/logging/secret-patterns.d.ts} +46 -87
- package/dist/esm/shared/logging/secret-patterns.js +83 -0
- package/dist/{shared/logging/truncate.js → esm/shared/logging/truncate.d.ts} +6 -40
- package/dist/esm/shared/logging/truncate.js +25 -0
- package/dist/esm/shared/options.d.ts +100 -0
- package/dist/esm/shared/options.js +1 -0
- package/dist/{shared/ulid.js → esm/shared/ulid.d.ts} +4 -84
- package/dist/esm/shared/ulid.js +77 -0
- package/dist/{shared/validation/collaborators.js → esm/shared/validation/collaborators.d.ts} +37 -65
- package/dist/esm/shared/validation/collaborators.js +70 -0
- package/dist/{shared/validation/option-shape.js → esm/shared/validation/option-shape.d.ts} +14 -36
- package/dist/esm/shared/validation/option-shape.js +24 -0
- package/dist/esm/shared/validation/options.d.ts +145 -0
- package/dist/esm/shared/validation/options.js +156 -0
- package/dist/{shared/validation/primitives.js → esm/shared/validation/primitives.d.ts} +30 -125
- package/dist/esm/shared/validation/primitives.js +100 -0
- package/dist/esm/shared/validation/ttl.d.ts +94 -0
- package/dist/esm/shared/validation/ttl.js +46 -0
- package/dist/esm/store/actions/list-namespaces.d.ts +79 -0
- package/dist/esm/store/actions/list-namespaces.js +86 -0
- package/dist/esm/store/actions/put.d.ts +43 -0
- package/dist/esm/store/actions/put.js +46 -0
- package/dist/{store/actions/reconcile-vector-index.js → esm/store/actions/reconcile-vector-index.d.ts} +8 -16
- package/dist/esm/store/actions/reconcile-vector-index.js +10 -0
- package/dist/esm/store/actions/search.d.ts +38 -0
- package/dist/esm/store/actions/search.js +23 -0
- package/dist/esm/store/internal/batch-plan.d.ts +56 -0
- package/dist/esm/store/internal/batch-plan.js +28 -0
- package/dist/esm/store/internal/filter.d.ts +43 -0
- package/dist/esm/store/internal/filter.js +60 -0
- package/dist/esm/store/internal/get-item.d.ts +77 -0
- package/dist/esm/store/internal/get-item.js +54 -0
- package/dist/esm/store/internal/item-write.d.ts +270 -0
- package/dist/esm/store/internal/item-write.js +173 -0
- package/dist/esm/store/internal/parse.d.ts +230 -0
- package/dist/esm/store/internal/parse.js +169 -0
- package/dist/{store/internal/rows.js → esm/store/internal/rows.d.ts} +111 -199
- package/dist/esm/store/internal/rows.js +147 -0
- package/dist/esm/store/internal/semantic-search.d.ts +168 -0
- package/dist/esm/store/internal/semantic-search.js +200 -0
- package/dist/esm/store/internal/setup.d.ts +96 -0
- package/dist/esm/store/internal/setup.js +98 -0
- package/dist/esm/store/internal/table-search.d.ts +100 -0
- package/dist/esm/store/internal/table-search.js +119 -0
- package/dist/esm/store/internal/vector-index.d.ts +258 -0
- package/dist/esm/store/internal/vector-index.js +256 -0
- package/dist/{store/store.js → esm/store/store.d.ts} +99 -133
- package/dist/esm/store/store.js +93 -0
- package/dist/esm/store/types.d.ts +111 -0
- package/dist/esm/store/types.js +1 -0
- package/dist/esm/store/vector-backend.d.ts +104 -0
- package/dist/esm/store/vector-backend.js +1 -0
- package/package.json +50 -44
- package/dist/backfill/backfill.js +0 -393
- package/dist/checkpointer/actions/list.js +0 -142
- package/dist/checkpointer/actions/put.js +0 -195
- package/dist/checkpointer/internal/delta-history.js +0 -252
- package/dist/checkpointer/internal/parse.js +0 -372
- package/dist/checkpointer/internal/pending-writes.js +0 -588
- package/dist/checkpointer/internal/read.js +0 -264
- package/dist/checkpointer/internal/rows.js +0 -834
- package/dist/checkpointer/internal/setup.js +0 -72
- package/dist/checkpointer/types.js +0 -12
- package/dist/factory/factory.js +0 -266
- package/dist/factory/types.js +0 -10
- package/dist/history/actions/get-messages.js +0 -141
- package/dist/history/actions/list-sessions.js +0 -156
- package/dist/history/internal/append.js +0 -500
- package/dist/history/internal/message-read.js +0 -204
- package/dist/history/internal/parse.js +0 -252
- package/dist/history/internal/session.js +0 -628
- package/dist/history/internal/setup.js +0 -106
- package/dist/history/types.js +0 -12
- package/dist/index.js +0 -51
- package/dist/shared/adapter.js +0 -143
- package/dist/shared/codec/codec.js +0 -441
- package/dist/shared/codec/compression.js +0 -89
- package/dist/shared/codec/json-serde.js +0 -191
- package/dist/shared/codec/s3/client-types.js +0 -26
- package/dist/shared/codec/s3/client.js +0 -97
- package/dist/shared/codec/s3/lifecycle.js +0 -355
- package/dist/shared/codec/s3/offloader.js +0 -658
- package/dist/shared/dynamodb/batch-write.js +0 -173
- package/dist/shared/dynamodb/paginate.js +0 -188
- package/dist/shared/dynamodb/partition-delete.js +0 -340
- package/dist/shared/dynamodb/recency-index.js +0 -377
- package/dist/shared/dynamodb/retry.js +0 -463
- package/dist/shared/errors/base-error.js +0 -174
- package/dist/shared/errors/boundary.js +0 -143
- package/dist/shared/errors/classify.d.ts +0 -97
- package/dist/shared/errors/classify.js +0 -257
- package/dist/shared/logging/redaction.js +0 -316
- package/dist/shared/options.js +0 -11
- package/dist/shared/validation/options.js +0 -328
- package/dist/shared/validation/ttl.js +0 -132
- package/dist/store/actions/list-namespaces.js +0 -197
- package/dist/store/actions/put.js +0 -78
- package/dist/store/actions/search.js +0 -66
- package/dist/store/internal/batch-plan.d.ts +0 -26
- package/dist/store/internal/batch-plan.js +0 -109
- package/dist/store/internal/filter.js +0 -137
- package/dist/store/internal/get-item.d.ts +0 -45
- package/dist/store/internal/get-item.js +0 -115
- package/dist/store/internal/item-write.js +0 -463
- package/dist/store/internal/parse.js +0 -350
- package/dist/store/internal/semantic-search.js +0 -389
- package/dist/store/internal/setup.js +0 -223
- package/dist/store/internal/table-search.js +0 -213
- package/dist/store/internal/vector-index.js +0 -546
- package/dist/store/types.js +0 -15
- package/dist/store/vector-backend.js +0 -17
- /package/dist/{shared → cjs/shared}/clock.d.ts +0 -0
- /package/dist/{shared → cjs/shared}/codec/json-serde.d.ts +0 -0
- /package/dist/{shared → cjs/shared}/concurrency.d.ts +0 -0
- /package/dist/{shared → cjs/shared}/dynamodb/cancellation.d.ts +0 -0
- /package/dist/{shared → cjs/shared}/logging/logger.d.ts +0 -0
- /package/dist/{shared → cjs/shared}/logging/truncate.d.ts +0 -0
- /package/dist/{shared → cjs/shared}/ulid.d.ts +0 -0
- /package/dist/{shared → cjs/shared}/validation/primitives.d.ts +0 -0
- /package/dist/{store → cjs/store}/vector-backend.d.ts +0 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { collectS3Keys } from '../../shared/codec/codec.js';
|
|
2
|
+
import { cleanUpS3Orphans } from '../../shared/codec/s3/offloader.js';
|
|
3
|
+
import { mapWithConcurrency } from '../../shared/concurrency.js';
|
|
4
|
+
import { abortErrorFrom } from '../../shared/dynamodb/abort.js';
|
|
5
|
+
import { commitRow, isConditionalCheckFailed, OVERWRITE_CAS_MAX_ATTEMPTS, readRow, rejectedRow, revisionGuard, settledVerdict, verdictFor, verifyRow, } from '../../shared/dynamodb/idempotent-write.js';
|
|
6
|
+
import { withDynamoDBRetry, retryFor } from '../../shared/dynamodb/retry.js';
|
|
7
|
+
import { PARTITION_KEY_ATTRIBUTE, rowKeyOf } from '../../shared/dynamodb/table-schema.js';
|
|
8
|
+
import { truncateForLog } from '../../shared/logging/truncate.js';
|
|
9
|
+
import { WRITE_GROUP_ATTRIBUTE } from './rows.js';
|
|
10
|
+
export async function commitPendingWrites(context, batch) {
|
|
11
|
+
const special = batch.items.filter((item) => item.index < 0);
|
|
12
|
+
const regular = batch.items.filter((item) => item.index >= 0);
|
|
13
|
+
const [specialError, regularOutcome] = await Promise.all([
|
|
14
|
+
writeSpecialRowsWithCleanup(context, batch.threadId, special, batch.signal),
|
|
15
|
+
writeRegularRows(context, regular, batch.signal),
|
|
16
|
+
]);
|
|
17
|
+
await releaseDeadUploads(context, regularOutcome.deadUploads);
|
|
18
|
+
const firstError = specialError ?? regularOutcome.error;
|
|
19
|
+
if (firstError)
|
|
20
|
+
throw firstError;
|
|
21
|
+
}
|
|
22
|
+
async function releaseDeadUploads(context, dead) {
|
|
23
|
+
if (!context.offloader)
|
|
24
|
+
return;
|
|
25
|
+
await cleanUpS3Orphans(context.offloader, {
|
|
26
|
+
keys: collectS3Keys(dead.map((item) => item.value)),
|
|
27
|
+
operation: 'putWrites',
|
|
28
|
+
logger: context.logger,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
async function commitSpecialRow(context, item, guard, signal) {
|
|
32
|
+
await commitRow(context, item, item.value, { guard, signal });
|
|
33
|
+
}
|
|
34
|
+
async function attemptCasWrites(context, item, initial, signal) {
|
|
35
|
+
let observed = initial;
|
|
36
|
+
for (let attempt = 1; attempt <= OVERWRITE_CAS_MAX_ATTEMPTS; attempt++) {
|
|
37
|
+
if (signal?.aborted) {
|
|
38
|
+
return { done: true, outcome: { committed: false, error: abortErrorFrom(signal) } };
|
|
39
|
+
}
|
|
40
|
+
const attempted = observed;
|
|
41
|
+
try {
|
|
42
|
+
await commitSpecialRow(context, item, revisionGuard(WRITE_GROUP_ATTRIBUTE, attempted), signal);
|
|
43
|
+
return { done: true, outcome: { committed: true, superseded: attempted.value } };
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
const verified = await verifyAfterFailure(context, item, attempted, error);
|
|
47
|
+
if (!verified.observed || !isConditionalCheckFailed(error)) {
|
|
48
|
+
return { done: true, outcome: verified.outcome };
|
|
49
|
+
}
|
|
50
|
+
observed = verified.observed;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return { done: false, observed };
|
|
54
|
+
}
|
|
55
|
+
async function overwriteUnconditionally(context, item, observed, signal) {
|
|
56
|
+
if (signal?.aborted)
|
|
57
|
+
return { committed: false, error: abortErrorFrom(signal) };
|
|
58
|
+
try {
|
|
59
|
+
await commitSpecialRow(context, item, undefined, signal);
|
|
60
|
+
return { committed: true, superseded: observed.value };
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
return (await verifyAfterFailure(context, item, observed, error, false)).outcome;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function writeWithoutOffloader(context, item, signal) {
|
|
67
|
+
try {
|
|
68
|
+
await withDynamoDBRetry((request) => context.client.put({ TableName: context.tableName, Item: item }, request), retryFor(context, signal));
|
|
69
|
+
return { committed: true };
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
return { committed: false, error: error };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export async function writeSpecialRow(context, item, signal) {
|
|
76
|
+
if (!context.offloader)
|
|
77
|
+
return writeWithoutOffloader(context, item, signal);
|
|
78
|
+
try {
|
|
79
|
+
const initial = await readSpecialRow(context, item);
|
|
80
|
+
const attempt = await attemptCasWrites(context, item, initial, signal);
|
|
81
|
+
if (attempt.done)
|
|
82
|
+
return attempt.outcome;
|
|
83
|
+
context.logger.warn('putWrites: special-write compare-and-swap exhausted; overwriting unconditionally, which ' +
|
|
84
|
+
'can orphan one S3 object under a concurrent call (reclaimed by ensureS3LifecycleRule)', { sortKey: item.SK, channel: item.channel, attempts: OVERWRITE_CAS_MAX_ATTEMPTS });
|
|
85
|
+
return await overwriteUnconditionally(context, item, attempt.observed, signal);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
return { committed: true, error: error };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export function writeRowProbe(item) {
|
|
92
|
+
return {
|
|
93
|
+
key: rowKeyOf(item),
|
|
94
|
+
kind: 'attribute',
|
|
95
|
+
attribute: WRITE_GROUP_ATTRIBUTE,
|
|
96
|
+
expected: item.writeGroup,
|
|
97
|
+
also: ['value'],
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function stateOf(row) {
|
|
101
|
+
if (!row)
|
|
102
|
+
return { exists: false };
|
|
103
|
+
return {
|
|
104
|
+
exists: true,
|
|
105
|
+
value: row.value,
|
|
106
|
+
revision: row[WRITE_GROUP_ATTRIBUTE],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export async function readSpecialRow(context, item) {
|
|
110
|
+
return stateOf(await readRow(context, writeRowProbe(item)));
|
|
111
|
+
}
|
|
112
|
+
export async function verifyAfterFailure(context, item, attempted, error, pinned = true) {
|
|
113
|
+
const probe = writeRowProbe(item);
|
|
114
|
+
const rejected = isConditionalCheckFailed(error) ? rejectedRow(error) : undefined;
|
|
115
|
+
const read = rejected
|
|
116
|
+
? { verdict: verdictFor(probe, rejected), row: rejected }
|
|
117
|
+
: await verifyRow(context, probe);
|
|
118
|
+
const verdict = rejected === undefined && (!pinned || stillPinned(attempted, read.row))
|
|
119
|
+
? settledVerdict(read.verdict, error)
|
|
120
|
+
: read.verdict;
|
|
121
|
+
if (verdict === 'landed')
|
|
122
|
+
return { outcome: { committed: true, superseded: attempted.value } };
|
|
123
|
+
if (verdict === 'unverified')
|
|
124
|
+
return { outcome: { committed: true, error } };
|
|
125
|
+
return { outcome: { committed: false, error }, observed: stateOf(read.row) };
|
|
126
|
+
}
|
|
127
|
+
function stillPinned(attempted, row) {
|
|
128
|
+
const current = stateOf(row);
|
|
129
|
+
if (current.revision !== attempted.revision)
|
|
130
|
+
return false;
|
|
131
|
+
if (current.exists === attempted.exists)
|
|
132
|
+
return true;
|
|
133
|
+
return !current.exists && attempted.revision === undefined;
|
|
134
|
+
}
|
|
135
|
+
async function deleteDescriptors(context, descriptors, label, scope) {
|
|
136
|
+
if (!context.offloader)
|
|
137
|
+
return;
|
|
138
|
+
await cleanUpS3Orphans(context.offloader, {
|
|
139
|
+
keys: collectS3Keys(descriptors.filter((ref) => Boolean(ref))),
|
|
140
|
+
operation: label,
|
|
141
|
+
logger: context.logger,
|
|
142
|
+
...(scope === undefined ? {} : { scope }),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
export async function writeSpecialRowsWithCleanup(context, threadId, items, signal) {
|
|
146
|
+
if (items.length === 0)
|
|
147
|
+
return undefined;
|
|
148
|
+
const outcomes = await Promise.all(items.map(async (item) => [
|
|
149
|
+
item,
|
|
150
|
+
await writeSpecialRow(context, item, signal),
|
|
151
|
+
]));
|
|
152
|
+
await deleteDescriptors(context, outcomes.filter(([, o]) => o.committed).map(([, o]) => o.superseded), 'putWrites.special.previous', [threadId]);
|
|
153
|
+
await deleteDescriptors(context, outcomes.filter(([, o]) => !o.committed).map(([item]) => item.value), 'putWrites.special.newUpload');
|
|
154
|
+
return outcomes.find(([, o]) => o.error)?.[1].error;
|
|
155
|
+
}
|
|
156
|
+
const FIRST_WRITE_WINS = {
|
|
157
|
+
ConditionExpression: `attribute_not_exists(${PARTITION_KEY_ATTRIBUTE})`,
|
|
158
|
+
ReturnValuesOnConditionCheckFailure: 'ALL_OLD',
|
|
159
|
+
};
|
|
160
|
+
async function commitWriteRow(context, item, signal) {
|
|
161
|
+
await commitRow(context, item, item.value, { guard: FIRST_WRITE_WINS, signal });
|
|
162
|
+
}
|
|
163
|
+
async function verifyFailure(context, item) {
|
|
164
|
+
if (!context.offloader)
|
|
165
|
+
return { verdict: 'not-landed' };
|
|
166
|
+
return verifyRow(context, writeRowProbe(item));
|
|
167
|
+
}
|
|
168
|
+
export const REGULAR_WRITE_CONCURRENCY = 32;
|
|
169
|
+
export async function writeRegularRows(context, items, signal) {
|
|
170
|
+
const settled = await mapWithConcurrency(items, REGULAR_WRITE_CONCURRENCY, async (item) => {
|
|
171
|
+
if (signal?.aborted)
|
|
172
|
+
return { ok: false, reason: abortErrorFrom(signal), sent: false };
|
|
173
|
+
try {
|
|
174
|
+
await commitWriteRow(context, item, signal);
|
|
175
|
+
return { ok: true };
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
return { ok: false, reason: error, sent: true };
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
const outcome = { deadUploads: [] };
|
|
182
|
+
for (const [index, result] of settled.entries()) {
|
|
183
|
+
if (result.ok)
|
|
184
|
+
continue;
|
|
185
|
+
const item = items[index];
|
|
186
|
+
const { reason } = result;
|
|
187
|
+
if (!result.sent) {
|
|
188
|
+
outcome.deadUploads.push(item);
|
|
189
|
+
outcome.error = outcome.error ?? reason;
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (isConditionalCheckFailed(reason)) {
|
|
193
|
+
reportGuardRejection(context, item, reason);
|
|
194
|
+
if (rejectionProvesForeignRow(item, reason))
|
|
195
|
+
outcome.deadUploads.push(item);
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
const { verdict, row } = await verifyFailure(context, item);
|
|
199
|
+
const settledNow = row === undefined ? settledVerdict(verdict, reason) : verdict;
|
|
200
|
+
if (settledNow === 'landed')
|
|
201
|
+
continue;
|
|
202
|
+
if (settledNow === 'not-landed')
|
|
203
|
+
outcome.deadUploads.push(item);
|
|
204
|
+
outcome.error = outcome.error ?? reason;
|
|
205
|
+
}
|
|
206
|
+
return outcome;
|
|
207
|
+
}
|
|
208
|
+
function rejectedChannel(error) {
|
|
209
|
+
return rejectedRow(error)?.channel;
|
|
210
|
+
}
|
|
211
|
+
export function reportGuardRejection(context, item, error) {
|
|
212
|
+
const found = rejectedChannel(error);
|
|
213
|
+
if (found !== undefined && found !== item.channel) {
|
|
214
|
+
context.logger.warn('putWrites: write row held by an unexpected channel; write not persisted', {
|
|
215
|
+
sortKey: item.SK,
|
|
216
|
+
expected: item.channel,
|
|
217
|
+
found: truncateForLog(found),
|
|
218
|
+
});
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
context.logger.debug('putWrites: skipped a write already committed for this task and channel', {
|
|
222
|
+
sortKey: item.SK,
|
|
223
|
+
channel: item.channel,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
export function rejectionProvesForeignRow(item, error) {
|
|
227
|
+
const group = rejectedRow(error)?.writeGroup;
|
|
228
|
+
return group !== undefined && group !== item.writeGroup;
|
|
229
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hides which rows a checkpoint read issues, with what consistency, and how a
|
|
3
|
+
* checkpoint an older release wrote is read back.
|
|
4
|
+
*
|
|
5
|
+
* A tuple is a META row, a PAYLOAD row and a checkpoint's WRITE rows, read
|
|
6
|
+
* strongly for `getTuple` and eventually for `list`, with expired rows absent
|
|
7
|
+
* however long DynamoDB's sweep lags, and with a pre-v4 checkpoint's `Send`s
|
|
8
|
+
* migrated from its parent's pending writes. The caller asks for a tuple; which
|
|
9
|
+
* reads that takes, and in what order, is decided here.
|
|
10
|
+
*/
|
|
11
|
+
import { type Checkpoint, type CheckpointMetadata, type CheckpointPendingWrite, type CheckpointTuple } from '@langchain/langgraph-checkpoint';
|
|
12
|
+
import type { ThreadAddress } from './parse.js';
|
|
13
|
+
import { type CheckpointLocation, type CheckpointMetaRow, type CheckpointPayloadRow, type MetaReader } from './rows.js';
|
|
14
|
+
import type { CheckpointerContext } from './setup.js';
|
|
15
|
+
/** The thread and namespace a read was asked for. */
|
|
16
|
+
export interface ThreadLocation {
|
|
17
|
+
readonly threadId: string;
|
|
18
|
+
readonly checkpointNs: string;
|
|
19
|
+
}
|
|
20
|
+
/** A checkpoint's parent, whose pending writes a pre-v4 checkpoint's migration reads. */
|
|
21
|
+
export interface PendingSendsSource extends ThreadLocation {
|
|
22
|
+
readonly parentCheckpointId: string | undefined;
|
|
23
|
+
}
|
|
24
|
+
/** Per-read options for the payload and writes reads. */
|
|
25
|
+
export interface ReadOptions {
|
|
26
|
+
signal?: AbortSignal;
|
|
27
|
+
/** `false` for bulk reads (`list`) that trade read-your-writes for half the read cost. */
|
|
28
|
+
consistent?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The META row a read is about: the one `checkpointId` names, else the newest
|
|
32
|
+
* in the namespace.
|
|
33
|
+
*
|
|
34
|
+
* Accepts: `address` — parsed; its `checkpointId` names the row, and its
|
|
35
|
+
* absence asks for the newest in the namespace. `signal` — aborts the read.
|
|
36
|
+
* `reader` — the public method this read serves, named when a foreign row is
|
|
37
|
+
* reported; `getTuple` unless the caller says otherwise.
|
|
38
|
+
*
|
|
39
|
+
* Returns: the row, or undefined when there is none — including when every row
|
|
40
|
+
* in the namespace has expired, or when the only rows there belong to another
|
|
41
|
+
* writer.
|
|
42
|
+
*
|
|
43
|
+
* Throws: `FORMAT_UNSUPPORTED` for a row of ours written by a newer version;
|
|
44
|
+
* whatever the read throws.
|
|
45
|
+
*
|
|
46
|
+
* Guarantees: strongly consistent, and expiry is judged here rather than waited
|
|
47
|
+
* for, so a checkpoint past its ttl is absent to every reader however long
|
|
48
|
+
* DynamoDB's sweep lags. The newest-first read returns the first live row of
|
|
49
|
+
* ours and stops there, stepping over expired and foreign rows
|
|
50
|
+
* {@link LATEST_META_PAGE_SIZE} at a time when the adapter has a `ttl`, and
|
|
51
|
+
* reading one row per page when it has none.
|
|
52
|
+
*/
|
|
53
|
+
export declare function fetchTargetMeta(context: CheckpointerContext, address: ThreadAddress, signal?: AbortSignal, reader?: MetaReader): Promise<CheckpointMetaRow | undefined>;
|
|
54
|
+
/**
|
|
55
|
+
* The PAYLOAD row of one checkpoint.
|
|
56
|
+
*
|
|
57
|
+
* Accepts: `at` — the checkpoint's location. `read.consistent` — defaults to
|
|
58
|
+
* true; `list` passes false and accepts replica lag, since a listing tolerates
|
|
59
|
+
* what a read-your-writes `getTuple` does not.
|
|
60
|
+
*
|
|
61
|
+
* Returns: the row, or undefined when it is not there — the two rows land in
|
|
62
|
+
* one transaction, so that is a thread being deleted row by row, or DynamoDB's
|
|
63
|
+
* expiry sweep reaching the PAYLOAD row before the META row — which the caller
|
|
64
|
+
* answers as "no checkpoint".
|
|
65
|
+
*
|
|
66
|
+
* Throws: `FORMAT_UNSUPPORTED` for a row a newer release wrote; whatever the
|
|
67
|
+
* read throws.
|
|
68
|
+
*/
|
|
69
|
+
export declare function fetchPayload(context: CheckpointerContext, at: CheckpointLocation, read?: ReadOptions): Promise<CheckpointPayloadRow | undefined>;
|
|
70
|
+
/**
|
|
71
|
+
* Every pending write stored for one checkpoint, decoded, in write order.
|
|
72
|
+
*
|
|
73
|
+
* Accepts: `at` — the checkpoint's location. `read.consistent` — omitted reads
|
|
74
|
+
* strongly consistently; `list` passes `false` explicitly and accepts replica
|
|
75
|
+
* lag, `getTuple` passes `true`.
|
|
76
|
+
*
|
|
77
|
+
* Returns: the writes after `dropSupersededWrites` has resolved
|
|
78
|
+
* first-write-wins; a checkpoint with none returns an empty array.
|
|
79
|
+
*
|
|
80
|
+
* Throws: `FORMAT_UNSUPPORTED` for a row a newer release wrote; whatever the
|
|
81
|
+
* query or the payload decode throws.
|
|
82
|
+
*
|
|
83
|
+
* Guarantees: the read is deliberately uncapped. It must be complete to be
|
|
84
|
+
* correct — a `Send` fan-out retried with a changed write order leaves
|
|
85
|
+
* superseded rows behind that would count toward any cap — so past
|
|
86
|
+
* {@link LIST_SCAN_WARN_THRESHOLD} rows the read still succeeds and an operator
|
|
87
|
+
* is told the checkpoint is unusually heavy.
|
|
88
|
+
*/
|
|
89
|
+
export declare function fetchPendingWrites(context: CheckpointerContext, at: CheckpointLocation, read?: ReadOptions): Promise<CheckpointPendingWrite[]>;
|
|
90
|
+
/** How a tuple is assembled: cancellation, read consistency, and metadata already decoded by the caller. */
|
|
91
|
+
export interface AssembleOptions {
|
|
92
|
+
signal?: AbortSignal;
|
|
93
|
+
/** `true` for `getTuple` (read-your-writes), `false` for the eventually-consistent `list` path. */
|
|
94
|
+
consistent: boolean;
|
|
95
|
+
/** Metadata the caller decoded to apply a filter, so it is not decoded (or downloaded) twice. */
|
|
96
|
+
metadata?: CheckpointMetadata;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* A full {@link CheckpointTuple} built from a META row.
|
|
100
|
+
*
|
|
101
|
+
* Accepts: `thread` — the **caller's** location, never the row's: `thread.threadId`
|
|
102
|
+
* scopes which S3 object the row may point at, so it must come from the
|
|
103
|
+
* partition the caller asked for; `thread.checkpointNs` is its namespace.
|
|
104
|
+
* `options.metadata` — already decoded by a filtered `list`, so a filtered
|
|
105
|
+
* listing decodes and downloads each metadata blob once, not twice.
|
|
106
|
+
* `options.consistent` — true for `getTuple`, false for `list`.
|
|
107
|
+
*
|
|
108
|
+
* Returns: the tuple, with `parentConfig` set only when the row names a parent;
|
|
109
|
+
* `undefined` when the PAYLOAD row is absent — a thread mid-delete, or an
|
|
110
|
+
* expiry sweep that reached the PAYLOAD row first — the same answer a caller
|
|
111
|
+
* gets for a checkpoint that does not exist.
|
|
112
|
+
*
|
|
113
|
+
* Throws: whatever the reads and decodes throw.
|
|
114
|
+
*/
|
|
115
|
+
export declare function assembleTuple(context: CheckpointerContext, thread: ThreadLocation, meta: CheckpointMetaRow, options: AssembleOptions): Promise<CheckpointTuple | undefined>;
|
|
116
|
+
/**
|
|
117
|
+
* Pre-v4 checkpoints kept a task's `Send`s as `__pregel_tasks` pending writes
|
|
118
|
+
* on the parent rather than in the checkpoint itself. Reading such a
|
|
119
|
+
* checkpoint rebuilds `channel_values[TASKS]` from those writes and stamps
|
|
120
|
+
* the channel with the highest version the checkpoint already carries (or
|
|
121
|
+
* the first version when it carries none), exactly as the reference savers
|
|
122
|
+
* do, so a thread written before LangGraph 0.2 still resumes.
|
|
123
|
+
*
|
|
124
|
+
* Accepts: `checkpoint` — any version. `parent` — the checkpoint's own thread
|
|
125
|
+
* and namespace, plus `parent.parentCheckpointId`, the parent whose pending
|
|
126
|
+
* writes hold the sends; absent means there is nowhere to migrate from.
|
|
127
|
+
* `read` — cancellation and consistency for the pending-writes read.
|
|
128
|
+
*
|
|
129
|
+
* Returns: the checkpoint untouched when it is v4 or has no parent, and
|
|
130
|
+
* otherwise a copy with `channel_values[TASKS]` rebuilt. The input is never
|
|
131
|
+
* mutated.
|
|
132
|
+
*
|
|
133
|
+
* Throws: whatever reading the parent's pending writes throws.
|
|
134
|
+
*/
|
|
135
|
+
export declare function migratePendingSends(context: CheckpointerContext, checkpoint: Checkpoint, parent: PendingSendsSource, read: ReadOptions): Promise<Checkpoint>;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { maxChannelVersion, TASKS, } from '@langchain/langgraph-checkpoint';
|
|
2
|
+
import { nowSeconds } from '../../shared/clock.js';
|
|
3
|
+
import { LIST_SCAN_WARN_THRESHOLD, paginateQuery } from '../../shared/dynamodb/paginate.js';
|
|
4
|
+
import { withDynamoDBRetry, retryFor } from '../../shared/dynamodb/retry.js';
|
|
5
|
+
import { isExpiredRow, withoutExpired, assertReadableRow, } from '../../shared/dynamodb/table-schema.js';
|
|
6
|
+
import { truncateForLog } from '../../shared/logging/truncate.js';
|
|
7
|
+
import { beginsWithQuery, metaRowKey, metaSortKeyPrefix, parseHeadRow, parseWriteRow, partitionKey, payloadRowKey, readCheckpoint, readMetadata, toPendingWrites, writeSortKeyPrefix, } from './rows.js';
|
|
8
|
+
const LATEST_META_PAGE_SIZE = 50;
|
|
9
|
+
export async function fetchTargetMeta(context, address, signal, reader = 'getTuple') {
|
|
10
|
+
const { threadId, checkpointNs, checkpointId } = address;
|
|
11
|
+
const now = nowSeconds();
|
|
12
|
+
if (checkpointId !== undefined) {
|
|
13
|
+
const result = await withDynamoDBRetry((request) => context.client.get({
|
|
14
|
+
TableName: context.tableName,
|
|
15
|
+
Key: metaRowKey({ threadId, checkpointNs, checkpointId }),
|
|
16
|
+
ConsistentRead: true,
|
|
17
|
+
}, request), retryFor(context, signal));
|
|
18
|
+
const meta = parseHeadRow(context, result.Item, reader);
|
|
19
|
+
return meta && !isExpiredRow(meta, now) ? meta : undefined;
|
|
20
|
+
}
|
|
21
|
+
const params = beginsWithQuery(context.tableName, partitionKey(threadId), metaSortKeyPrefix(checkpointNs), {
|
|
22
|
+
limit: context.ttl === undefined ? 1 : LATEST_META_PAGE_SIZE,
|
|
23
|
+
consistent: true,
|
|
24
|
+
});
|
|
25
|
+
const rows = paginateQuery({
|
|
26
|
+
retry: retryFor(context, signal),
|
|
27
|
+
signal,
|
|
28
|
+
client: context.client,
|
|
29
|
+
params: withoutExpired(params, now),
|
|
30
|
+
maxItems: Number.POSITIVE_INFINITY,
|
|
31
|
+
maxIterations: Number.POSITIVE_INFINITY,
|
|
32
|
+
});
|
|
33
|
+
for await (const raw of rows) {
|
|
34
|
+
const meta = parseHeadRow(context, raw, reader);
|
|
35
|
+
if (meta && !isExpiredRow(meta, now))
|
|
36
|
+
return meta;
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
export async function fetchPayload(context, at, read = {}) {
|
|
41
|
+
const result = await withDynamoDBRetry((request) => context.client.get({
|
|
42
|
+
TableName: context.tableName,
|
|
43
|
+
Key: payloadRowKey(at),
|
|
44
|
+
ConsistentRead: read.consistent ?? true,
|
|
45
|
+
}, request), retryFor(context, read.signal));
|
|
46
|
+
const item = result.Item;
|
|
47
|
+
if (item !== undefined)
|
|
48
|
+
assertReadableRow(item, 'checkpoint payload');
|
|
49
|
+
return item;
|
|
50
|
+
}
|
|
51
|
+
export async function fetchPendingWrites(context, at, read = {}) {
|
|
52
|
+
const params = beginsWithQuery(context.tableName, partitionKey(at.threadId), writeSortKeyPrefix(at.checkpointNs, at.checkpointId), { ascending: true, consistent: read.consistent ?? true });
|
|
53
|
+
const items = [];
|
|
54
|
+
for await (const item of paginateQuery({
|
|
55
|
+
retry: retryFor(context, read.signal),
|
|
56
|
+
signal: read.signal,
|
|
57
|
+
client: context.client,
|
|
58
|
+
params,
|
|
59
|
+
maxItems: Number.POSITIVE_INFINITY,
|
|
60
|
+
maxIterations: Number.POSITIVE_INFINITY,
|
|
61
|
+
})) {
|
|
62
|
+
const row = parseWriteRow(item);
|
|
63
|
+
if (row === undefined) {
|
|
64
|
+
context.logger.warn('getTuple: skipped a row that is not a pending-write item', {
|
|
65
|
+
sortKey: truncateForLog(item.SK),
|
|
66
|
+
});
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
items.push(row);
|
|
70
|
+
}
|
|
71
|
+
if (items.length >= LIST_SCAN_WARN_THRESHOLD) {
|
|
72
|
+
context.logger.warn('getTuple: a checkpoint carries very many pending-write rows; the read is complete but slow', {
|
|
73
|
+
threadId: at.threadId,
|
|
74
|
+
checkpointId: at.checkpointId,
|
|
75
|
+
rows: items.length,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return toPendingWrites(context, items, at.threadId, read.signal);
|
|
79
|
+
}
|
|
80
|
+
function configFor(threadId, checkpointNs, checkpointId) {
|
|
81
|
+
return {
|
|
82
|
+
configurable: { thread_id: threadId, checkpoint_ns: checkpointNs, checkpoint_id: checkpointId },
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
export async function assembleTuple(context, thread, meta, options) {
|
|
86
|
+
const read = { signal: options.signal, consistent: options.consistent };
|
|
87
|
+
const at = { ...thread, checkpointId: meta.checkpointId };
|
|
88
|
+
const payload = await fetchPayload(context, at, read);
|
|
89
|
+
if (!payload)
|
|
90
|
+
return undefined;
|
|
91
|
+
const [checkpoint, metadata, pendingWrites] = await Promise.all([
|
|
92
|
+
readCheckpoint(context, payload, thread.threadId, options.signal).then((stored) => migratePendingSends(context, stored, { ...thread, parentCheckpointId: meta.parentCheckpointId }, read)),
|
|
93
|
+
options.metadata ?? readMetadata(context, meta, thread.threadId, options.signal),
|
|
94
|
+
fetchPendingWrites(context, at, read),
|
|
95
|
+
]);
|
|
96
|
+
const tuple = {
|
|
97
|
+
config: configFor(thread.threadId, thread.checkpointNs, meta.checkpointId),
|
|
98
|
+
checkpoint,
|
|
99
|
+
metadata,
|
|
100
|
+
pendingWrites,
|
|
101
|
+
};
|
|
102
|
+
if (meta.parentCheckpointId !== undefined) {
|
|
103
|
+
tuple.parentConfig = configFor(thread.threadId, thread.checkpointNs, meta.parentCheckpointId);
|
|
104
|
+
}
|
|
105
|
+
return tuple;
|
|
106
|
+
}
|
|
107
|
+
export async function migratePendingSends(context, checkpoint, parent, read) {
|
|
108
|
+
if (checkpoint.v >= 4 || parent.parentCheckpointId === undefined)
|
|
109
|
+
return checkpoint;
|
|
110
|
+
const writes = await fetchPendingWrites(context, {
|
|
111
|
+
threadId: parent.threadId,
|
|
112
|
+
checkpointNs: parent.checkpointNs,
|
|
113
|
+
checkpointId: parent.parentCheckpointId,
|
|
114
|
+
}, read);
|
|
115
|
+
const sends = writes.filter(([, channel]) => channel === TASKS).map(([, , value]) => value);
|
|
116
|
+
const versions = Object.values(checkpoint.channel_versions);
|
|
117
|
+
return {
|
|
118
|
+
...checkpoint,
|
|
119
|
+
channel_values: { ...checkpoint.channel_values, [TASKS]: sends },
|
|
120
|
+
channel_versions: {
|
|
121
|
+
...checkpoint.channel_versions,
|
|
122
|
+
[TASKS]: versions.length > 0 ? maxChannelVersion(...versions) : 1,
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|