@farukada/aws-langgraph-dynamodb-ts 1.0.0-rc.1 → 1.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1621 -288
- package/dist/backfill/backfill.d.ts +168 -0
- package/dist/backfill/backfill.js +393 -0
- package/dist/checkpointer/actions/delete-thread.d.ts +44 -4
- package/dist/checkpointer/actions/delete-thread.js +56 -22
- package/dist/checkpointer/actions/get-tuple.d.ts +29 -5
- package/dist/checkpointer/actions/get-tuple.js +41 -13
- package/dist/checkpointer/actions/list.d.ts +42 -10
- package/dist/checkpointer/actions/list.js +86 -57
- package/dist/checkpointer/actions/put-writes.d.ts +41 -9
- package/dist/checkpointer/actions/put-writes.js +62 -48
- package/dist/checkpointer/actions/put.d.ts +82 -10
- package/dist/checkpointer/actions/put.js +166 -44
- package/dist/checkpointer/internal/delta-history.d.ts +112 -0
- package/dist/checkpointer/internal/delta-history.js +252 -0
- package/dist/checkpointer/internal/listing.d.ts +149 -0
- package/dist/checkpointer/internal/listing.js +245 -0
- package/dist/checkpointer/internal/parse.d.ts +262 -0
- package/dist/checkpointer/internal/parse.js +372 -0
- package/dist/checkpointer/internal/pending-writes.d.ts +275 -0
- package/dist/checkpointer/internal/pending-writes.js +588 -0
- package/dist/checkpointer/internal/read.d.ts +130 -0
- package/dist/checkpointer/internal/read.js +264 -0
- package/dist/checkpointer/internal/rows.d.ts +571 -0
- package/dist/checkpointer/internal/rows.js +834 -0
- package/dist/checkpointer/internal/setup.d.ts +42 -21
- package/dist/checkpointer/internal/setup.js +65 -31
- package/dist/checkpointer/saver.d.ts +242 -42
- package/dist/checkpointer/saver.js +257 -53
- package/dist/checkpointer/types.d.ts +37 -44
- package/dist/checkpointer/types.js +10 -0
- package/dist/factory/factory.d.ts +120 -11
- package/dist/factory/factory.js +195 -16
- package/dist/factory/types.d.ts +23 -4
- package/dist/factory/types.js +8 -0
- package/dist/history/actions/add-messages.d.ts +30 -2
- package/dist/history/actions/add-messages.js +37 -57
- package/dist/history/actions/clear.d.ts +46 -4
- package/dist/history/actions/clear.js +64 -15
- package/dist/history/actions/get-messages.d.ts +41 -0
- package/dist/history/actions/get-messages.js +94 -32
- package/dist/history/actions/list-sessions.d.ts +52 -10
- package/dist/history/actions/list-sessions.js +141 -38
- package/dist/history/actions/reconcile-count.d.ts +41 -8
- package/dist/history/actions/reconcile-count.js +44 -57
- package/dist/history/chat-message-history.d.ts +200 -38
- package/dist/history/chat-message-history.js +218 -51
- package/dist/history/internal/append.d.ts +212 -0
- package/dist/history/internal/append.js +500 -0
- package/dist/history/internal/message-read.d.ts +84 -0
- package/dist/history/internal/message-read.js +204 -0
- package/dist/history/internal/parse.d.ts +153 -0
- package/dist/history/internal/parse.js +252 -0
- package/dist/history/internal/rows.d.ts +195 -0
- package/dist/history/internal/rows.js +250 -0
- package/dist/history/internal/session.d.ts +331 -0
- package/dist/history/internal/session.js +628 -0
- package/dist/history/internal/setup.d.ts +52 -19
- package/dist/history/internal/setup.js +90 -27
- package/dist/history/session-adapter.d.ts +95 -6
- package/dist/history/session-adapter.js +99 -8
- package/dist/history/types.d.ts +61 -31
- package/dist/history/types.js +10 -0
- package/dist/index.d.ts +38 -14
- package/dist/index.js +31 -12
- package/dist/shared/adapter.d.ts +135 -0
- package/dist/shared/adapter.js +143 -0
- package/dist/shared/clock.d.ts +48 -4
- package/dist/shared/clock.js +51 -4
- package/dist/shared/codec/codec.d.ts +275 -9
- package/dist/shared/codec/codec.js +394 -19
- package/dist/shared/codec/compression.d.ts +43 -6
- package/dist/shared/codec/compression.js +52 -11
- package/dist/shared/codec/json-serde.d.ts +76 -3
- package/dist/shared/codec/json-serde.js +181 -7
- package/dist/shared/codec/s3/client-types.d.ts +20 -1
- package/dist/shared/codec/s3/client-types.js +20 -1
- package/dist/shared/codec/s3/client.d.ts +35 -8
- package/dist/shared/codec/s3/client.js +61 -10
- package/dist/shared/codec/s3/config.d.ts +226 -22
- package/dist/shared/codec/s3/config.js +274 -24
- package/dist/shared/codec/s3/lifecycle.d.ts +163 -11
- package/dist/shared/codec/s3/lifecycle.js +328 -36
- package/dist/shared/codec/s3/offloader.d.ts +390 -19
- package/dist/shared/codec/s3/offloader.js +590 -50
- package/dist/shared/concurrency.d.ts +40 -3
- package/dist/shared/concurrency.js +55 -7
- package/dist/shared/dynamodb/abort.d.ts +45 -7
- package/dist/shared/dynamodb/abort.js +46 -14
- package/dist/shared/dynamodb/batch-write.d.ts +77 -13
- package/dist/shared/dynamodb/batch-write.js +146 -26
- package/dist/shared/dynamodb/cancellation.d.ts +121 -3
- package/dist/shared/dynamodb/cancellation.js +147 -2
- package/dist/shared/dynamodb/client.d.ts +159 -12
- package/dist/shared/dynamodb/client.js +135 -10
- package/dist/shared/dynamodb/idempotent-write.d.ts +551 -0
- package/dist/shared/dynamodb/idempotent-write.js +593 -0
- package/dist/shared/dynamodb/paginate.d.ts +105 -8
- package/dist/shared/dynamodb/paginate.js +175 -6
- package/dist/shared/dynamodb/partition-delete.d.ts +181 -16
- package/dist/shared/dynamodb/partition-delete.js +312 -43
- package/dist/shared/dynamodb/recency-index.d.ts +231 -0
- package/dist/shared/dynamodb/recency-index.js +377 -0
- package/dist/shared/dynamodb/retry.d.ts +265 -10
- package/dist/shared/dynamodb/retry.js +426 -20
- package/dist/shared/dynamodb/table-schema.d.ts +190 -0
- package/dist/shared/dynamodb/table-schema.js +209 -0
- package/dist/shared/errors/base-error.d.ts +174 -8
- package/dist/shared/errors/base-error.js +154 -7
- package/dist/shared/errors/boundary.d.ts +63 -10
- package/dist/shared/errors/boundary.js +110 -13
- package/dist/shared/errors/classify.d.ts +97 -0
- package/dist/shared/errors/classify.js +257 -0
- package/dist/shared/errors/error-code.d.ts +76 -1
- package/dist/shared/errors/error-code.js +83 -1
- package/dist/shared/errors/errors.d.ts +157 -58
- package/dist/shared/errors/errors.js +218 -93
- package/dist/shared/logging/logger.d.ts +63 -1
- package/dist/shared/logging/logger.js +97 -2
- package/dist/shared/logging/redaction.d.ts +86 -6
- package/dist/shared/logging/redaction.js +265 -24
- package/dist/shared/logging/secret-patterns.d.ts +136 -24
- package/dist/shared/logging/secret-patterns.js +165 -30
- package/dist/shared/logging/truncate.d.ts +197 -0
- package/dist/shared/logging/truncate.js +231 -0
- package/dist/shared/options.d.ts +52 -5
- package/dist/shared/options.js +9 -0
- package/dist/shared/ulid.d.ts +71 -14
- package/dist/shared/ulid.js +77 -14
- package/dist/shared/validation/collaborators.d.ts +141 -0
- package/dist/shared/validation/collaborators.js +188 -0
- package/dist/shared/validation/option-shape.d.ts +89 -0
- package/dist/shared/validation/option-shape.js +113 -0
- package/dist/shared/validation/options.d.ts +142 -5
- package/dist/shared/validation/options.js +284 -46
- package/dist/shared/validation/primitives.d.ts +287 -24
- package/dist/shared/validation/primitives.js +347 -42
- package/dist/shared/validation/ttl.d.ts +61 -12
- package/dist/shared/validation/ttl.js +102 -22
- package/dist/store/actions/list-namespaces.d.ts +76 -5
- package/dist/store/actions/list-namespaces.js +160 -22
- package/dist/store/actions/put.d.ts +33 -7
- package/dist/store/actions/put.js +53 -71
- package/dist/store/actions/reconcile-vector-index.d.ts +28 -8
- package/dist/store/actions/reconcile-vector-index.js +33 -13
- package/dist/store/actions/search.d.ts +34 -5
- package/dist/store/actions/search.js +52 -20
- package/dist/store/internal/batch-plan.d.ts +24 -9
- package/dist/store/internal/batch-plan.js +91 -34
- package/dist/store/internal/filter.d.ts +36 -2
- package/dist/store/internal/filter.js +66 -14
- package/dist/store/internal/get-item.d.ts +45 -0
- package/dist/store/internal/get-item.js +115 -0
- package/dist/store/internal/item-write.d.ts +230 -0
- package/dist/store/internal/item-write.js +463 -0
- package/dist/store/internal/parse.d.ts +225 -0
- package/dist/store/internal/parse.js +350 -0
- package/dist/store/internal/rows.d.ts +355 -0
- package/dist/store/internal/rows.js +447 -0
- package/dist/store/internal/semantic-search.d.ts +146 -12
- package/dist/store/internal/semantic-search.js +317 -15
- package/dist/store/internal/setup.d.ts +86 -21
- package/dist/store/internal/setup.js +209 -26
- package/dist/store/internal/table-search.d.ts +100 -0
- package/dist/store/internal/table-search.js +213 -0
- package/dist/store/internal/vector-index.d.ts +247 -0
- package/dist/store/internal/vector-index.js +546 -0
- package/dist/store/store.d.ts +258 -33
- package/dist/store/store.js +309 -53
- package/dist/store/types.d.ts +74 -28
- package/dist/store/types.js +13 -0
- package/dist/store/vector-backend.d.ts +64 -3
- package/dist/store/vector-backend.js +15 -0
- package/package.json +41 -25
- package/dist/checkpointer/internal/assemble.d.ts +0 -17
- package/dist/checkpointer/internal/assemble.js +0 -38
- package/dist/checkpointer/internal/checkpoint-write-verify.d.ts +0 -24
- package/dist/checkpointer/internal/checkpoint-write-verify.js +0 -67
- package/dist/checkpointer/internal/configurable.d.ts +0 -12
- package/dist/checkpointer/internal/configurable.js +0 -24
- package/dist/checkpointer/internal/fetch.d.ts +0 -19
- package/dist/checkpointer/internal/fetch.js +0 -88
- package/dist/checkpointer/internal/filter-match.d.ts +0 -13
- package/dist/checkpointer/internal/filter-match.js +0 -15
- package/dist/checkpointer/internal/item-reader.d.ts +0 -66
- package/dist/checkpointer/internal/item-reader.js +0 -113
- package/dist/checkpointer/internal/item-writer.d.ts +0 -35
- package/dist/checkpointer/internal/item-writer.js +0 -107
- package/dist/checkpointer/internal/keys.d.ts +0 -41
- package/dist/checkpointer/internal/keys.js +0 -117
- package/dist/checkpointer/internal/list-scope.d.ts +0 -61
- package/dist/checkpointer/internal/list-scope.js +0 -108
- package/dist/checkpointer/internal/pending-sends.d.ts +0 -13
- package/dist/checkpointer/internal/pending-sends.js +0 -29
- package/dist/checkpointer/internal/query.d.ts +0 -21
- package/dist/checkpointer/internal/query.js +0 -42
- package/dist/checkpointer/internal/regular-write.d.ts +0 -28
- package/dist/checkpointer/internal/regular-write.js +0 -66
- package/dist/checkpointer/internal/special-write-cas.d.ts +0 -29
- package/dist/checkpointer/internal/special-write-cas.js +0 -104
- package/dist/checkpointer/internal/special-write-cleanup.d.ts +0 -23
- package/dist/checkpointer/internal/special-write-cleanup.js +0 -50
- package/dist/checkpointer/internal/special-write-verify.d.ts +0 -53
- package/dist/checkpointer/internal/special-write-verify.js +0 -80
- package/dist/checkpointer/internal/stored-channels.d.ts +0 -31
- package/dist/checkpointer/internal/stored-channels.js +0 -70
- package/dist/checkpointer/internal/validation.d.ts +0 -18
- package/dist/checkpointer/internal/validation.js +0 -40
- package/dist/checkpointer/internal/write-guard.d.ts +0 -20
- package/dist/checkpointer/internal/write-guard.js +0 -48
- package/dist/checkpointer/internal/write-index.d.ts +0 -36
- package/dist/checkpointer/internal/write-index.js +0 -41
- package/dist/history/internal/append-saga.d.ts +0 -25
- package/dist/history/internal/append-saga.js +0 -79
- package/dist/history/internal/compensation.d.ts +0 -25
- package/dist/history/internal/compensation.js +0 -92
- package/dist/history/internal/item-mapper.d.ts +0 -9
- package/dist/history/internal/item-mapper.js +0 -27
- package/dist/history/internal/keys.d.ts +0 -16
- package/dist/history/internal/keys.js +0 -48
- package/dist/history/internal/message-chunker.d.ts +0 -13
- package/dist/history/internal/message-chunker.js +0 -67
- package/dist/history/internal/message-transaction.d.ts +0 -25
- package/dist/history/internal/message-transaction.js +0 -61
- package/dist/history/internal/message-window.d.ts +0 -17
- package/dist/history/internal/message-window.js +0 -49
- package/dist/history/internal/query.d.ts +0 -23
- package/dist/history/internal/query.js +0 -39
- package/dist/history/internal/session-count.d.ts +0 -47
- package/dist/history/internal/session-count.js +0 -115
- package/dist/history/internal/session-title.d.ts +0 -19
- package/dist/history/internal/session-title.js +0 -43
- package/dist/history/internal/session-update.d.ts +0 -27
- package/dist/history/internal/session-update.js +0 -69
- package/dist/history/internal/title-generator.d.ts +0 -12
- package/dist/history/internal/title-generator.js +0 -41
- package/dist/history/internal/ttl-anchor.d.ts +0 -24
- package/dist/history/internal/ttl-anchor.js +0 -38
- package/dist/history/internal/validation.d.ts +0 -25
- package/dist/history/internal/validation.js +0 -53
- package/dist/shared/codec/descriptor-keys.d.ts +0 -12
- package/dist/shared/codec/descriptor-keys.js +0 -14
- package/dist/shared/codec/encode.d.ts +0 -13
- package/dist/shared/codec/encode.js +0 -43
- package/dist/shared/codec/payload-loss.d.ts +0 -12
- package/dist/shared/codec/payload-loss.js +0 -38
- package/dist/shared/codec/s3/adapter-config.d.ts +0 -13
- package/dist/shared/codec/s3/adapter-config.js +0 -22
- package/dist/shared/codec/s3/bounded-body.d.ts +0 -14
- package/dist/shared/codec/s3/bounded-body.js +0 -47
- package/dist/shared/codec/s3/delete.d.ts +0 -7
- package/dist/shared/codec/s3/delete.js +0 -28
- package/dist/shared/codec/s3/key-scope.d.ts +0 -23
- package/dist/shared/codec/s3/key-scope.js +0 -44
- package/dist/shared/codec/s3/orphans.d.ts +0 -23
- package/dist/shared/codec/s3/orphans.js +0 -71
- package/dist/shared/codec/s3/read-write.d.ts +0 -18
- package/dist/shared/codec/s3/read-write.js +0 -51
- package/dist/shared/codec/s3/retry.d.ts +0 -5
- package/dist/shared/codec/s3/retry.js +0 -22
- package/dist/shared/constants.d.ts +0 -112
- package/dist/shared/constants.js +0 -115
- package/dist/shared/dynamodb/backoff.d.ts +0 -15
- package/dist/shared/dynamodb/backoff.js +0 -48
- package/dist/shared/dynamodb/conditional-put.d.ts +0 -67
- package/dist/shared/dynamodb/conditional-put.js +0 -76
- package/dist/shared/dynamodb/drain-unprocessed.d.ts +0 -21
- package/dist/shared/dynamodb/drain-unprocessed.js +0 -43
- package/dist/shared/dynamodb/expiry.d.ts +0 -16
- package/dist/shared/dynamodb/expiry.js +0 -29
- package/dist/shared/dynamodb/paginate-core.d.ts +0 -24
- package/dist/shared/dynamodb/paginate-core.js +0 -82
- package/dist/shared/dynamodb/retry-classifier.d.ts +0 -17
- package/dist/shared/dynamodb/retry-classifier.js +0 -118
- package/dist/shared/dynamodb/retry-policy.d.ts +0 -26
- package/dist/shared/dynamodb/retry-policy.js +0 -22
- package/dist/shared/dynamodb/scan.d.ts +0 -14
- package/dist/shared/dynamodb/scan.js +0 -19
- package/dist/shared/dynamodb/types.d.ts +0 -23
- package/dist/shared/dynamodb/types.js +0 -2
- package/dist/shared/errors/upstream-error.d.ts +0 -16
- package/dist/shared/errors/upstream-error.js +0 -27
- package/dist/shared/errors/wrap-error.d.ts +0 -7
- package/dist/shared/errors/wrap-error.js +0 -15
- package/dist/shared/logging/redaction-walk.d.ts +0 -23
- package/dist/shared/logging/redaction-walk.js +0 -112
- package/dist/store/actions/get.d.ts +0 -13
- package/dist/store/actions/get.js +0 -73
- package/dist/store/internal/backend-search.d.ts +0 -4
- package/dist/store/internal/backend-search.js +0 -74
- package/dist/store/internal/candidates.d.ts +0 -23
- package/dist/store/internal/candidates.js +0 -94
- package/dist/store/internal/index-reconcile.d.ts +0 -21
- package/dist/store/internal/index-reconcile.js +0 -118
- package/dist/store/internal/index-sync.d.ts +0 -10
- package/dist/store/internal/index-sync.js +0 -25
- package/dist/store/internal/item-mapper.d.ts +0 -27
- package/dist/store/internal/item-mapper.js +0 -61
- package/dist/store/internal/keys.d.ts +0 -17
- package/dist/store/internal/keys.js +0 -41
- package/dist/store/internal/namespace-match.d.ts +0 -11
- package/dist/store/internal/namespace-match.js +0 -40
- package/dist/store/internal/option-validation.d.ts +0 -13
- package/dist/store/internal/option-validation.js +0 -77
- package/dist/store/internal/overwrite-swap.d.ts +0 -32
- package/dist/store/internal/overwrite-swap.js +0 -68
- package/dist/store/internal/persist.d.ts +0 -28
- package/dist/store/internal/persist.js +0 -64
- package/dist/store/internal/query.d.ts +0 -11
- package/dist/store/internal/query.js +0 -48
- package/dist/store/internal/ranker.d.ts +0 -18
- package/dist/store/internal/ranker.js +0 -39
- package/dist/store/internal/read-existing.d.ts +0 -23
- package/dist/store/internal/read-existing.js +0 -41
- package/dist/store/internal/score-direction.d.ts +0 -31
- package/dist/store/internal/score-direction.js +0 -38
- package/dist/store/internal/search-filter.d.ts +0 -3
- package/dist/store/internal/search-filter.js +0 -10
- package/dist/store/internal/text-path.d.ts +0 -17
- package/dist/store/internal/text-path.js +0 -147
- package/dist/store/internal/validation.d.ts +0 -18
- package/dist/store/internal/validation.js +0 -51
- package/dist/store/internal/write-verify.d.ts +0 -42
- package/dist/store/internal/write-verify.js +0 -71
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.putWithRevisionSwap = putWithRevisionSwap;
|
|
4
|
-
const conditional_put_1 = require("../../shared/dynamodb/conditional-put");
|
|
5
|
-
const retry_1 = require("../../shared/dynamodb/retry");
|
|
6
|
-
const read_existing_1 = require("./read-existing");
|
|
7
|
-
/** Put the record, optionally pinned to the revision the caller observed. */
|
|
8
|
-
async function put(context, record, observed) {
|
|
9
|
-
const guard = observed ? (0, conditional_put_1.revisionGuard)(conditional_put_1.REVISION_ATTRIBUTE, observed) : {};
|
|
10
|
-
await (0, retry_1.withDynamoDBRetry)(() => context.client.put({ TableName: context.tableName, Item: record, ...guard }), context.retry);
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Commit `record`, re-reading and retrying while another writer holds the row,
|
|
14
|
-
* and return the state this write actually superseded — the only descriptor
|
|
15
|
-
* safe to delete afterwards.
|
|
16
|
-
*
|
|
17
|
-
* Without the swap both racers read the same previous descriptor, both commit,
|
|
18
|
-
* and both delete it, orphaning the loser's own upload. Retrying against the
|
|
19
|
-
* *re-read* state is what makes each writer supersede exactly one payload.
|
|
20
|
-
*
|
|
21
|
-
* A rejection is not proof a competitor won: `withDynamoDBRetry` retries
|
|
22
|
-
* transient errors, so an attempt can commit server-side, its response can be
|
|
23
|
-
* lost, and the retried put can hit the row it just wrote and fail the same
|
|
24
|
-
* guard — indistinguishable from a competitor's win by the rejection alone.
|
|
25
|
-
* Each attempt's pinned observation is captured in `attempted` before the
|
|
26
|
-
* put, so that when a re-read finds the row already holding *this call's
|
|
27
|
-
* own* `rev`, the swap returns whatever `attempted` held — never this
|
|
28
|
-
* record's own just-committed value, which would strand the live row
|
|
29
|
-
* pointing at a deleted object. That comparison is guarded on `rev` being
|
|
30
|
-
* set: `rev` is optional on the record type, and an unnonced record against a
|
|
31
|
-
* pre-0.9.0 revision-less row would otherwise match `undefined === undefined`
|
|
32
|
-
* and claim a race it never entered.
|
|
33
|
-
*
|
|
34
|
-
* On exhaustion the write proceeds unconditionally and warns. That is
|
|
35
|
-
* deliberate: the fallback is precisely the pre-0.9.0 behaviour — one possible
|
|
36
|
-
* orphan, reclaimed by a lifecycle rule — so pathological contention degrades
|
|
37
|
-
* instead of turning a working put into an error. `createdAt` is refreshed from
|
|
38
|
-
* each re-read so a row created by whoever won keeps its true creation time.
|
|
39
|
-
*/
|
|
40
|
-
async function putWithRevisionSwap(context, record, existing) {
|
|
41
|
-
let observed = existing;
|
|
42
|
-
for (let attempt = 1; attempt <= conditional_put_1.OVERWRITE_CAS_MAX_ATTEMPTS; attempt++) {
|
|
43
|
-
const attempted = observed;
|
|
44
|
-
try {
|
|
45
|
-
await put(context, record, attempted);
|
|
46
|
-
return attempted;
|
|
47
|
-
}
|
|
48
|
-
catch (error) {
|
|
49
|
-
if (!(0, conditional_put_1.isConditionalCheckFailed)(error))
|
|
50
|
-
throw error;
|
|
51
|
-
/** The rejection carries the row that turned it away; the read is spent only when it does not. */
|
|
52
|
-
const rejected = (0, conditional_put_1.rejectedItem)(error);
|
|
53
|
-
observed = rejected
|
|
54
|
-
? (0, read_existing_1.existingFrom)(rejected)
|
|
55
|
-
: await (0, read_existing_1.readExisting)(context, record.PK, record.SK);
|
|
56
|
-
if (record.rev !== undefined && observed.revision === record.rev)
|
|
57
|
-
return attempted;
|
|
58
|
-
/** A row that vanished between attempts (a concurrent delete) makes this a fresh creation. */
|
|
59
|
-
record.createdAt = observed.exists
|
|
60
|
-
? (observed.createdAt ?? record.createdAt)
|
|
61
|
-
: record.updatedAt;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
context.logger.warn('store.put: compare-and-swap exhausted; overwriting unconditionally, which can orphan one ' +
|
|
65
|
-
'S3 object under a concurrent put (reclaimed by ensureS3LifecycleRule)', { namespace: record.namespace, key: record.key, attempts: conditional_put_1.OVERWRITE_CAS_MAX_ATTEMPTS });
|
|
66
|
-
await put(context, record);
|
|
67
|
-
return observed;
|
|
68
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { StoreItemRecord } from '../types';
|
|
2
|
-
import type { ExistingRecordMeta } from './read-existing';
|
|
3
|
-
import type { StoreContext } from './setup';
|
|
4
|
-
/**
|
|
5
|
-
* Put the record and clean up whichever side is now dead.
|
|
6
|
-
*
|
|
7
|
-
* The compare-and-swap path runs **only when an offloader is configured**:
|
|
8
|
-
* without one there is no S3 object to orphan, so a plain last-write-wins put
|
|
9
|
-
* stays correct and costs no extra write capacity (DynamoDB charges for a
|
|
10
|
-
* failed conditional write too). With one, the swap is what lets this call
|
|
11
|
-
* delete exactly the payload it superseded rather than a descriptor a racer may
|
|
12
|
-
* already have replaced.
|
|
13
|
-
*
|
|
14
|
-
* Every failure reaching the catch arrives after at least one put was issued —
|
|
15
|
-
* `putWithRevisionSwap` only re-reads from inside its own catch — so none of
|
|
16
|
-
* them proves a non-commit on its own: a put can commit server-side and lose
|
|
17
|
-
* its response, and a `ConditionalCheckFailedException` is as consistent with
|
|
18
|
-
* hitting the row this call just wrote as with a competitor's win. The row is
|
|
19
|
-
* therefore read back (`verifyWriteLanded`) before anything is deleted. Only a
|
|
20
|
-
* confirmed `'not-landed'` deletes this record's own nonced object; a confirmed
|
|
21
|
-
* `'landed'` cleans up the previous object like the success path and swallows
|
|
22
|
-
* the error, and an `'unverified'` read deletes nothing and rethrows — leaking
|
|
23
|
-
* one object at worst rather than stranding a live row pointing at a deleted
|
|
24
|
-
* one. The verification compares the per-call `rev`, so an inline record is
|
|
25
|
-
* verified too: a lost acknowledgement of an inline overwrite used to be
|
|
26
|
-
* reported as a failure while the previous offloaded object was never cleaned.
|
|
27
|
-
*/
|
|
28
|
-
export declare function persistRecord(context: StoreContext, record: StoreItemRecord, existing: ExistingRecordMeta): Promise<void>;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.persistRecord = persistRecord;
|
|
4
|
-
const descriptor_keys_1 = require("../../shared/codec/descriptor-keys");
|
|
5
|
-
const orphans_1 = require("../../shared/codec/s3/orphans");
|
|
6
|
-
const retry_1 = require("../../shared/dynamodb/retry");
|
|
7
|
-
const overwrite_swap_1 = require("./overwrite-swap");
|
|
8
|
-
const write_verify_1 = require("./write-verify");
|
|
9
|
-
/**
|
|
10
|
-
* Best-effort delete of one descriptor's S3 object. `scope` is passed for a
|
|
11
|
-
* descriptor read back from the row (the superseded value) and omitted for
|
|
12
|
-
* this call's own upload.
|
|
13
|
-
*/
|
|
14
|
-
async function cleanUp(context, descriptor, label, scope) {
|
|
15
|
-
if (!context.offloader || !descriptor)
|
|
16
|
-
return;
|
|
17
|
-
await (0, orphans_1.cleanUpS3Orphans)(context.offloader, (0, descriptor_keys_1.collectS3Keys)([descriptor]), label, context.logger, scope === undefined ? {} : { scope });
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Put the record and clean up whichever side is now dead.
|
|
21
|
-
*
|
|
22
|
-
* The compare-and-swap path runs **only when an offloader is configured**:
|
|
23
|
-
* without one there is no S3 object to orphan, so a plain last-write-wins put
|
|
24
|
-
* stays correct and costs no extra write capacity (DynamoDB charges for a
|
|
25
|
-
* failed conditional write too). With one, the swap is what lets this call
|
|
26
|
-
* delete exactly the payload it superseded rather than a descriptor a racer may
|
|
27
|
-
* already have replaced.
|
|
28
|
-
*
|
|
29
|
-
* Every failure reaching the catch arrives after at least one put was issued —
|
|
30
|
-
* `putWithRevisionSwap` only re-reads from inside its own catch — so none of
|
|
31
|
-
* them proves a non-commit on its own: a put can commit server-side and lose
|
|
32
|
-
* its response, and a `ConditionalCheckFailedException` is as consistent with
|
|
33
|
-
* hitting the row this call just wrote as with a competitor's win. The row is
|
|
34
|
-
* therefore read back (`verifyWriteLanded`) before anything is deleted. Only a
|
|
35
|
-
* confirmed `'not-landed'` deletes this record's own nonced object; a confirmed
|
|
36
|
-
* `'landed'` cleans up the previous object like the success path and swallows
|
|
37
|
-
* the error, and an `'unverified'` read deletes nothing and rethrows — leaking
|
|
38
|
-
* one object at worst rather than stranding a live row pointing at a deleted
|
|
39
|
-
* one. The verification compares the per-call `rev`, so an inline record is
|
|
40
|
-
* verified too: a lost acknowledgement of an inline overwrite used to be
|
|
41
|
-
* reported as a failure while the previous offloaded object was never cleaned.
|
|
42
|
-
*/
|
|
43
|
-
async function persistRecord(context, record, existing) {
|
|
44
|
-
let superseded = existing;
|
|
45
|
-
try {
|
|
46
|
-
if (context.offloader) {
|
|
47
|
-
superseded = await (0, overwrite_swap_1.putWithRevisionSwap)(context, record, existing);
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
await (0, retry_1.withDynamoDBRetry)(() => context.client.put({ TableName: context.tableName, Item: record }), context.retry);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
catch (error) {
|
|
54
|
-
const verdict = await (0, write_verify_1.verifyWriteLanded)(context, record);
|
|
55
|
-
if (verdict === 'not-landed')
|
|
56
|
-
await cleanUp(context, record.value, 'store.put');
|
|
57
|
-
if (verdict !== 'landed')
|
|
58
|
-
throw error;
|
|
59
|
-
}
|
|
60
|
-
await cleanUp(context, superseded.value, 'store.put.overwrite', [
|
|
61
|
-
...record.namespace,
|
|
62
|
-
record.key,
|
|
63
|
-
]);
|
|
64
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { QueryCommandInput, ScanCommandInput } from '@aws-sdk/lib-dynamodb';
|
|
2
|
-
/** Query input for a scoped prefix (PK = prefix[0], optional SK begins_with). */
|
|
3
|
-
export declare function scopedQuery(tableName: string, prefix: string[]): QueryCommandInput;
|
|
4
|
-
/** Scan input for the rootless case, filtered to store items only. */
|
|
5
|
-
export declare function storeScan(tableName: string): ScanCommandInput;
|
|
6
|
-
/**
|
|
7
|
-
* Restrict a Query/Scan to the attributes `narrowStoreRecord` needs, leaving the
|
|
8
|
-
* payload behind: a namespace listing never reads a value. RCU is billed on
|
|
9
|
-
* the stored size regardless, so the saving is transfer and unmarshalling.
|
|
10
|
-
*/
|
|
11
|
-
export declare function projectKeys<T extends QueryCommandInput | ScanCommandInput>(params: T): T;
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.scopedQuery = scopedQuery;
|
|
4
|
-
exports.storeScan = storeScan;
|
|
5
|
-
exports.projectKeys = projectKeys;
|
|
6
|
-
const keys_1 = require("./keys");
|
|
7
|
-
/** Query input for a scoped prefix (PK = prefix[0], optional SK begins_with). */
|
|
8
|
-
function scopedQuery(tableName, prefix) {
|
|
9
|
-
const skPrefix = (0, keys_1.sortKeyPrefix)(prefix);
|
|
10
|
-
if (skPrefix.length === 0) {
|
|
11
|
-
return {
|
|
12
|
-
TableName: tableName,
|
|
13
|
-
KeyConditionExpression: '#pk = :pk',
|
|
14
|
-
ExpressionAttributeNames: { '#pk': 'PK' },
|
|
15
|
-
ExpressionAttributeValues: { ':pk': (0, keys_1.partitionKey)(prefix) },
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
return {
|
|
19
|
-
TableName: tableName,
|
|
20
|
-
KeyConditionExpression: '#pk = :pk AND begins_with(#sk, :skp)',
|
|
21
|
-
ExpressionAttributeNames: { '#pk': 'PK', '#sk': 'SK' },
|
|
22
|
-
ExpressionAttributeValues: { ':pk': (0, keys_1.partitionKey)(prefix), ':skp': skPrefix },
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
/** Scan input for the rootless case, filtered to store items only. */
|
|
26
|
-
function storeScan(tableName) {
|
|
27
|
-
return {
|
|
28
|
-
TableName: tableName,
|
|
29
|
-
FilterExpression: 'attribute_exists(#ns)',
|
|
30
|
-
ExpressionAttributeNames: { '#ns': 'namespace' },
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Restrict a Query/Scan to the attributes `narrowStoreRecord` needs, leaving the
|
|
35
|
-
* payload behind: a namespace listing never reads a value. RCU is billed on
|
|
36
|
-
* the stored size regardless, so the saving is transfer and unmarshalling.
|
|
37
|
-
*/
|
|
38
|
-
function projectKeys(params) {
|
|
39
|
-
return {
|
|
40
|
-
...params,
|
|
41
|
-
ProjectionExpression: 'PK, SK, #ns, #key',
|
|
42
|
-
ExpressionAttributeNames: {
|
|
43
|
-
...params.ExpressionAttributeNames,
|
|
44
|
-
'#ns': 'namespace',
|
|
45
|
-
'#key': 'key',
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { Item, SearchItem } from '@langchain/langgraph-checkpoint';
|
|
2
|
-
/** A decoded item plus its stored embedding, awaiting ranking. */
|
|
3
|
-
export interface RankCandidate {
|
|
4
|
-
item: Item;
|
|
5
|
-
embedding?: number[];
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* Rank candidates by cosine similarity to `queryVector`, descending. Throws a
|
|
9
|
-
* {@link ValidationError} when the candidate count exceeds `maxCandidates`
|
|
10
|
-
* (steer large corpora to an external VectorBackend).
|
|
11
|
-
*
|
|
12
|
-
* A stored embedding whose length differs from the query vector's cannot be
|
|
13
|
-
* scored — it was written by a different embeddings model — and is ranked
|
|
14
|
-
* last with an undefined score. `onDimensionMismatch` is invoked once with
|
|
15
|
-
* how many candidates that affected, so the caller can say so instead of
|
|
16
|
-
* silently returning a ranking that quietly omits them.
|
|
17
|
-
*/
|
|
18
|
-
export declare function rankInMemory(candidates: RankCandidate[], queryVector: number[], maxCandidates: number, onDimensionMismatch?: (count: number) => void): SearchItem[];
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.rankInMemory = rankInMemory;
|
|
4
|
-
const errors_1 = require("../../shared/errors/errors");
|
|
5
|
-
const semantic_search_1 = require("./semantic-search");
|
|
6
|
-
/** Sort weight for an item without an embedding; below the −1 cosine minimum. */
|
|
7
|
-
const UNSCORED_RANK = -2;
|
|
8
|
-
/**
|
|
9
|
-
* Rank candidates by cosine similarity to `queryVector`, descending. Throws a
|
|
10
|
-
* {@link ValidationError} when the candidate count exceeds `maxCandidates`
|
|
11
|
-
* (steer large corpora to an external VectorBackend).
|
|
12
|
-
*
|
|
13
|
-
* A stored embedding whose length differs from the query vector's cannot be
|
|
14
|
-
* scored — it was written by a different embeddings model — and is ranked
|
|
15
|
-
* last with an undefined score. `onDimensionMismatch` is invoked once with
|
|
16
|
-
* how many candidates that affected, so the caller can say so instead of
|
|
17
|
-
* silently returning a ranking that quietly omits them.
|
|
18
|
-
*/
|
|
19
|
-
function rankInMemory(candidates, queryVector, maxCandidates, onDimensionMismatch) {
|
|
20
|
-
if (candidates.length > maxCandidates) {
|
|
21
|
-
throw new errors_1.ValidationError(`Semantic search candidate set (${candidates.length}) exceeds maxSearchCandidates ` +
|
|
22
|
-
`(${maxCandidates}); use a dedicated VectorBackend for large corpora`, 'maxSearchCandidates');
|
|
23
|
-
}
|
|
24
|
-
const mismatched = candidates.filter(({ embedding }) => embedding !== undefined && embedding.length !== queryVector.length).length;
|
|
25
|
-
if (mismatched > 0)
|
|
26
|
-
onDimensionMismatch?.(mismatched);
|
|
27
|
-
return candidates
|
|
28
|
-
.map(({ item, embedding }) => ({
|
|
29
|
-
...item,
|
|
30
|
-
score: embedding && embedding.length === queryVector.length
|
|
31
|
-
? (0, semantic_search_1.cosineSimilarity)(queryVector, embedding)
|
|
32
|
-
: undefined,
|
|
33
|
-
}))
|
|
34
|
-
.sort((a, b) => rankValue(b) - rankValue(a));
|
|
35
|
-
}
|
|
36
|
-
/** Sort weight: real cosine score, or a value below the cosine minimum for unscored items. */
|
|
37
|
-
function rankValue(item) {
|
|
38
|
-
return item.score ?? UNSCORED_RANK;
|
|
39
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { DescriptorRef } from '../../shared/codec/descriptor-keys';
|
|
2
|
-
import type { DocItem } from '../../shared/dynamodb/types';
|
|
3
|
-
import type { StoreContext } from './setup';
|
|
4
|
-
/** The previous row's createdAt, payload descriptor and revision. */
|
|
5
|
-
export interface ExistingRecordMeta {
|
|
6
|
-
exists: boolean;
|
|
7
|
-
createdAt?: string;
|
|
8
|
-
value?: DescriptorRef;
|
|
9
|
-
revision?: string;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Read the fields a put needs from the row it is about to replace, in one
|
|
13
|
-
* strongly-consistent projection: `createdAt` to preserve, the descriptor's
|
|
14
|
-
* location and S3 key to clean up afterwards (never its inline bytes, which
|
|
15
|
-
* can be hundreds of kilobytes the write would only discard), and the
|
|
16
|
-
* revision the compare-and-swap pins.
|
|
17
|
-
*
|
|
18
|
-
* Lives apart from `actions/put.ts` so `persist.ts` can re-read on a lost swap
|
|
19
|
-
* without importing its own caller.
|
|
20
|
-
*/
|
|
21
|
-
export declare function readExisting(context: StoreContext, pk: string, sk: string): Promise<ExistingRecordMeta>;
|
|
22
|
-
/** Project a raw row (a read result, or the row a rejection carried) onto {@link ExistingRecordMeta}. */
|
|
23
|
-
export declare function existingFrom(item: DocItem | undefined): ExistingRecordMeta;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.readExisting = readExisting;
|
|
4
|
-
exports.existingFrom = existingFrom;
|
|
5
|
-
const conditional_put_1 = require("../../shared/dynamodb/conditional-put");
|
|
6
|
-
const retry_1 = require("../../shared/dynamodb/retry");
|
|
7
|
-
/**
|
|
8
|
-
* Read the fields a put needs from the row it is about to replace, in one
|
|
9
|
-
* strongly-consistent projection: `createdAt` to preserve, the descriptor's
|
|
10
|
-
* location and S3 key to clean up afterwards (never its inline bytes, which
|
|
11
|
-
* can be hundreds of kilobytes the write would only discard), and the
|
|
12
|
-
* revision the compare-and-swap pins.
|
|
13
|
-
*
|
|
14
|
-
* Lives apart from `actions/put.ts` so `persist.ts` can re-read on a lost swap
|
|
15
|
-
* without importing its own caller.
|
|
16
|
-
*/
|
|
17
|
-
async function readExisting(context, pk, sk) {
|
|
18
|
-
const existing = await (0, retry_1.withDynamoDBRetry)(() => context.client.get({
|
|
19
|
-
TableName: context.tableName,
|
|
20
|
-
Key: { PK: pk, SK: sk },
|
|
21
|
-
ConsistentRead: true,
|
|
22
|
-
ProjectionExpression: '#c, #r, #v.#loc, #v.#s3k',
|
|
23
|
-
ExpressionAttributeNames: {
|
|
24
|
-
'#c': 'createdAt',
|
|
25
|
-
'#r': conditional_put_1.REVISION_ATTRIBUTE,
|
|
26
|
-
'#v': 'value',
|
|
27
|
-
'#loc': 'location',
|
|
28
|
-
'#s3k': 's3Key',
|
|
29
|
-
},
|
|
30
|
-
}), context.retry);
|
|
31
|
-
return existingFrom(existing.Item);
|
|
32
|
-
}
|
|
33
|
-
/** Project a raw row (a read result, or the row a rejection carried) onto {@link ExistingRecordMeta}. */
|
|
34
|
-
function existingFrom(item) {
|
|
35
|
-
return {
|
|
36
|
-
exists: item !== undefined,
|
|
37
|
-
createdAt: item?.createdAt,
|
|
38
|
-
value: item?.value,
|
|
39
|
-
revision: item?.[conditional_put_1.REVISION_ATTRIBUTE],
|
|
40
|
-
};
|
|
41
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { VectorMatch } from '../vector-backend';
|
|
2
|
-
/** Which direction a {@link VectorBackend} reports its score in. */
|
|
3
|
-
export type VectorScoreDirection = 'relevance' | 'distance';
|
|
4
|
-
/** Every direction {@link toRelevanceScores} recognises, for validating input. */
|
|
5
|
-
export declare const VECTOR_SCORE_DIRECTIONS: readonly VectorScoreDirection[];
|
|
6
|
-
/**
|
|
7
|
-
* Normalise a backend's matches to the relevance direction upstream
|
|
8
|
-
* `SearchItem.score` documents — "higher scores indicate better matches",
|
|
9
|
-
* typically a cosine similarity between -1 and 1.
|
|
10
|
-
*
|
|
11
|
-
* A distance is converted by **negation** rather than `1 / (1 + d)`: negation
|
|
12
|
-
* is monotone over the whole real line, needs no non-negativity precondition,
|
|
13
|
-
* and is exactly invertible, so the original distance is simply `-score`. A
|
|
14
|
-
* reciprocal would silently imply a different `(0, 1]` scale and is undefined
|
|
15
|
-
* at `d === -1`. Negative scores are already in range for this contract, so
|
|
16
|
-
* nothing is lost by producing them.
|
|
17
|
-
*
|
|
18
|
-
* Results are re-sorted after conversion so a backend that returns its matches
|
|
19
|
-
* in some other order still ranks correctly. Anything that is not `'distance'`
|
|
20
|
-
* is returned untouched — its own order stays authoritative, exactly as before.
|
|
21
|
-
*
|
|
22
|
-
* The test is for `'distance'` rather than against `'relevance'` on purpose:
|
|
23
|
-
* converting is the destructive branch, so only the exact value that asks for
|
|
24
|
-
* it may reach it. Testing the other way round made every unrecognised
|
|
25
|
-
* string — `'Distance'`, a typo, a value read from a config file — reverse the
|
|
26
|
-
* ranking silently, with no error and no warning (the ascending-score warning
|
|
27
|
-
* lives downstream of this conversion, so it could never fire). `setUpStore`
|
|
28
|
-
* rejects such a value outright; this keeps the failure harmless for any
|
|
29
|
-
* caller that reaches the function some other way.
|
|
30
|
-
*/
|
|
31
|
-
export declare function toRelevanceScores(matches: VectorMatch[], direction: VectorScoreDirection): VectorMatch[];
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VECTOR_SCORE_DIRECTIONS = void 0;
|
|
4
|
-
exports.toRelevanceScores = toRelevanceScores;
|
|
5
|
-
/** Every direction {@link toRelevanceScores} recognises, for validating input. */
|
|
6
|
-
exports.VECTOR_SCORE_DIRECTIONS = ['relevance', 'distance'];
|
|
7
|
-
/**
|
|
8
|
-
* Normalise a backend's matches to the relevance direction upstream
|
|
9
|
-
* `SearchItem.score` documents — "higher scores indicate better matches",
|
|
10
|
-
* typically a cosine similarity between -1 and 1.
|
|
11
|
-
*
|
|
12
|
-
* A distance is converted by **negation** rather than `1 / (1 + d)`: negation
|
|
13
|
-
* is monotone over the whole real line, needs no non-negativity precondition,
|
|
14
|
-
* and is exactly invertible, so the original distance is simply `-score`. A
|
|
15
|
-
* reciprocal would silently imply a different `(0, 1]` scale and is undefined
|
|
16
|
-
* at `d === -1`. Negative scores are already in range for this contract, so
|
|
17
|
-
* nothing is lost by producing them.
|
|
18
|
-
*
|
|
19
|
-
* Results are re-sorted after conversion so a backend that returns its matches
|
|
20
|
-
* in some other order still ranks correctly. Anything that is not `'distance'`
|
|
21
|
-
* is returned untouched — its own order stays authoritative, exactly as before.
|
|
22
|
-
*
|
|
23
|
-
* The test is for `'distance'` rather than against `'relevance'` on purpose:
|
|
24
|
-
* converting is the destructive branch, so only the exact value that asks for
|
|
25
|
-
* it may reach it. Testing the other way round made every unrecognised
|
|
26
|
-
* string — `'Distance'`, a typo, a value read from a config file — reverse the
|
|
27
|
-
* ranking silently, with no error and no warning (the ascending-score warning
|
|
28
|
-
* lives downstream of this conversion, so it could never fire). `setUpStore`
|
|
29
|
-
* rejects such a value outright; this keeps the failure harmless for any
|
|
30
|
-
* caller that reaches the function some other way.
|
|
31
|
-
*/
|
|
32
|
-
function toRelevanceScores(matches, direction) {
|
|
33
|
-
if (direction !== 'distance')
|
|
34
|
-
return matches;
|
|
35
|
-
return matches
|
|
36
|
-
.map((match) => ({ ...match, score: -match.score }))
|
|
37
|
-
.sort((left, right) => right.score - left.score);
|
|
38
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.passesFilter = passesFilter;
|
|
4
|
-
const filter_1 = require("./filter");
|
|
5
|
-
/** True when `item` satisfies the search operation's optional metadata filter. */
|
|
6
|
-
function passesFilter(item, op) {
|
|
7
|
-
if (!op.filter)
|
|
8
|
-
return true;
|
|
9
|
-
return (0, filter_1.matchesStoreFilter)(item.value, op.filter);
|
|
10
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { JsonValue } from './filter';
|
|
2
|
-
/**
|
|
3
|
-
* Split a JSON path into tokens the way LangGraph's `InMemoryStore` does: dots
|
|
4
|
-
* separate plain segments, while a `[…]` index and a `{…}` field group each
|
|
5
|
-
* become a token of their own (`tags[0]` → `['tags', '[0]']`).
|
|
6
|
-
*/
|
|
7
|
-
export declare function tokenizePath(path: string): string[];
|
|
8
|
-
/**
|
|
9
|
-
* Extract the indexable text of `value` at `path`, byte-for-byte as LangGraph's
|
|
10
|
-
* `InMemoryStore` does (`store/utils`), so an embedding computed here matches
|
|
11
|
-
* one computed by the reference store for the same document. Supports plain
|
|
12
|
-
* paths, `[n]`/`[-n]`/`[*]` indexing, a bare `*` wildcard, `{a,b.c}` field
|
|
13
|
-
* groups and `$` for the whole document. The package root's `getTextAtPath` is
|
|
14
|
-
* a string-only variant that returns nothing for numbers, booleans, objects
|
|
15
|
-
* and arrays and throws on a `null` intermediate; it must not be used here.
|
|
16
|
-
*/
|
|
17
|
-
export declare function getTextAtPath(value: JsonValue, path: string): string[];
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.tokenizePath = tokenizePath;
|
|
4
|
-
exports.getTextAtPath = getTextAtPath;
|
|
5
|
-
/** Pretty JSON, exactly as `InMemoryStore` embeds non-scalar values. */
|
|
6
|
-
function pretty(value) {
|
|
7
|
-
return JSON.stringify(value, null, 2);
|
|
8
|
-
}
|
|
9
|
-
function isScalar(value) {
|
|
10
|
-
return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
|
|
11
|
-
}
|
|
12
|
-
/** Text for a leaf: scalars stringify, containers pretty-print, null yields nothing. */
|
|
13
|
-
function leafText(value) {
|
|
14
|
-
if (isScalar(value))
|
|
15
|
-
return [String(value)];
|
|
16
|
-
if (value === null)
|
|
17
|
-
return [];
|
|
18
|
-
return [pretty(value)];
|
|
19
|
-
}
|
|
20
|
-
/** Index just past the closer matching an opener at `start - 1`, honouring nesting. */
|
|
21
|
-
function scanGroup(path, start, open, close) {
|
|
22
|
-
let depth = 1;
|
|
23
|
-
let i = start;
|
|
24
|
-
while (i < path.length && depth > 0) {
|
|
25
|
-
if (path[i] === open)
|
|
26
|
-
depth += 1;
|
|
27
|
-
else if (path[i] === close)
|
|
28
|
-
depth -= 1;
|
|
29
|
-
i += 1;
|
|
30
|
-
}
|
|
31
|
-
return i;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Split a JSON path into tokens the way LangGraph's `InMemoryStore` does: dots
|
|
35
|
-
* separate plain segments, while a `[…]` index and a `{…}` field group each
|
|
36
|
-
* become a token of their own (`tags[0]` → `['tags', '[0]']`).
|
|
37
|
-
*/
|
|
38
|
-
function tokenizePath(path) {
|
|
39
|
-
const tokens = [];
|
|
40
|
-
let current = '';
|
|
41
|
-
const flush = () => {
|
|
42
|
-
if (current.length > 0)
|
|
43
|
-
tokens.push(current);
|
|
44
|
-
current = '';
|
|
45
|
-
};
|
|
46
|
-
let i = 0;
|
|
47
|
-
while (i < path.length) {
|
|
48
|
-
const char = path[i];
|
|
49
|
-
if (char === '[' || char === '{') {
|
|
50
|
-
flush();
|
|
51
|
-
const end = scanGroup(path, i + 1, char, char === '[' ? ']' : '}');
|
|
52
|
-
tokens.push(path.slice(i, end));
|
|
53
|
-
i = end;
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
if (char === '.')
|
|
57
|
-
flush();
|
|
58
|
-
else
|
|
59
|
-
current += char;
|
|
60
|
-
i += 1;
|
|
61
|
-
}
|
|
62
|
-
flush();
|
|
63
|
-
return tokens;
|
|
64
|
-
}
|
|
65
|
-
/** Walk one `{…}`-group field by plain `in` lookups, as the reference does. */
|
|
66
|
-
function groupFieldText(value, field) {
|
|
67
|
-
let current = value;
|
|
68
|
-
for (const token of tokenizePath(field)) {
|
|
69
|
-
if (current !== null && typeof current === 'object' && token in current) {
|
|
70
|
-
current = current[token];
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
return [];
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return isScalar(current) ? [String(current)] : [pretty(current)];
|
|
77
|
-
}
|
|
78
|
-
/** Resolve a `[n]`, `[-n]` or `[*]` token against an array; anything else yields nothing. */
|
|
79
|
-
function indexText(value, token, tokens, pos) {
|
|
80
|
-
if (!Array.isArray(value))
|
|
81
|
-
return [];
|
|
82
|
-
const index = token.slice(1, -1);
|
|
83
|
-
if (index === '*')
|
|
84
|
-
return value.flatMap((item) => extract(item, tokens, pos + 1));
|
|
85
|
-
let idx = Number.parseInt(index, 10);
|
|
86
|
-
if (Number.isNaN(idx))
|
|
87
|
-
return [];
|
|
88
|
-
if (idx < 0)
|
|
89
|
-
idx = value.length + idx;
|
|
90
|
-
return idx >= 0 && idx < value.length ? extract(value[idx], tokens, pos + 1) : [];
|
|
91
|
-
}
|
|
92
|
-
/** Resolve a `{a,b.c}` token: each listed field, walked from the current value. */
|
|
93
|
-
function groupText(value, token) {
|
|
94
|
-
if (typeof value !== 'object' || value === null)
|
|
95
|
-
return [];
|
|
96
|
-
const results = [];
|
|
97
|
-
for (const field of token.slice(1, -1).split(',')) {
|
|
98
|
-
const trimmed = field.trim();
|
|
99
|
-
if (tokenizePath(trimmed).length > 0)
|
|
100
|
-
results.push(...groupFieldText(value, trimmed));
|
|
101
|
-
}
|
|
102
|
-
return results;
|
|
103
|
-
}
|
|
104
|
-
/** Resolve a bare `*` token: every array item or every object value. */
|
|
105
|
-
function wildcardText(value, tokens, pos) {
|
|
106
|
-
if (Array.isArray(value))
|
|
107
|
-
return value.flatMap((item) => extract(item, tokens, pos + 1));
|
|
108
|
-
if (typeof value === 'object' && value !== null) {
|
|
109
|
-
return Object.values(value).flatMap((item) => extract(item, tokens, pos + 1));
|
|
110
|
-
}
|
|
111
|
-
return [];
|
|
112
|
-
}
|
|
113
|
-
/** Resolve a plain member token by an `in` lookup, exactly as the reference does. */
|
|
114
|
-
function memberText(value, token, tokens, pos) {
|
|
115
|
-
if (typeof value !== 'object' || value === null || !(token in value))
|
|
116
|
-
return [];
|
|
117
|
-
return extract(value[token], tokens, pos + 1);
|
|
118
|
-
}
|
|
119
|
-
function extract(value, tokens, pos) {
|
|
120
|
-
if (pos >= tokens.length)
|
|
121
|
-
return leafText(value);
|
|
122
|
-
const token = tokens[pos];
|
|
123
|
-
if (token.startsWith('[') && token.endsWith(']'))
|
|
124
|
-
return indexText(value, token, tokens, pos);
|
|
125
|
-
const results = pos === 0 && token === '$' ? [pretty(value)] : [];
|
|
126
|
-
if (token.startsWith('{') && token.endsWith('}'))
|
|
127
|
-
results.push(...groupText(value, token));
|
|
128
|
-
else if (token === '*')
|
|
129
|
-
results.push(...wildcardText(value, tokens, pos));
|
|
130
|
-
else
|
|
131
|
-
results.push(...memberText(value, token, tokens, pos));
|
|
132
|
-
return results;
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Extract the indexable text of `value` at `path`, byte-for-byte as LangGraph's
|
|
136
|
-
* `InMemoryStore` does (`store/utils`), so an embedding computed here matches
|
|
137
|
-
* one computed by the reference store for the same document. Supports plain
|
|
138
|
-
* paths, `[n]`/`[-n]`/`[*]` indexing, a bare `*` wildcard, `{a,b.c}` field
|
|
139
|
-
* groups and `$` for the whole document. The package root's `getTextAtPath` is
|
|
140
|
-
* a string-only variant that returns nothing for numbers, booleans, objects
|
|
141
|
-
* and arrays and throws on a `null` intermediate; it must not be used here.
|
|
142
|
-
*/
|
|
143
|
-
function getTextAtPath(value, path) {
|
|
144
|
-
if (path === '' || path === '$')
|
|
145
|
-
return [pretty(value)];
|
|
146
|
-
return extract(value, tokenizePath(path), 0);
|
|
147
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/** Validate search/listNamespaces paging is non-negative integers. */
|
|
2
|
-
export declare function validatePaging(offset: number, limit: number): void;
|
|
3
|
-
/** Validate the namespace is non-empty and each element is a valid, ≤256-byte identifier. */
|
|
4
|
-
export declare function validateNamespace(namespace: string[]): void;
|
|
5
|
-
/** Validate an item key is a non-blank, separator- and control-char-free, ≤256-byte string. */
|
|
6
|
-
export declare function validateKey(key: string): void;
|
|
7
|
-
/**
|
|
8
|
-
* Validate a namespace/key pair as the item address it becomes: each segment
|
|
9
|
-
* on its own, then the sort key they compose, which DynamoDB caps at 1024
|
|
10
|
-
* bytes regardless of how short the individual segments are.
|
|
11
|
-
*/
|
|
12
|
-
export declare function validateStoreKey(namespace: string[], key: string): void;
|
|
13
|
-
/**
|
|
14
|
-
* Validate an optional namespace depth cap. Left unchecked, a negative value
|
|
15
|
-
* silently inverted truncation via `Array.prototype.slice(0, -n)`, which drops
|
|
16
|
-
* the *last* n elements rather than erroring.
|
|
17
|
-
*/
|
|
18
|
-
export declare function validateMaxDepth(maxDepth?: number): void;
|