@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
|
@@ -5,16 +5,17 @@
|
|
|
5
5
|
* so a large append is several transactions, each writing its messages and the
|
|
6
6
|
* SESSION row's update together. When one of them fails the append is rolled
|
|
7
7
|
* back: committed chunks are deleted and their effect on the SESSION row
|
|
8
|
-
* reverted, and each S3 object is released only once no row can name it.
|
|
9
|
-
*
|
|
8
|
+
* reverted, and each S3 object is released only once no row can name it.
|
|
9
|
+
* Every failure but a refusal is read back before anything is undone, and a
|
|
10
|
+
* chunk that may still commit keeps its objects. This is also the
|
|
10
11
|
* one module that writes a message row, which is what lets a delete pin a
|
|
11
12
|
* message row to the SESSION row's `writeId`.
|
|
12
13
|
*/
|
|
13
|
-
import { type RowKey } from '../../shared/dynamodb/table-schema';
|
|
14
|
-
import type { SessionId, StorableMessages } from './parse';
|
|
15
|
-
import { type MessageRow } from './rows';
|
|
16
|
-
import { type SessionUpdateFields, type TtlAnchorResult } from './session';
|
|
17
|
-
import { type HistoryContext } from './setup';
|
|
14
|
+
import { type RowKey } from '../../shared/dynamodb/table-schema.js';
|
|
15
|
+
import type { SessionId, StorableMessages } from './parse.js';
|
|
16
|
+
import { type MessageRow } from './rows.js';
|
|
17
|
+
import { type SessionUpdateFields, type TtlAnchorResult } from './session.js';
|
|
18
|
+
import { type HistoryContext } from './setup.js';
|
|
18
19
|
/** One append, parsed: the session, its messages in stored form, and the session's ttl anchor. */
|
|
19
20
|
export interface AppendRequest {
|
|
20
21
|
readonly sessionId: SessionId;
|
|
@@ -29,6 +30,8 @@ interface AppendFields {
|
|
|
29
30
|
title?: string;
|
|
30
31
|
ttlTimestamp?: number;
|
|
31
32
|
forceTtlRefresh?: boolean;
|
|
33
|
+
/** The expired anchor the session row carries, which the first chunk starts the session over from. */
|
|
34
|
+
restart?: number;
|
|
32
35
|
}
|
|
33
36
|
/** An append cut into chunks, with the fields every chunk's SESSION update stamps. */
|
|
34
37
|
export interface ChunkedAppend {
|
|
@@ -48,6 +51,8 @@ export interface FailedAppend {
|
|
|
48
51
|
readonly trigger: Error;
|
|
49
52
|
/** True when the failing chunk's own outcome could not be read back. */
|
|
50
53
|
readonly uncertain: boolean;
|
|
54
|
+
/** Why the failing chunk's outcome is unknown: the read-back's own failure, or the write's failure when some attempt of it may still be applied. */
|
|
55
|
+
readonly unsettledBecause?: Error;
|
|
51
56
|
}
|
|
52
57
|
/**
|
|
53
58
|
* Append messages to a session: encode them, cut them into transactions, and
|
|
@@ -59,8 +64,10 @@ export interface FailedAppend {
|
|
|
59
64
|
* Returns: nothing, once every chunk has committed.
|
|
60
65
|
*
|
|
61
66
|
* Throws: the first chunk's failure after the append is rolled back;
|
|
62
|
-
* `COMPENSATION_FAILED` when the rollback itself fails
|
|
63
|
-
*
|
|
67
|
+
* `COMPENSATION_FAILED` when the rollback itself fails, or when a failing
|
|
68
|
+
* chunk's own outcome could not be established; `ABORTED` when the signal
|
|
69
|
+
* fires, after the same rollback; whatever encoding a message throws, after
|
|
70
|
+
* this call's own uploads are released.
|
|
64
71
|
*/
|
|
65
72
|
export declare function appendMessages(context: HistoryContext, request: AppendRequest): Promise<void>;
|
|
66
73
|
/**
|
|
@@ -69,8 +76,13 @@ export declare function appendMessages(context: HistoryContext, request: AppendR
|
|
|
69
76
|
* suffix is cleaned immediately, the committed prefix only after its rows are
|
|
70
77
|
* confirmed deleted. If the rollback itself fails, the committed chunks' S3
|
|
71
78
|
* objects are deliberately left in place (their rows may survive) and it
|
|
72
|
-
* raises `COMPENSATION_FAILED` carrying both the trigger and the
|
|
73
|
-
* rollback
|
|
79
|
+
* raises `COMPENSATION_FAILED` carrying both the trigger and the rollback
|
|
80
|
+
* error. Once the rollback has succeeded, it rethrows the trigger unchanged —
|
|
81
|
+
* unless the failing chunk itself is unsettled and the trigger is not a
|
|
82
|
+
* cancel, in which case it raises `COMPENSATION_FAILED` again, this time
|
|
83
|
+
* carrying `failure.unsettledBecause`: the rollback did not fail, but the
|
|
84
|
+
* session still cannot be called restored while that one chunk's own fate is
|
|
85
|
+
* unknown. A cancel is always reported as the cancel it is.
|
|
74
86
|
*
|
|
75
87
|
* `failure.uncertain` marks the failed chunk
|
|
76
88
|
* (`append.chunks[failure.committed.length]`) as one whose outcome could not be
|
|
@@ -83,18 +95,25 @@ export declare function appendMessages(context: HistoryContext, request: AppendR
|
|
|
83
95
|
* order; empty means the very first chunk failed, and then the only thing to
|
|
84
96
|
* undo is the session row this call may have created. `failure.trigger` — the
|
|
85
97
|
* failure that started this. `failure.uncertain` — see above.
|
|
98
|
+
* `failure.unsettledBecause` — why the failing chunk is unsettled, when it
|
|
99
|
+
* is: the read-back's own failure, or the write's own failure when some
|
|
100
|
+
* attempt of it may still be applied.
|
|
86
101
|
*
|
|
87
102
|
* Returns: never; the declared `Promise<never>` is the contract.
|
|
88
103
|
*
|
|
89
|
-
* Throws: `failure.trigger` when the rollback succeeded
|
|
90
|
-
* when
|
|
104
|
+
* Throws: `failure.trigger` when the rollback succeeded and the failing chunk
|
|
105
|
+
* is settled, or is a cancel; `COMPENSATION_FAILED` when the rollback itself
|
|
106
|
+
* failed, carrying both the trigger and the rollback error as
|
|
107
|
+
* `details.rollbackError`; or when the rollback succeeded but the failing
|
|
108
|
+
* chunk is unsettled and the trigger is not a cancel, carrying the trigger
|
|
109
|
+
* and `failure.unsettledBecause` as `details.rollbackError`.
|
|
91
110
|
*
|
|
92
111
|
* Guarantees: an object is deleted only once no row can reference it — the
|
|
93
112
|
* never-committed suffix immediately, the committed prefix only after its rows
|
|
94
113
|
* are confirmed gone, and an unverified chunk never. Storage is leaked in
|
|
95
114
|
* preference to leaving a live row pointing at a deleted object.
|
|
96
115
|
*
|
|
97
|
-
*
|
|
116
|
+
* None of its three log lines can stop it: all three go through
|
|
98
117
|
* {@link reportStep}. Otherwise a throw from the first would skip the S3
|
|
99
118
|
* cleanup, the rollback, the count revert and the rethrow all at once, leaving
|
|
100
119
|
* every committed chunk in the table with `messageCount` still counting it,
|
|
@@ -107,15 +126,21 @@ export declare function compensate(context: HistoryContext, append: ChunkedAppen
|
|
|
107
126
|
* messages and count in one transaction; if a later chunk fails, every
|
|
108
127
|
* already-committed chunk is deleted and its count reverted, and the batch's
|
|
109
128
|
* S3 objects are cleaned once their rows are gone, restoring the pre-call
|
|
110
|
-
* state before the error is rethrown. Except on a failed rollback,
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* committed
|
|
117
|
-
*
|
|
118
|
-
*
|
|
129
|
+
* state before the error is rethrown. Except on a failed rollback, or a chunk
|
|
130
|
+
* whose outcome cannot be established (below), which surface as
|
|
131
|
+
* `COMPENSATION_FAILED`; a failed rollback deliberately leaves the committed
|
|
132
|
+
* chunks' S3 objects behind, since their rows may survive.
|
|
133
|
+
*
|
|
134
|
+
* A failure that is not a refusal is ambiguous — the transaction may have
|
|
135
|
+
* committed and lost its response — so the chunk is read back first. Present
|
|
136
|
+
* means it committed. Absent means it did not, unless some attempt of it may
|
|
137
|
+
* still be applied by DynamoDB — one that got no answer, or one DynamoDB
|
|
138
|
+
* answered as still in progress (`TransactionInProgressException`) or with a
|
|
139
|
+
* server error (5xx). A failed read, and that last case, leave the chunk
|
|
140
|
+
* unsettled: its objects are leaked, the rest is rolled back, and the call
|
|
141
|
+
* fails with `COMPENSATION_FAILED`, or with `ABORTED` when the caller
|
|
142
|
+
* cancelled. A chunk that landed although the cancel cut its answer short is
|
|
143
|
+
* rolled back with the rest, and no chunk is sent once the signal has fired.
|
|
119
144
|
*
|
|
120
145
|
* Accepts: `append.sessionId` — the session every chunk writes to.
|
|
121
146
|
* `append.chunks` — in order, each already within the transaction's limits;
|
|
@@ -125,14 +150,19 @@ export declare function compensate(context: HistoryContext, append: ChunkedAppen
|
|
|
125
150
|
* Returns: nothing, and only when every chunk is known to have committed.
|
|
126
151
|
*
|
|
127
152
|
* Throws: the first chunk's failure, after the rollback has restored the
|
|
128
|
-
* pre-call state;
|
|
129
|
-
*
|
|
153
|
+
* pre-call state; `COMPENSATION_FAILED` carrying both that failure and the
|
|
154
|
+
* rollback's own, when the rollback could not finish; `COMPENSATION_FAILED`
|
|
155
|
+
* too, carrying the failing chunk's own unsettled reason as
|
|
156
|
+
* `details.rollbackError`, when the rollback succeeded but that chunk's own
|
|
157
|
+
* outcome could not be established; `ABORTED` when the signal fires, after
|
|
158
|
+
* the same rollback.
|
|
130
159
|
*
|
|
131
160
|
* Guarantees: each message's S3 key carries its own ULID, so no two rows of any
|
|
132
161
|
* call can address the same object and the rollback's cleanup can never delete
|
|
133
162
|
* an object a surviving row still points at. What a caller observes is
|
|
134
|
-
* all-or-nothing; what the table holds is all-or-nothing only until a
|
|
135
|
-
* fails,
|
|
163
|
+
* all-or-nothing; what the table holds is all-or-nothing only until a
|
|
164
|
+
* rollback fails, or a failing chunk's own outcome cannot be established,
|
|
165
|
+
* which is why either case is a distinct error and not a rethrow.
|
|
136
166
|
*/
|
|
137
167
|
export declare function appendChunks(context: HistoryContext, append: ChunkedAppend): Promise<void>;
|
|
138
168
|
/** Per-call retry seams (injected in tests to keep backoff instant). */
|
|
@@ -147,11 +177,13 @@ export interface ChunkRetryOptions {
|
|
|
147
177
|
* single `ClientRequestToken` is used per attempt so a re-sent commit (e.g.
|
|
148
178
|
* after a lost response) is idempotent and never double-applies the count
|
|
149
179
|
* `ADD`. When `fields.forceTtlRefresh` is set, the session update carries a
|
|
150
|
-
* monotonic ConditionExpression (see session.ts)
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
180
|
+
* monotonic ConditionExpression (see session.ts), and when `fields.restart`
|
|
181
|
+
* names an expired anchor it is pinned to that anchor; if — and only if —
|
|
182
|
+
* that condition loses a race against a concurrent caller who just healed or
|
|
183
|
+
* restarted the same session, this retries the identical chunk once with
|
|
184
|
+
* `forceTtlRefresh: false` and no `restart` (safe: `if_not_exists` and `ADD`
|
|
185
|
+
* then converge on whatever already won) rather than losing the message
|
|
186
|
+
* writes to a benign ttl race. A
|
|
155
187
|
* cancellation caused by any other item (a genuine message-row conflict) is
|
|
156
188
|
* not retried here — it propagates for the normal transient-conflict retry
|
|
157
189
|
* budget inside `withDynamoDBRetry` to handle, or to the caller otherwise.
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.appendMessages = appendMessages;
|
|
4
|
+
exports.compensate = compensate;
|
|
5
|
+
exports.appendChunks = appendChunks;
|
|
6
|
+
exports.writeMessageChunk = writeMessageChunk;
|
|
7
|
+
exports.estimateRowBytes = estimateRowBytes;
|
|
8
|
+
exports.chunkBySize = chunkBySize;
|
|
9
|
+
const clock_js_1 = require("../../shared/clock.js");
|
|
10
|
+
const codec_js_1 = require("../../shared/codec/codec.js");
|
|
11
|
+
const offloader_js_1 = require("../../shared/codec/s3/offloader.js");
|
|
12
|
+
const abort_js_1 = require("../../shared/dynamodb/abort.js");
|
|
13
|
+
const batch_write_js_1 = require("../../shared/dynamodb/batch-write.js");
|
|
14
|
+
const cancellation_js_1 = require("../../shared/dynamodb/cancellation.js");
|
|
15
|
+
const idempotent_write_js_1 = require("../../shared/dynamodb/idempotent-write.js");
|
|
16
|
+
const table_schema_js_1 = require("../../shared/dynamodb/table-schema.js");
|
|
17
|
+
const base_error_js_1 = require("../../shared/errors/base-error.js");
|
|
18
|
+
const classify_js_1 = require("../../shared/errors/classify.js");
|
|
19
|
+
const error_code_js_1 = require("../../shared/errors/error-code.js");
|
|
20
|
+
const errors_js_1 = require("../../shared/errors/errors.js");
|
|
21
|
+
const logger_js_1 = require("../../shared/logging/logger.js");
|
|
22
|
+
const truncate_js_1 = require("../../shared/logging/truncate.js");
|
|
23
|
+
const rows_js_1 = require("./rows.js");
|
|
24
|
+
const session_js_1 = require("./session.js");
|
|
25
|
+
const setup_js_1 = require("./setup.js");
|
|
26
|
+
const MAX_MESSAGES_PER_TRANSACTION = 99;
|
|
27
|
+
const MAX_TRANSACTION_BYTES = 3_500_000;
|
|
28
|
+
function keyOfFailedUpload(error) {
|
|
29
|
+
if (!(0, base_error_js_1.hasErrorCode)(error, error_code_js_1.ErrorCode.S3_OFFLOAD_FAILED))
|
|
30
|
+
return [];
|
|
31
|
+
const { operation, key } = error.context;
|
|
32
|
+
return operation === 'upload' && typeof key === 'string' ? [key] : [];
|
|
33
|
+
}
|
|
34
|
+
async function buildMessageRows(context, request) {
|
|
35
|
+
const { sessionId, signal } = request;
|
|
36
|
+
const ttlTimestamp = request.anchor?.ttlTimestamp;
|
|
37
|
+
const messageIds = request.messages.map(() => context.ulid());
|
|
38
|
+
const items = [];
|
|
39
|
+
try {
|
|
40
|
+
for (const [index, message] of request.messages.entries()) {
|
|
41
|
+
items.push(await (0, rows_js_1.buildMessageRow)(context, { sessionId, messageId: messageIds[index], message, ttlTimestamp }, signal));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (context.offloader) {
|
|
46
|
+
await (0, offloader_js_1.cleanUpS3Orphans)(context.offloader, {
|
|
47
|
+
keys: [
|
|
48
|
+
...(0, codec_js_1.collectS3Keys)(items.map((item) => item.message)),
|
|
49
|
+
...keyOfFailedUpload(error),
|
|
50
|
+
],
|
|
51
|
+
operation: 'history.addMessages.encode',
|
|
52
|
+
logger: context.logger,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
return items;
|
|
58
|
+
}
|
|
59
|
+
async function appendMessages(context, request) {
|
|
60
|
+
const items = await buildMessageRows(context, request);
|
|
61
|
+
const chunks = chunkBySize(items, MAX_MESSAGES_PER_TRANSACTION, MAX_TRANSACTION_BYTES);
|
|
62
|
+
await appendChunks(context, {
|
|
63
|
+
sessionId: request.sessionId,
|
|
64
|
+
chunks,
|
|
65
|
+
fields: {
|
|
66
|
+
now: (0, clock_js_1.nowIso)(),
|
|
67
|
+
title: (0, session_js_1.deriveTitle)(request.messages),
|
|
68
|
+
ttlTimestamp: request.anchor?.ttlTimestamp,
|
|
69
|
+
forceTtlRefresh: request.anchor?.refresh,
|
|
70
|
+
restart: request.anchor?.expiredAnchor,
|
|
71
|
+
},
|
|
72
|
+
signal: request.signal,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function reportStep(context, report) {
|
|
76
|
+
(0, logger_js_1.absorbLoggerFailure)(() => report(context.logger));
|
|
77
|
+
}
|
|
78
|
+
async function cleanBatchS3(context, chunks) {
|
|
79
|
+
if (!context.offloader)
|
|
80
|
+
return;
|
|
81
|
+
const descriptors = chunks.flat().map((item) => item.message);
|
|
82
|
+
await (0, offloader_js_1.cleanUpS3Orphans)(context.offloader, {
|
|
83
|
+
keys: (0, codec_js_1.collectS3Keys)(descriptors),
|
|
84
|
+
operation: 'history.addMessages',
|
|
85
|
+
logger: context.logger,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
async function rollbackCommitted(context, append, committed) {
|
|
89
|
+
const { sessionId } = append;
|
|
90
|
+
const { now, title } = append.fields;
|
|
91
|
+
const keys = committed.flatMap((chunk) => chunk.keys);
|
|
92
|
+
const total = committed.reduce((sum, chunk) => sum + chunk.count, 0);
|
|
93
|
+
if (keys.length === 0) {
|
|
94
|
+
await (0, session_js_1.revertSessionCreation)(context, sessionId, { total, createdAt: now, title });
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
await (0, batch_write_js_1.batchWriteAll)(context.client, context.tableName, keys.map((Key) => ({ DeleteRequest: { Key } })), { retry: context.retry });
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
const deleted = error.details
|
|
102
|
+
.succeededCount;
|
|
103
|
+
await (0, session_js_1.revertSessionCount)(context, sessionId, deleted, now);
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
await (0, session_js_1.revertSessionCreation)(context, sessionId, { total, createdAt: now, title });
|
|
107
|
+
}
|
|
108
|
+
async function compensate(context, append, failure) {
|
|
109
|
+
const { sessionId, chunks } = append;
|
|
110
|
+
const { committed, trigger, uncertain, unsettledBecause } = failure;
|
|
111
|
+
if (committed.length > 0) {
|
|
112
|
+
reportStep(context, (logger) => logger.warn('history.addMessages compensating committed chunks after a chunk failed', {
|
|
113
|
+
sessionId,
|
|
114
|
+
committedChunks: committed.length,
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
const firstDead = committed.length + (uncertain ? 1 : 0);
|
|
118
|
+
await cleanBatchS3(context, chunks.slice(firstDead));
|
|
119
|
+
try {
|
|
120
|
+
await rollbackCommitted(context, append, committed);
|
|
121
|
+
}
|
|
122
|
+
catch (rollbackError) {
|
|
123
|
+
reportStep(context, (logger) => logger.error('history.addMessages rollback failed; messageCount may have drifted', {
|
|
124
|
+
sessionId,
|
|
125
|
+
committedChunks: committed.length,
|
|
126
|
+
}));
|
|
127
|
+
throw (0, errors_js_1.compensationFailedError)(trigger, (0, base_error_js_1.toError)(rollbackError));
|
|
128
|
+
}
|
|
129
|
+
await cleanBatchS3(context, chunks.slice(0, committed.length));
|
|
130
|
+
if (!uncertain)
|
|
131
|
+
throw trigger;
|
|
132
|
+
reportStep(context, (logger) => logger.error('history.addMessages could not tell whether a failed chunk committed; messageCount may have drifted', {
|
|
133
|
+
sessionId,
|
|
134
|
+
committedChunks: committed.length,
|
|
135
|
+
reason: (0, truncate_js_1.truncateForLog)((0, base_error_js_1.failureLabel)(unsettledBecause ?? trigger)),
|
|
136
|
+
}));
|
|
137
|
+
if ((0, abort_js_1.isAbortError)(trigger))
|
|
138
|
+
throw trigger;
|
|
139
|
+
throw (0, errors_js_1.unsettledAppendError)(trigger, unsettledBecause ?? trigger);
|
|
140
|
+
}
|
|
141
|
+
function chunkProbe(chunk) {
|
|
142
|
+
return {
|
|
143
|
+
key: (0, table_schema_js_1.rowKeyOf)(chunk[0]),
|
|
144
|
+
kind: 'attribute',
|
|
145
|
+
attribute: table_schema_js_1.SORT_KEY_ATTRIBUTE,
|
|
146
|
+
expected: chunk[0].SK,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
async function settleFailedChunk(context, chunk, failure) {
|
|
150
|
+
const answeredRefusal = !(0, abort_js_1.isAbortError)(failure) && !(0, errors_js_1.retryBudgetMayStillLand)(failure) && (0, classify_js_1.refusedByService)(failure);
|
|
151
|
+
if (answeredRefusal)
|
|
152
|
+
return { verdict: 'not-landed' };
|
|
153
|
+
const probe = chunkProbe(chunk);
|
|
154
|
+
let row;
|
|
155
|
+
try {
|
|
156
|
+
row = await (0, idempotent_write_js_1.readRow)(context, probe);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
return { verdict: 'unverified', unsettledBecause: (0, base_error_js_1.toError)(error) };
|
|
160
|
+
}
|
|
161
|
+
const verdict = (0, idempotent_write_js_1.settledVerdict)((0, idempotent_write_js_1.verdictFor)(probe, row), failure);
|
|
162
|
+
return verdict === 'unverified' ? { verdict, unsettledBecause: failure } : { verdict };
|
|
163
|
+
}
|
|
164
|
+
async function commitChunk(context, append, chunk, position) {
|
|
165
|
+
const fields = { ...append.fields, sessionId: append.sessionId, count: chunk.length };
|
|
166
|
+
try {
|
|
167
|
+
await writeMessageChunk(context, chunk, position === 0 ? fields : { ...fields, restart: undefined }, { signal: append.signal });
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
return (0, base_error_js_1.toError)(error);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function asCommitted(chunk) {
|
|
175
|
+
return { keys: chunk.map((item) => (0, table_schema_js_1.rowKeyOf)(item)), count: chunk.length };
|
|
176
|
+
}
|
|
177
|
+
async function appendChunks(context, append) {
|
|
178
|
+
const committed = [];
|
|
179
|
+
for (const [position, chunk] of append.chunks.entries()) {
|
|
180
|
+
if (append.signal?.aborted) {
|
|
181
|
+
await compensate(context, append, {
|
|
182
|
+
committed,
|
|
183
|
+
trigger: (0, abort_js_1.abortErrorFrom)(append.signal),
|
|
184
|
+
uncertain: false,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
const failure = await commitChunk(context, append, chunk, position);
|
|
188
|
+
if (!failure) {
|
|
189
|
+
committed.push(asCommitted(chunk));
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
const settled = await settleFailedChunk(context, chunk, failure);
|
|
193
|
+
if (settled.verdict === 'landed')
|
|
194
|
+
committed.push(asCommitted(chunk));
|
|
195
|
+
if (settled.verdict === 'landed' && !(0, abort_js_1.isAbortError)(failure))
|
|
196
|
+
continue;
|
|
197
|
+
await compensate(context, append, {
|
|
198
|
+
committed,
|
|
199
|
+
trigger: failure,
|
|
200
|
+
uncertain: settled.verdict === 'unverified',
|
|
201
|
+
unsettledBecause: settled.unsettledBecause,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function isTtlConditionLoss(error) {
|
|
206
|
+
return (0, cancellation_js_1.conditionFailedAt)(error, 0) && (0, cancellation_js_1.conditionalCheckFailure)(error) !== undefined;
|
|
207
|
+
}
|
|
208
|
+
async function attempt(context, items, fields, retry) {
|
|
209
|
+
await (0, idempotent_write_js_1.transactIdempotently)(context, [
|
|
210
|
+
(0, session_js_1.buildSessionUpdate)(context.tableName, fields),
|
|
211
|
+
...items.map((item) => ({ Put: { TableName: context.tableName, Item: item } })),
|
|
212
|
+
], { signal: retry.signal, rng: retry.rng, minAttempts: setup_js_1.MESSAGE_APPEND_RETRY_MAX_ATTEMPTS });
|
|
213
|
+
}
|
|
214
|
+
async function writeMessageChunk(context, items, fields, retry = {}) {
|
|
215
|
+
const withIndex = { ...fields, indexShards: context.indexShards, writeId: context.ulid() };
|
|
216
|
+
try {
|
|
217
|
+
await attempt(context, items, withIndex, retry);
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
const pinned = fields.forceTtlRefresh || fields.restart !== undefined;
|
|
221
|
+
if (pinned && isTtlConditionLoss(error)) {
|
|
222
|
+
await attempt(context, items, { ...withIndex, forceTtlRefresh: false, restart: undefined }, retry);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const ROW_OVERHEAD_BYTES = 256;
|
|
229
|
+
function utf8Bytes(value) {
|
|
230
|
+
return Buffer.byteLength(value, 'utf8');
|
|
231
|
+
}
|
|
232
|
+
function descriptorBytes(descriptor) {
|
|
233
|
+
const body = descriptor.location === codec_js_1.PayloadLocation.INLINE
|
|
234
|
+
? descriptor.bytes.length
|
|
235
|
+
: utf8Bytes(descriptor.s3Key);
|
|
236
|
+
return body + utf8Bytes(descriptor.serdeType);
|
|
237
|
+
}
|
|
238
|
+
function estimateRowBytes(item) {
|
|
239
|
+
return (utf8Bytes(item.PK) +
|
|
240
|
+
utf8Bytes(item.SK) +
|
|
241
|
+
utf8Bytes(item.sessionId) +
|
|
242
|
+
descriptorBytes(item.message) +
|
|
243
|
+
ROW_OVERHEAD_BYTES);
|
|
244
|
+
}
|
|
245
|
+
function shouldFlush(chunk, next, limits) {
|
|
246
|
+
if (chunk.count === 0)
|
|
247
|
+
return false;
|
|
248
|
+
return chunk.count >= limits.maxItems || chunk.bytes + next > limits.maxBytes;
|
|
249
|
+
}
|
|
250
|
+
function chunkBySize(items, maxItems, maxBytes) {
|
|
251
|
+
const chunks = [];
|
|
252
|
+
let current = [];
|
|
253
|
+
let currentBytes = 0;
|
|
254
|
+
for (const item of items) {
|
|
255
|
+
const size = estimateRowBytes(item);
|
|
256
|
+
if (shouldFlush({ count: current.length, bytes: currentBytes }, size, { maxItems, maxBytes })) {
|
|
257
|
+
chunks.push(current);
|
|
258
|
+
current = [];
|
|
259
|
+
currentBytes = 0;
|
|
260
|
+
}
|
|
261
|
+
current.push(item);
|
|
262
|
+
currentBytes += size;
|
|
263
|
+
}
|
|
264
|
+
if (current.length > 0)
|
|
265
|
+
chunks.push(current);
|
|
266
|
+
return chunks;
|
|
267
|
+
}
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* rows the same way it reads them, so a repaired count is the number a read
|
|
9
9
|
* returns.
|
|
10
10
|
*/
|
|
11
|
-
import type { ParsedWindow, SessionId } from './parse';
|
|
12
|
-
import { type MessageRow } from './rows';
|
|
13
|
-
import type { HistoryContext } from './setup';
|
|
11
|
+
import type { ParsedWindow, SessionId } from './parse.js';
|
|
12
|
+
import { type MessageRow } from './rows.js';
|
|
13
|
+
import type { HistoryContext } from './setup.js';
|
|
14
14
|
/**
|
|
15
15
|
* Read the live message items a window selects, in chronological order.
|
|
16
16
|
*
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readWindow = readWindow;
|
|
4
|
+
exports.countLiveMessages = countLiveMessages;
|
|
5
|
+
const clock_js_1 = require("../../shared/clock.js");
|
|
6
|
+
const paginate_js_1 = require("../../shared/dynamodb/paginate.js");
|
|
7
|
+
const retry_js_1 = require("../../shared/dynamodb/retry.js");
|
|
8
|
+
const table_schema_js_1 = require("../../shared/dynamodb/table-schema.js");
|
|
9
|
+
const errors_js_1 = require("../../shared/errors/errors.js");
|
|
10
|
+
const truncate_js_1 = require("../../shared/logging/truncate.js");
|
|
11
|
+
const ulid_js_1 = require("../../shared/ulid.js");
|
|
12
|
+
const rows_js_1 = require("./rows.js");
|
|
13
|
+
function parseSessionMessageRow(context, sessionId, raw) {
|
|
14
|
+
(0, table_schema_js_1.assertReadableRow)(raw, 'message');
|
|
15
|
+
const item = (0, rows_js_1.parseMessageRow)(raw);
|
|
16
|
+
if (item)
|
|
17
|
+
return item;
|
|
18
|
+
context.logger.warn('getMessages: refused a row that is not a chat message item', {
|
|
19
|
+
sessionId,
|
|
20
|
+
sortKey: (0, truncate_js_1.truncateForLog)(raw.SK),
|
|
21
|
+
});
|
|
22
|
+
throw (0, errors_js_1.validationError)('a row in the message key space of this session is not a chat message item this package ' +
|
|
23
|
+
'wrote: its `sessionId` or `message` attribute is absent, is of the wrong type, or names ' +
|
|
24
|
+
'another session. The `warn` logged alongside this names the row', 'message');
|
|
25
|
+
}
|
|
26
|
+
async function readWindow(context, sessionId, window, signal) {
|
|
27
|
+
const now = (0, clock_js_1.nowSeconds)();
|
|
28
|
+
const limit = window.limit ?? Number.POSITIVE_INFINITY;
|
|
29
|
+
const items = [];
|
|
30
|
+
for await (const raw of (0, paginate_js_1.paginateQuery)({
|
|
31
|
+
retry: (0, retry_js_1.retryFor)(context, signal),
|
|
32
|
+
signal,
|
|
33
|
+
client: context.client,
|
|
34
|
+
params: (0, rows_js_1.messageQuery)(context.tableName, sessionId, {
|
|
35
|
+
consistent: true,
|
|
36
|
+
descending: window.limit !== undefined,
|
|
37
|
+
limit: window.limit,
|
|
38
|
+
beforeSortKey: window.before && (0, rows_js_1.messageSortKey)((0, ulid_js_1.ulidTimePrefix)(window.before.getTime())),
|
|
39
|
+
}),
|
|
40
|
+
maxItems: Number.POSITIVE_INFINITY,
|
|
41
|
+
maxIterations: Number.POSITIVE_INFINITY,
|
|
42
|
+
})) {
|
|
43
|
+
const item = parseSessionMessageRow(context, sessionId, raw);
|
|
44
|
+
if ((0, table_schema_js_1.isExpiredRow)(item, now))
|
|
45
|
+
continue;
|
|
46
|
+
items.push(item);
|
|
47
|
+
if (items.length >= limit)
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
if (items.length >= paginate_js_1.LIST_SCAN_WARN_THRESHOLD) {
|
|
51
|
+
context.logger.warn('getMessages: a session holds very many messages; the read is complete but slow. Pass a ' +
|
|
52
|
+
'`limit` to read only the newest turns', { sessionId, messages: items.length });
|
|
53
|
+
}
|
|
54
|
+
return window.limit === undefined ? items : items.reverse();
|
|
55
|
+
}
|
|
56
|
+
function parseCountableRow(raw, sessionId) {
|
|
57
|
+
(0, table_schema_js_1.assertReadableRow)(raw, 'message');
|
|
58
|
+
const item = (0, rows_js_1.parseMessageRow)(raw);
|
|
59
|
+
if (item)
|
|
60
|
+
return item;
|
|
61
|
+
throw (0, errors_js_1.validationError)(`session "${sessionId}" holds a row in its message key space that is not a chat message ` +
|
|
62
|
+
'item this package wrote, so its messages cannot be counted: a read of the session ' +
|
|
63
|
+
'reports the same row and names it. Remove or repair the row, then reconcile again', 'message');
|
|
64
|
+
}
|
|
65
|
+
async function countLiveMessages(context, sessionId, signal) {
|
|
66
|
+
const now = (0, clock_js_1.nowSeconds)();
|
|
67
|
+
const query = (0, rows_js_1.messageQuery)(context.tableName, sessionId, { consistent: true });
|
|
68
|
+
let total = 0;
|
|
69
|
+
for await (const raw of (0, paginate_js_1.paginateQuery)({
|
|
70
|
+
retry: (0, retry_js_1.retryFor)(context, signal),
|
|
71
|
+
signal,
|
|
72
|
+
client: context.client,
|
|
73
|
+
params: {
|
|
74
|
+
...query,
|
|
75
|
+
ProjectionExpression: '#pk, #sid, #msg.#loc, #v, #ttl',
|
|
76
|
+
ExpressionAttributeNames: {
|
|
77
|
+
...query.ExpressionAttributeNames,
|
|
78
|
+
'#sid': 'sessionId',
|
|
79
|
+
'#msg': 'message',
|
|
80
|
+
'#loc': 'location',
|
|
81
|
+
'#v': 'v',
|
|
82
|
+
'#ttl': 'ttl',
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
maxItems: Number.POSITIVE_INFINITY,
|
|
86
|
+
maxIterations: Number.POSITIVE_INFINITY,
|
|
87
|
+
})) {
|
|
88
|
+
const row = parseCountableRow(raw, sessionId);
|
|
89
|
+
if (!(0, table_schema_js_1.isExpiredRow)(row, now))
|
|
90
|
+
total += 1;
|
|
91
|
+
}
|
|
92
|
+
return total;
|
|
93
|
+
}
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* range a message id can express.
|
|
10
10
|
*/
|
|
11
11
|
import { type BaseMessage, type StoredMessage } from '@langchain/core/messages';
|
|
12
|
-
import { type PageLimit } from '../../shared/validation/primitives';
|
|
13
|
-
import type { GetMessagesOptions, ListSessionsOptions, MessageWindow } from '../types';
|
|
12
|
+
import { type PageLimit } from '../../shared/validation/primitives.js';
|
|
13
|
+
import type { GetMessagesOptions, ListSessionsOptions, MessageWindow } from '../types.js';
|
|
14
14
|
declare const sessionIdBrand: unique symbol;
|
|
15
15
|
declare const storableMessagesBrand: unique symbol;
|
|
16
16
|
declare const parsedWindowBrand: unique symbol;
|