@farukada/aws-langgraph-dynamodb-ts 0.1.1 → 0.2.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 +131 -5
- package/dist/checkpointer/actions/delete-thread.d.ts.map +1 -1
- package/dist/checkpointer/actions/delete-thread.js +17 -9
- package/dist/checkpointer/actions/delete-thread.js.map +1 -1
- package/dist/checkpointer/actions/get-tuple.d.ts.map +1 -1
- package/dist/checkpointer/actions/get-tuple.js +70 -32
- package/dist/checkpointer/actions/get-tuple.js.map +1 -1
- package/dist/checkpointer/actions/put-writes.d.ts.map +1 -1
- package/dist/checkpointer/actions/put-writes.js +36 -19
- package/dist/checkpointer/actions/put-writes.js.map +1 -1
- package/dist/checkpointer/actions/put.d.ts.map +1 -1
- package/dist/checkpointer/actions/put.js +75 -18
- package/dist/checkpointer/actions/put.js.map +1 -1
- package/dist/checkpointer/actions/writer.d.ts +6 -4
- package/dist/checkpointer/actions/writer.d.ts.map +1 -1
- package/dist/checkpointer/actions/writer.js +12 -12
- package/dist/checkpointer/actions/writer.js.map +1 -1
- package/dist/checkpointer/index.d.ts +11 -4
- package/dist/checkpointer/index.d.ts.map +1 -1
- package/dist/checkpointer/index.js +97 -72
- package/dist/checkpointer/index.js.map +1 -1
- package/dist/checkpointer/types/index.d.ts +8 -0
- package/dist/checkpointer/types/index.d.ts.map +1 -1
- package/dist/checkpointer/utils/deserialization.d.ts.map +1 -1
- package/dist/checkpointer/utils/deserialization.js +28 -4
- package/dist/checkpointer/utils/deserialization.js.map +1 -1
- package/dist/checkpointer/utils/validation.d.ts +8 -8
- package/dist/checkpointer/utils/validation.d.ts.map +1 -1
- package/dist/checkpointer/utils/validation.js +45 -1
- package/dist/checkpointer/utils/validation.js.map +1 -1
- package/dist/factory.d.ts +14 -0
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +39 -20
- package/dist/factory.js.map +1 -1
- package/dist/history/actions/add-message.d.ts +5 -9
- package/dist/history/actions/add-message.d.ts.map +1 -1
- package/dist/history/actions/add-message.js +14 -42
- package/dist/history/actions/add-message.js.map +1 -1
- package/dist/history/actions/add-messages.d.ts +6 -10
- package/dist/history/actions/add-messages.d.ts.map +1 -1
- package/dist/history/actions/add-messages.js +33 -38
- package/dist/history/actions/add-messages.js.map +1 -1
- package/dist/history/actions/clear.d.ts.map +1 -1
- package/dist/history/actions/clear.js +3 -3
- package/dist/history/actions/clear.js.map +1 -1
- package/dist/history/actions/get-messages.d.ts.map +1 -1
- package/dist/history/actions/get-messages.js +2 -2
- package/dist/history/actions/get-messages.js.map +1 -1
- package/dist/history/actions/list-sessions.d.ts.map +1 -1
- package/dist/history/actions/list-sessions.js +6 -3
- package/dist/history/actions/list-sessions.js.map +1 -1
- package/dist/history/index.d.ts +41 -5
- package/dist/history/index.d.ts.map +1 -1
- package/dist/history/index.js +52 -18
- package/dist/history/index.js.map +1 -1
- package/dist/history/session-adapter.d.ts +39 -0
- package/dist/history/session-adapter.d.ts.map +1 -0
- package/dist/history/session-adapter.js +74 -0
- package/dist/history/session-adapter.js.map +1 -0
- package/dist/history/types/index.d.ts +32 -1
- package/dist/history/types/index.d.ts.map +1 -1
- package/dist/history/utils/index.d.ts +1 -0
- package/dist/history/utils/index.d.ts.map +1 -1
- package/dist/history/utils/index.js +1 -0
- package/dist/history/utils/index.js.map +1 -1
- package/dist/history/utils/optimistic-retry.d.ts +31 -0
- package/dist/history/utils/optimistic-retry.d.ts.map +1 -0
- package/dist/history/utils/optimistic-retry.js +74 -0
- package/dist/history/utils/optimistic-retry.js.map +1 -0
- package/dist/history/utils/title-generator.d.ts.map +1 -1
- package/dist/history/utils/title-generator.js +8 -3
- package/dist/history/utils/title-generator.js.map +1 -1
- package/dist/history/utils/update-expression-builder.d.ts +18 -21
- package/dist/history/utils/update-expression-builder.d.ts.map +1 -1
- package/dist/history/utils/update-expression-builder.js +31 -46
- package/dist/history/utils/update-expression-builder.js.map +1 -1
- package/dist/history/utils/validation.d.ts.map +1 -1
- package/dist/history/utils/validation.js +23 -3
- package/dist/history/utils/validation.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/shared/utils/batch-write.d.ts +44 -6
- package/dist/shared/utils/batch-write.d.ts.map +1 -1
- package/dist/shared/utils/batch-write.js +76 -28
- package/dist/shared/utils/batch-write.js.map +1 -1
- package/dist/shared/utils/client-factory.d.ts +25 -0
- package/dist/shared/utils/client-factory.d.ts.map +1 -0
- package/dist/shared/utils/client-factory.js +23 -0
- package/dist/shared/utils/client-factory.js.map +1 -0
- package/dist/shared/utils/compressor.d.ts +21 -3
- package/dist/shared/utils/compressor.d.ts.map +1 -1
- package/dist/shared/utils/compressor.js +75 -10
- package/dist/shared/utils/compressor.js.map +1 -1
- package/dist/shared/utils/constants.d.ts +1 -1
- package/dist/shared/utils/constants.d.ts.map +1 -1
- package/dist/shared/utils/constants.js +5 -1
- package/dist/shared/utils/constants.js.map +1 -1
- package/dist/shared/utils/index.d.ts +3 -0
- package/dist/shared/utils/index.d.ts.map +1 -1
- package/dist/shared/utils/index.js +3 -0
- package/dist/shared/utils/index.js.map +1 -1
- package/dist/shared/utils/logger.d.ts +27 -0
- package/dist/shared/utils/logger.d.ts.map +1 -1
- package/dist/shared/utils/logger.js +86 -0
- package/dist/shared/utils/logger.js.map +1 -1
- package/dist/shared/utils/retry.d.ts +7 -0
- package/dist/shared/utils/retry.d.ts.map +1 -1
- package/dist/shared/utils/retry.js +75 -17
- package/dist/shared/utils/retry.js.map +1 -1
- package/dist/shared/utils/s3-offloader.d.ts +10 -3
- package/dist/shared/utils/s3-offloader.d.ts.map +1 -1
- package/dist/shared/utils/s3-offloader.js +19 -9
- package/dist/shared/utils/s3-offloader.js.map +1 -1
- package/dist/shared/utils/s3-orphans.d.ts +16 -0
- package/dist/shared/utils/s3-orphans.d.ts.map +1 -0
- package/dist/shared/utils/s3-orphans.js +79 -0
- package/dist/shared/utils/s3-orphans.js.map +1 -0
- package/dist/shared/utils/sleep.d.ts +48 -0
- package/dist/shared/utils/sleep.d.ts.map +1 -0
- package/dist/shared/utils/sleep.js +82 -0
- package/dist/shared/utils/sleep.js.map +1 -0
- package/dist/shared/utils/ttl.d.ts +6 -2
- package/dist/shared/utils/ttl.d.ts.map +1 -1
- package/dist/shared/utils/ttl.js +17 -2
- package/dist/shared/utils/ttl.js.map +1 -1
- package/dist/store/actions/get-operation.d.ts.map +1 -1
- package/dist/store/actions/get-operation.js +2 -2
- package/dist/store/actions/get-operation.js.map +1 -1
- package/dist/store/actions/list-namespaces-operation.d.ts.map +1 -1
- package/dist/store/actions/list-namespaces-operation.js +44 -29
- package/dist/store/actions/list-namespaces-operation.js.map +1 -1
- package/dist/store/actions/put-operation.d.ts.map +1 -1
- package/dist/store/actions/put-operation.js +19 -5
- package/dist/store/actions/put-operation.js.map +1 -1
- package/dist/store/actions/search-operation.d.ts.map +1 -1
- package/dist/store/actions/search-operation.js +54 -21
- package/dist/store/actions/search-operation.js.map +1 -1
- package/dist/store/index.d.ts +1 -0
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +24 -20
- package/dist/store/index.js.map +1 -1
- package/dist/store/types/index.d.ts +33 -1
- package/dist/store/types/index.d.ts.map +1 -1
- package/dist/store/utils/filter.d.ts.map +1 -1
- package/dist/store/utils/filter.js +63 -1
- package/dist/store/utils/filter.js.map +1 -1
- package/dist/store/utils/validation.d.ts +6 -2
- package/dist/store/utils/validation.d.ts.map +1 -1
- package/dist/store/utils/validation.js +21 -5
- package/dist/store/utils/validation.js.map +1 -1
- package/package.json +39 -25
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Backoff helper shared by the UnprocessedItems / UnprocessedKeys retry loops
|
|
4
|
+
* in batch-write and BatchGetItem paths. Centralized so both call sites use
|
|
5
|
+
* the same cap, growth, and sleep semantics.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.MAX_BACKOFF_DELAY_MS = exports.INITIAL_BACKOFF_DELAY_MS = void 0;
|
|
9
|
+
exports.sleep = sleep;
|
|
10
|
+
exports.nextBackoffDelay = nextBackoffDelay;
|
|
11
|
+
exports.fullJitter = fullJitter;
|
|
12
|
+
const DEFAULT_INITIAL_DELAY_MS = 100;
|
|
13
|
+
const DEFAULT_MAX_DELAY_MS = 5000;
|
|
14
|
+
/**
|
|
15
|
+
* Sleep for `ms` milliseconds, optionally cancellable via an `AbortSignal`.
|
|
16
|
+
*
|
|
17
|
+
* If `signal` is already aborted the returned promise rejects synchronously with
|
|
18
|
+
* the signal's abort reason. Otherwise the timer resolves on the normal path and
|
|
19
|
+
* the abort listener is removed to avoid leaking handlers.
|
|
20
|
+
*
|
|
21
|
+
* The `settled` flag is a belt-and-braces guard: `{ once: true }` already
|
|
22
|
+
* prevents the listener from firing twice, but the guard also ensures we never
|
|
23
|
+
* resolve *and* reject (which would produce an unhandled rejection if the timer
|
|
24
|
+
* and abort event fire in the same microtask turn).
|
|
25
|
+
*/
|
|
26
|
+
function sleep(ms, signal) {
|
|
27
|
+
if (signal?.aborted) {
|
|
28
|
+
return Promise.reject(signal.reason ?? new Error('Aborted'));
|
|
29
|
+
}
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
let settled = false;
|
|
32
|
+
const timer = setTimeout(() => {
|
|
33
|
+
if (settled)
|
|
34
|
+
return;
|
|
35
|
+
settled = true;
|
|
36
|
+
signal?.removeEventListener('abort', onAbort);
|
|
37
|
+
resolve();
|
|
38
|
+
}, ms);
|
|
39
|
+
const onAbort = () => {
|
|
40
|
+
if (settled)
|
|
41
|
+
return;
|
|
42
|
+
settled = true;
|
|
43
|
+
clearTimeout(timer);
|
|
44
|
+
reject(signal?.reason ?? new Error('Aborted'));
|
|
45
|
+
};
|
|
46
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Exponential-backoff delay calculator. Given the *previous* delay, returns the
|
|
51
|
+
* next delay — double it, capped at `max`. Use with {@link sleep} and
|
|
52
|
+
* {@link fullJitter} so concurrent retriers don't synchronize.
|
|
53
|
+
*
|
|
54
|
+
* let delay = INITIAL_DELAY_MS;
|
|
55
|
+
* while (keep_going) {
|
|
56
|
+
* await sleep(fullJitter(delay));
|
|
57
|
+
* delay = nextBackoffDelay(delay);
|
|
58
|
+
* }
|
|
59
|
+
*/
|
|
60
|
+
function nextBackoffDelay(currentMs, maxMs = DEFAULT_MAX_DELAY_MS) {
|
|
61
|
+
return Math.min(currentMs * 2, maxMs);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Apply full jitter (AWS recommended) to a backoff delay.
|
|
65
|
+
*
|
|
66
|
+
* Returns a uniform random value in `[0, delayMs)`. Spreading retries across the
|
|
67
|
+
* backoff window prevents the thundering-herd pattern where every throttled
|
|
68
|
+
* client wakes up at the same instant and re-throttles the service.
|
|
69
|
+
* See https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
|
|
70
|
+
*/
|
|
71
|
+
function fullJitter(delayMs) {
|
|
72
|
+
return Math.random() * delayMs;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Starting delay for UnprocessedItems / UnprocessedKeys retry loops.
|
|
76
|
+
*/
|
|
77
|
+
exports.INITIAL_BACKOFF_DELAY_MS = DEFAULT_INITIAL_DELAY_MS;
|
|
78
|
+
/**
|
|
79
|
+
* Maximum delay for UnprocessedItems / UnprocessedKeys retry loops.
|
|
80
|
+
*/
|
|
81
|
+
exports.MAX_BACKOFF_DELAY_MS = DEFAULT_MAX_DELAY_MS;
|
|
82
|
+
//# sourceMappingURL=sleep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sleep.js","sourceRoot":"","sources":["../../../src/shared/utils/sleep.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAiBH,sBAoBC;AAaD,4CAEC;AAUD,gCAEC;AA9DD,MAAM,wBAAwB,GAAG,GAAG,CAAC;AACrC,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAElC;;;;;;;;;;;GAWG;AACH,SAAgB,KAAK,CAAC,EAAU,EAAE,MAAoB;IACpD,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;QACpB,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QACjD,CAAC,CAAC;QACF,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,gBAAgB,CAAC,SAAiB,EAAE,QAAgB,oBAAoB;IACtF,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,UAAU,CAAC,OAAe;IACxC,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC;AACjC,CAAC;AAED;;GAEG;AACU,QAAA,wBAAwB,GAAG,wBAAwB,CAAC;AAEjE;;GAEG;AACU,QAAA,oBAAoB,GAAG,oBAAoB,CAAC"}
|
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
* Provide centralized TTL calculation for DynamoDB items
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
|
-
* Calculate Unix timestamp for TTL expiration from seconds
|
|
6
|
+
* Calculate Unix timestamp for TTL expiration from seconds.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* Validates the input so callers can't silently produce absurd timestamps
|
|
9
|
+
* (e.g. `Number.MAX_SAFE_INTEGER`) that DynamoDB would reject at write time.
|
|
10
|
+
*
|
|
11
|
+
* @param ttlSeconds - Number of seconds until expiration (integer > 0, ≤ 100 years)
|
|
9
12
|
* @returns Unix timestamp in seconds for DynamoDB TTL attribute
|
|
13
|
+
* @throws Error if ttlSeconds is not a positive finite integer within the allowed range
|
|
10
14
|
*/
|
|
11
15
|
export declare function calculateTTLTimestampFromSeconds(ttlSeconds: number): number;
|
|
12
16
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ttl.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/ttl.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"ttl.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/ttl.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;;;;;;;;GASG;AACH,wBAAgB,gCAAgC,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAW3E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE7D"}
|
package/dist/shared/utils/ttl.js
CHANGED
|
@@ -6,13 +6,28 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.calculateTTLTimestampFromSeconds = calculateTTLTimestampFromSeconds;
|
|
8
8
|
exports.calculateTTLTimestamp = calculateTTLTimestamp;
|
|
9
|
+
/** 100 years in seconds — comfortable upper bound for any TTL use case. */
|
|
10
|
+
const MAX_TTL_SECONDS = 100 * 365 * 24 * 60 * 60;
|
|
9
11
|
/**
|
|
10
|
-
* Calculate Unix timestamp for TTL expiration from seconds
|
|
12
|
+
* Calculate Unix timestamp for TTL expiration from seconds.
|
|
11
13
|
*
|
|
12
|
-
*
|
|
14
|
+
* Validates the input so callers can't silently produce absurd timestamps
|
|
15
|
+
* (e.g. `Number.MAX_SAFE_INTEGER`) that DynamoDB would reject at write time.
|
|
16
|
+
*
|
|
17
|
+
* @param ttlSeconds - Number of seconds until expiration (integer > 0, ≤ 100 years)
|
|
13
18
|
* @returns Unix timestamp in seconds for DynamoDB TTL attribute
|
|
19
|
+
* @throws Error if ttlSeconds is not a positive finite integer within the allowed range
|
|
14
20
|
*/
|
|
15
21
|
function calculateTTLTimestampFromSeconds(ttlSeconds) {
|
|
22
|
+
if (typeof ttlSeconds !== 'number' || !Number.isInteger(ttlSeconds)) {
|
|
23
|
+
throw new Error('ttlSeconds must be an integer');
|
|
24
|
+
}
|
|
25
|
+
if (ttlSeconds <= 0) {
|
|
26
|
+
throw new Error('ttlSeconds must be positive');
|
|
27
|
+
}
|
|
28
|
+
if (ttlSeconds > MAX_TTL_SECONDS) {
|
|
29
|
+
throw new Error(`ttlSeconds cannot exceed ${MAX_TTL_SECONDS} (100 years)`);
|
|
30
|
+
}
|
|
16
31
|
return Math.floor(Date.now() / 1000) + ttlSeconds;
|
|
17
32
|
}
|
|
18
33
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ttl.js","sourceRoot":"","sources":["../../../src/shared/utils/ttl.ts"],"names":[],"mappings":";AAAA;;;GAGG;;
|
|
1
|
+
{"version":3,"file":"ttl.js","sourceRoot":"","sources":["../../../src/shared/utils/ttl.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAeH,4EAWC;AASD,sDAEC;AAnCD,2EAA2E;AAC3E,MAAM,eAAe,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAEjD;;;;;;;;;GASG;AACH,SAAgB,gCAAgC,CAAC,UAAkB;IACjE,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,UAAU,GAAG,eAAe,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,4BAA4B,eAAe,cAAc,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,UAAU,CAAC;AACpD,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,qBAAqB,CAAC,OAAe;IACnD,OAAO,gCAAgC,CAAC,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;AAClE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-operation.d.ts","sourceRoot":"","sources":["../../../src/store/actions/get-operation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAGzD;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,wBAAwB,KAC/B,OAAO,CAAC,IAAI,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"get-operation.d.ts","sourceRoot":"","sources":["../../../src/store/actions/get-operation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAGzD;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,wBAAwB,KAC/B,OAAO,CAAC,IAAI,GAAG,IAAI,CAoCrB,CAAC"}
|
|
@@ -10,7 +10,7 @@ const utils_1 = require("../utils");
|
|
|
10
10
|
* @throws Error if the operation fails or validation fails
|
|
11
11
|
*/
|
|
12
12
|
const getOperationAction = async (params) => {
|
|
13
|
-
const { client, memoryTableName, userId, op } = params;
|
|
13
|
+
const { client, memoryTableName, userId, op, signal } = params;
|
|
14
14
|
// Validate inputs
|
|
15
15
|
(0, utils_1.validateUserId)(userId);
|
|
16
16
|
(0, utils_1.validateNamespace)(op.namespace);
|
|
@@ -26,7 +26,7 @@ const getOperationAction = async (params) => {
|
|
|
26
26
|
namespace_key: sortKey,
|
|
27
27
|
},
|
|
28
28
|
});
|
|
29
|
-
});
|
|
29
|
+
}, { signal });
|
|
30
30
|
if (!ddbItem.Item) {
|
|
31
31
|
return null;
|
|
32
32
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-operation.js","sourceRoot":"","sources":["../../../src/store/actions/get-operation.ts"],"names":[],"mappings":";;;AAGA,oCAA6F;AAE7F;;;;;;GAMG;AACI,MAAM,kBAAkB,GAAG,KAAK,EACrC,MAAgC,EACV,EAAE;IACxB,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"get-operation.js","sourceRoot":"","sources":["../../../src/store/actions/get-operation.ts"],"names":[],"mappings":";;;AAGA,oCAA6F;AAE7F;;;;;;GAMG;AACI,MAAM,kBAAkB,GAAG,KAAK,EACrC,MAAgC,EACV,EAAE;IACxB,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAE/D,kBAAkB;IAClB,IAAA,sBAAc,EAAC,MAAM,CAAC,CAAC;IACvB,IAAA,yBAAiB,EAAC,EAAE,CAAC,SAAS,CAAC,CAAC;IAChC,IAAA,mBAAW,EAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAEpB,MAAM,aAAa,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,GAAG,aAAa,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC;IAE7C,2BAA2B;IAC3B,MAAM,OAAO,GAAG,MAAM,IAAA,yBAAiB,EACrC,KAAK,IAAI,EAAE;QACT,OAAO,MAAM,MAAM,CAAC,GAAG,CAAC;YACtB,SAAS,EAAE,eAAe;YAC1B,GAAG,EAAE;gBACH,OAAO,EAAE,MAAM;gBACf,aAAa,EAAE,OAAO;aACvB;SACF,CAAC,CAAC;IACL,CAAC,EACD,EAAE,MAAM,EAAE,CACX,CAAC;IAEF,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG;QACrB,SAAS,EAAE,EAAE,CAAC,SAAS;QACvB,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK;QACzB,SAAS,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;QAC3C,SAAS,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;KAC5C,CAAC;AACJ,CAAC,CAAC;AAtCW,QAAA,kBAAkB,sBAsC7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-namespaces-operation.d.ts","sourceRoot":"","sources":["../../../src/store/actions/list-namespaces-operation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mCAAmC,EAAiB,MAAM,UAAU,CAAC;AASnF;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,GACxC,QAAQ,mCAAmC,KAC1C,OAAO,CAAC,MAAM,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"list-namespaces-operation.d.ts","sourceRoot":"","sources":["../../../src/store/actions/list-namespaces-operation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mCAAmC,EAAiB,MAAM,UAAU,CAAC;AASnF;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,GACxC,QAAQ,mCAAmC,KAC1C,OAAO,CAAC,MAAM,EAAE,EAAE,CAwJpB,CAAC"}
|
|
@@ -10,9 +10,12 @@ const utils_1 = require("../utils");
|
|
|
10
10
|
* @throws Error if the operation fails or validation fails
|
|
11
11
|
*/
|
|
12
12
|
const listNamespacesOperationAction = async (params) => {
|
|
13
|
-
const { client, memoryTableName, userId, op } = params;
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const { client, memoryTableName, userId, op, signal } = params;
|
|
14
|
+
// LangGraph's BaseStore.listNamespaces defaults these to 100 and 0 before dispatching
|
|
15
|
+
// through batch(), but nothing guarantees the caller went via that path. Fall back
|
|
16
|
+
// to the same defaults so `(limit + offset) * CANDIDATE_MULTIPLIER` below stays finite.
|
|
17
|
+
const limit = op.limit ?? 100;
|
|
18
|
+
const offset = op.offset ?? 0;
|
|
16
19
|
const matchConditions = op.matchConditions ?? [];
|
|
17
20
|
const maxDepth = op.maxDepth;
|
|
18
21
|
// Validate inputs
|
|
@@ -22,20 +25,30 @@ const listNamespacesOperationAction = async (params) => {
|
|
|
22
25
|
// Determine if we can optimize with KeyConditionExpression
|
|
23
26
|
const prefixCondition = matchConditions.find((c) => c.matchType === 'prefix');
|
|
24
27
|
const namespacePrefix = prefixCondition ? extractConcretePrefix(prefixCondition.path) : '';
|
|
25
|
-
// Build query parameters
|
|
28
|
+
// Build query parameters.
|
|
29
|
+
//
|
|
30
|
+
// IMPORTANT: ExpressionAttributeNames starts as a local accumulator rather
|
|
31
|
+
// than an always-present `{}` on the QueryInput — DynamoDB rejects requests
|
|
32
|
+
// that carry an empty ExpressionAttributeNames object with
|
|
33
|
+
// `ValidationException: ExpressionAttributeNames must not be empty`. We
|
|
34
|
+
// attach it to the input only when at least one entry has been added.
|
|
35
|
+
const expressionAttributeNames = {};
|
|
26
36
|
const queryParams = {
|
|
27
37
|
TableName: memoryTableName,
|
|
28
38
|
KeyConditionExpression: 'user_id = :uid',
|
|
29
39
|
ExpressionAttributeValues: {
|
|
30
40
|
':uid': userId,
|
|
31
41
|
},
|
|
32
|
-
ExpressionAttributeNames: {},
|
|
33
42
|
ProjectionExpression: 'namespace',
|
|
34
43
|
};
|
|
35
|
-
// Optimize a query with begins_with for prefix conditions
|
|
44
|
+
// Optimize a query with begins_with for prefix conditions.
|
|
45
|
+
// NOTE: we do NOT append a separator — the SK is `<nsPath>#<key>`; appending
|
|
46
|
+
// "#" misses sub-namespaces (`"users/alice#x"` would not begin with `"users#"`).
|
|
47
|
+
// Raw prefix is over-inclusive (`users` also matches `users_v2`) but the
|
|
48
|
+
// in-memory match filter eliminates false positives.
|
|
36
49
|
if (namespacePrefix) {
|
|
37
50
|
queryParams.KeyConditionExpression += ' AND begins_with(namespace_key, :nsPrefix)';
|
|
38
|
-
queryParams.ExpressionAttributeValues[':nsPrefix'] =
|
|
51
|
+
queryParams.ExpressionAttributeValues[':nsPrefix'] = namespacePrefix;
|
|
39
52
|
}
|
|
40
53
|
// Build FilterExpression for suffix conditions using contains()
|
|
41
54
|
const filterExpressions = [];
|
|
@@ -45,7 +58,7 @@ const listNamespacesOperationAction = async (params) => {
|
|
|
45
58
|
if (concreteSuffix) {
|
|
46
59
|
const attrName = `#ns${index}`;
|
|
47
60
|
const valueName = `:suffix${index}`;
|
|
48
|
-
|
|
61
|
+
expressionAttributeNames[attrName] = 'namespace';
|
|
49
62
|
queryParams.ExpressionAttributeValues[valueName] = concreteSuffix;
|
|
50
63
|
filterExpressions.push(`contains(${attrName}, ${valueName})`);
|
|
51
64
|
}
|
|
@@ -53,6 +66,10 @@ const listNamespacesOperationAction = async (params) => {
|
|
|
53
66
|
if (filterExpressions.length > 0) {
|
|
54
67
|
queryParams.FilterExpression = filterExpressions.join(' AND ');
|
|
55
68
|
}
|
|
69
|
+
// Only attach ExpressionAttributeNames when non-empty — DDB rejects {}.
|
|
70
|
+
if (Object.keys(expressionAttributeNames).length > 0) {
|
|
71
|
+
queryParams.ExpressionAttributeNames = expressionAttributeNames;
|
|
72
|
+
}
|
|
56
73
|
// Use a Set to track unique namespaces
|
|
57
74
|
const namespaceSet = new Set();
|
|
58
75
|
let lastEvaluatedKey;
|
|
@@ -72,7 +89,7 @@ const listNamespacesOperationAction = async (params) => {
|
|
|
72
89
|
}
|
|
73
90
|
const response = await (0, utils_1.withDynamoDBRetry)(async () => {
|
|
74
91
|
return await client.query(queryParams);
|
|
75
|
-
});
|
|
92
|
+
}, { signal });
|
|
76
93
|
// Extract and deduplicate namespaces
|
|
77
94
|
response.Items?.forEach((item) => {
|
|
78
95
|
if (item.namespace !== undefined && item.namespace !== null) {
|
|
@@ -89,35 +106,33 @@ const listNamespacesOperationAction = async (params) => {
|
|
|
89
106
|
break;
|
|
90
107
|
}
|
|
91
108
|
} while (lastEvaluatedKey);
|
|
92
|
-
// Convert Set to an array of namespace arrays
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
// Apply all match conditions
|
|
98
|
-
const
|
|
99
|
-
// Check all match conditions (must match ALL)
|
|
109
|
+
// Convert Set to an array of namespace arrays.
|
|
110
|
+
// userId is the partition key and is NOT part of the namespace path, so it is
|
|
111
|
+
// excluded here to match the shape returned by other store methods and the
|
|
112
|
+
// LangGraph reference InMemoryStore implementation.
|
|
113
|
+
const allNamespaces = Array.from(namespaceSet).map((ns) => (ns ? ns.split('/') : []));
|
|
114
|
+
// Apply all match conditions (reference: memory.js:122-138)
|
|
115
|
+
const matchedNamespaces = allNamespaces.filter((namespacePath) => {
|
|
100
116
|
for (const condition of matchConditions) {
|
|
101
|
-
// Always check the condition, regardless of wildcards
|
|
102
|
-
// DynamoDB filtering is just an optimization, we verify all conditions here
|
|
103
117
|
if (!matchesCondition(namespacePath, condition)) {
|
|
104
118
|
return false;
|
|
105
119
|
}
|
|
106
120
|
}
|
|
107
|
-
// Check maxDepth if specified
|
|
108
|
-
if (maxDepth !== undefined) {
|
|
109
|
-
// Depth is measured from userId (first element)
|
|
110
|
-
const depth = namespacePath.length;
|
|
111
|
-
if (depth > maxDepth) {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
121
|
return true;
|
|
116
122
|
});
|
|
123
|
+
// Apply maxDepth: truncate each namespace to its first N segments, then dedupe.
|
|
124
|
+
// This matches the reference impl (memory.js:115-121) where deeper namespaces
|
|
125
|
+
// collapse into their parent paths rather than being filtered out entirely.
|
|
126
|
+
const truncatedSet = new Set();
|
|
127
|
+
for (const path of matchedNamespaces) {
|
|
128
|
+
const truncated = maxDepth !== undefined ? path.slice(0, maxDepth) : path;
|
|
129
|
+
truncatedSet.add(truncated.join('/'));
|
|
130
|
+
}
|
|
131
|
+
const dedupedNamespaces = Array.from(truncatedSet).map((ns) => (ns ? ns.split('/') : []));
|
|
117
132
|
// Sort namespaces for consistent ordering
|
|
118
|
-
|
|
133
|
+
dedupedNamespaces.sort((a, b) => a.join('/').localeCompare(b.join('/')));
|
|
119
134
|
// Apply offset and limit
|
|
120
|
-
return
|
|
135
|
+
return dedupedNamespaces.slice(offset, offset + limit);
|
|
121
136
|
};
|
|
122
137
|
exports.listNamespacesOperationAction = listNamespacesOperationAction;
|
|
123
138
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-namespaces-operation.js","sourceRoot":"","sources":["../../../src/store/actions/list-namespaces-operation.ts"],"names":[],"mappings":";;;AAIA,oCAMkB;AAElB;;;;;;GAMG;AACI,MAAM,6BAA6B,GAAG,KAAK,EAChD,MAA2C,EACtB,EAAE;IACvB,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"list-namespaces-operation.js","sourceRoot":"","sources":["../../../src/store/actions/list-namespaces-operation.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"put-operation.d.ts","sourceRoot":"","sources":["../../../src/store/actions/put-operation.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAYpD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAU,QAAQ,wBAAwB,KAAG,OAAO,CAAC,IAAI,
|
|
1
|
+
{"version":3,"file":"put-operation.d.ts","sourceRoot":"","sources":["../../../src/store/actions/put-operation.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAYpD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAU,QAAQ,wBAAwB,KAAG,OAAO,CAAC,IAAI,CA4GvF,CAAC"}
|
|
@@ -11,15 +11,29 @@ const utils_1 = require("../utils");
|
|
|
11
11
|
* @throws Error if the operation fails or validation fails
|
|
12
12
|
*/
|
|
13
13
|
const putOperationAction = async (params) => {
|
|
14
|
-
const { client, embedding, memoryTableName, userId, op, ttlDays } = params;
|
|
14
|
+
const { client, embedding, memoryTableName, userId, op, ttlDays, signal } = params;
|
|
15
15
|
// Validate inputs
|
|
16
16
|
(0, utils_1.validateUserId)(userId);
|
|
17
17
|
(0, utils_1.validateNamespace)(op.namespace);
|
|
18
18
|
(0, utils_1.validateKey)(op.key);
|
|
19
|
-
(0, utils_1.validateValue)(op.value);
|
|
20
19
|
(0, utils_1.validateTTL)(ttlDays);
|
|
21
20
|
const namespacePath = op.namespace.join('/');
|
|
22
21
|
const namespace_key = `${namespacePath}#${op.key}`;
|
|
22
|
+
// LangGraph convention: PutOperation with value === null means delete the item.
|
|
23
|
+
// BaseStore.delete(ns, key) routes through batch([{namespace, key, value: null}]).
|
|
24
|
+
if (op.value === null) {
|
|
25
|
+
await (0, utils_1.withDynamoDBRetry)(async () => {
|
|
26
|
+
await client.delete({
|
|
27
|
+
TableName: memoryTableName,
|
|
28
|
+
Key: {
|
|
29
|
+
user_id: userId,
|
|
30
|
+
namespace_key: namespace_key,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}, { signal });
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
(0, utils_1.validateValue)(op.value);
|
|
23
37
|
const now = Date.now();
|
|
24
38
|
// Generate embeddings if requested
|
|
25
39
|
let embeddings;
|
|
@@ -70,8 +84,8 @@ const putOperationAction = async (params) => {
|
|
|
70
84
|
updateExpressionParts.push('embedding = :embedding');
|
|
71
85
|
expressionAttributeValues[':embedding'] = embeddings;
|
|
72
86
|
}
|
|
73
|
-
// Add TTL if configured
|
|
74
|
-
if (ttlDays
|
|
87
|
+
// Add TTL if configured (validateTTL already rejected non-positive or non-integer values)
|
|
88
|
+
if (ttlDays !== undefined) {
|
|
75
89
|
updateExpressionParts.push('ttl = :ttl');
|
|
76
90
|
expressionAttributeValues[':ttl'] = (0, shared_1.calculateTTLTimestamp)(ttlDays);
|
|
77
91
|
}
|
|
@@ -87,7 +101,7 @@ const putOperationAction = async (params) => {
|
|
|
87
101
|
ExpressionAttributeNames: expressionAttributeNames,
|
|
88
102
|
ExpressionAttributeValues: expressionAttributeValues,
|
|
89
103
|
});
|
|
90
|
-
});
|
|
104
|
+
}, { signal });
|
|
91
105
|
};
|
|
92
106
|
exports.putOperationAction = putOperationAction;
|
|
93
107
|
//# sourceMappingURL=put-operation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"put-operation.js","sourceRoot":"","sources":["../../../src/store/actions/put-operation.ts"],"names":[],"mappings":";;;AAAA,iDAAyC;AAEzC,yCAAqD;AAErD,oCASkB;AAElB;;;;;GAKG;AACI,MAAM,kBAAkB,GAAG,KAAK,EAAE,MAAgC,EAAiB,EAAE;IAC1F,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"put-operation.js","sourceRoot":"","sources":["../../../src/store/actions/put-operation.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-operation.d.ts","sourceRoot":"","sources":["../../../src/store/actions/search-operation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAGlE,OAAO,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAUvD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,2BAA2B,KAClC,OAAO,CAAC,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"search-operation.d.ts","sourceRoot":"","sources":["../../../src/store/actions/search-operation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAGlE,OAAO,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAUvD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,2BAA2B,KAClC,OAAO,CAAC,UAAU,EAAE,CAiKtB,CAAC"}
|
|
@@ -17,7 +17,7 @@ const utils_2 = require("../utils");
|
|
|
17
17
|
* @throws Error if the operation fails or validation fails
|
|
18
18
|
*/
|
|
19
19
|
const searchOperationAction = async (params) => {
|
|
20
|
-
const { client, embedding, memoryTableName, userId, op } = params;
|
|
20
|
+
const { client, embedding, memoryTableName, userId, op, fallbackToLexicalOnEmbeddingFailure = false, signal, } = params;
|
|
21
21
|
const limit = op.limit ?? 100;
|
|
22
22
|
const offset = op.offset ?? 0;
|
|
23
23
|
// Validate inputs
|
|
@@ -39,8 +39,13 @@ const searchOperationAction = async (params) => {
|
|
|
39
39
|
// Build KeyConditionExpression
|
|
40
40
|
let keyConditionExpression = 'user_id = :uid';
|
|
41
41
|
if (namespacePrefix) {
|
|
42
|
-
// Use begins_with on namespace_key for hierarchical search
|
|
43
|
-
|
|
42
|
+
// Use begins_with on namespace_key for hierarchical search. NOTE: we do NOT
|
|
43
|
+
// append a separator — `namespace_key` is `<nsPath>#<key>`, so appending "#"
|
|
44
|
+
// would miss sub-namespaces ("users/alice#x" doesn't begin with "users#"),
|
|
45
|
+
// and appending "/" would miss exact matches. Raw prefix is over-inclusive
|
|
46
|
+
// (`users` also matches `users_v2`) but the in-memory ordering guarantees
|
|
47
|
+
// correctness; the spurious rows are negligible in practice.
|
|
48
|
+
expressionAttributeValues[':nsp'] = namespacePrefix;
|
|
44
49
|
keyConditionExpression += ' AND begins_with(namespace_key, :nsp)';
|
|
45
50
|
}
|
|
46
51
|
queryParams.KeyConditionExpression = keyConditionExpression;
|
|
@@ -59,9 +64,14 @@ const searchOperationAction = async (params) => {
|
|
|
59
64
|
// DynamoDB page. For non-semantic queries we keep the original capped fetch.
|
|
60
65
|
const isSemanticSearch = !!op.query && !!embedding;
|
|
61
66
|
const fetchTarget = isSemanticSearch ? undefined : limit + offset;
|
|
67
|
+
if (op.query && !embedding) {
|
|
68
|
+
// User asked for text search but no embedding is configured — the query is
|
|
69
|
+
// effectively dropped. Warn so callers aren't surprised by unfiltered results.
|
|
70
|
+
(0, utils_1.getLogger)().warn('search operation received `query` but no embedding is configured on the store; ' +
|
|
71
|
+
'text search is skipped and results reflect only filter/namespace matches');
|
|
72
|
+
}
|
|
62
73
|
const items = [];
|
|
63
74
|
let lastEvaluatedKey;
|
|
64
|
-
let scannedCount = 0;
|
|
65
75
|
let iterationCount = 0;
|
|
66
76
|
// Execute a query with retry logic and safety limits
|
|
67
77
|
do {
|
|
@@ -70,17 +80,29 @@ const searchOperationAction = async (params) => {
|
|
|
70
80
|
if (iterationCount > utils_2.ValidationConstants.MAX_LOOP_ITERATIONS) {
|
|
71
81
|
throw new Error('Search operation exceeded maximum iteration limit');
|
|
72
82
|
}
|
|
73
|
-
|
|
83
|
+
// Size each page based on items still needed (items.length, not ScannedCount).
|
|
84
|
+
// ScannedCount grows even for filtered-out rows, so gating by it can terminate
|
|
85
|
+
// the loop early when a FilterExpression is active.
|
|
86
|
+
queryParams.Limit = fetchTarget ? Math.max(1, fetchTarget - items.length) : undefined;
|
|
74
87
|
if (lastEvaluatedKey) {
|
|
75
88
|
queryParams.ExclusiveStartKey = lastEvaluatedKey;
|
|
76
89
|
}
|
|
77
90
|
const response = await (0, utils_2.withDynamoDBRetry)(async () => {
|
|
78
91
|
return await client.query(queryParams);
|
|
79
|
-
});
|
|
80
|
-
scannedCount += response.ScannedCount ?? 0;
|
|
92
|
+
}, { signal });
|
|
81
93
|
if (response.Items && response.Items.length > 0) {
|
|
82
|
-
//
|
|
94
|
+
// Memory cap: non-semantic search throws (hard fail, surfaces to caller).
|
|
95
|
+
// Semantic search logs a warning and returns a partial (possibly suboptimal)
|
|
96
|
+
// ranked corpus instead — better than nothing for a best-effort relevance feature.
|
|
83
97
|
if (items.length + response.Items.length > utils_2.ValidationConstants.MAX_TOTAL_ITEMS_IN_MEMORY) {
|
|
98
|
+
if (isSemanticSearch) {
|
|
99
|
+
(0, utils_1.getLogger)().warn(`Semantic search corpus truncated at ${utils_2.ValidationConstants.MAX_TOTAL_ITEMS_IN_MEMORY} items — ` +
|
|
100
|
+
`results may not include the most relevant matches`);
|
|
101
|
+
const remaining = utils_2.ValidationConstants.MAX_TOTAL_ITEMS_IN_MEMORY - items.length;
|
|
102
|
+
if (remaining > 0)
|
|
103
|
+
items.push(...response.Items.slice(0, remaining));
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
84
106
|
throw new Error('Search operation exceeded maximum items in memory limit');
|
|
85
107
|
}
|
|
86
108
|
items.push(...response.Items);
|
|
@@ -90,18 +112,12 @@ const searchOperationAction = async (params) => {
|
|
|
90
112
|
break;
|
|
91
113
|
if (fetchTarget && items.length >= fetchTarget)
|
|
92
114
|
break;
|
|
93
|
-
if (fetchTarget && scannedCount >= fetchTarget)
|
|
94
|
-
break;
|
|
95
115
|
} while (lastEvaluatedKey);
|
|
96
|
-
// Warn if semantic search corpus was truncated
|
|
97
|
-
if (isSemanticSearch && lastEvaluatedKey) {
|
|
98
|
-
(0, utils_1.getLogger)().warn(`Semantic search corpus truncated at ${utils_2.ValidationConstants.MAX_TOTAL_ITEMS_IN_MEMORY} items — results may not include the most relevant matches`);
|
|
99
|
-
}
|
|
100
116
|
if (items.length > 0) {
|
|
101
117
|
let paginatedItems;
|
|
102
118
|
if (isSemanticSearch) {
|
|
103
119
|
// Rank the ENTIRE corpus by similarity, then paginate
|
|
104
|
-
const ranked = await applySemanticSearch(items, op.query, embedding);
|
|
120
|
+
const ranked = await applySemanticSearch(items, op.query, embedding, fallbackToLexicalOnEmbeddingFailure);
|
|
105
121
|
paginatedItems = ranked.slice(offset, offset + limit);
|
|
106
122
|
}
|
|
107
123
|
else {
|
|
@@ -120,12 +136,27 @@ const searchOperationAction = async (params) => {
|
|
|
120
136
|
};
|
|
121
137
|
exports.searchOperationAction = searchOperationAction;
|
|
122
138
|
/**
|
|
123
|
-
* Apply semantic search using vector embeddings and cosine similarity
|
|
124
|
-
*
|
|
139
|
+
* Apply semantic search using vector embeddings and cosine similarity.
|
|
140
|
+
*
|
|
141
|
+
* Fail-closed by default: an `embedQuery()` failure propagates to the caller so
|
|
142
|
+
* they know the returned ranking is not what was requested. Pass
|
|
143
|
+
* `fallbackToLexical = true` to opt in to the legacy fail-open behavior where
|
|
144
|
+
* embedding errors are logged and the raw, unranked items are returned.
|
|
125
145
|
*/
|
|
126
|
-
async function applySemanticSearch(items, query, embedding) {
|
|
146
|
+
async function applySemanticSearch(items, query, embedding, fallbackToLexical) {
|
|
147
|
+
let queryEmbedding;
|
|
148
|
+
try {
|
|
149
|
+
queryEmbedding = await embedding.embedQuery(query);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (!fallbackToLexical) {
|
|
153
|
+
// Fail-closed: surface the failure so the caller can retry or degrade explicitly.
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
(0, utils_1.getLogger)().warn('Semantic search embedding failed — returning unranked results (fallbackToLexicalOnEmbeddingFailure=true):', error);
|
|
157
|
+
return items;
|
|
158
|
+
}
|
|
127
159
|
try {
|
|
128
|
-
const queryEmbedding = await embedding.embedQuery(query);
|
|
129
160
|
const itemsWithScores = items
|
|
130
161
|
.map((item) => {
|
|
131
162
|
if (!item.embedding || !Array.isArray(item.embedding) || item.embedding.length === 0) {
|
|
@@ -147,8 +178,10 @@ async function applySemanticSearch(items, query, embedding) {
|
|
|
147
178
|
return itemsWithScores.map((result) => result.item);
|
|
148
179
|
}
|
|
149
180
|
catch (error) {
|
|
150
|
-
|
|
151
|
-
|
|
181
|
+
if (!fallbackToLexical) {
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
(0, utils_1.getLogger)().warn('Semantic search ranking failed — returning unranked results (fallbackToLexicalOnEmbeddingFailure=true):', error);
|
|
152
185
|
return items;
|
|
153
186
|
}
|
|
154
187
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-operation.js","sourceRoot":"","sources":["../../../src/store/actions/search-operation.ts"],"names":[],"mappings":";;;AAIA,8CAA+C;AAE/C,oCAOkB;AAElB;;;;;;;;;;;;GAYG;AACI,MAAM,qBAAqB,GAAG,KAAK,EACxC,MAAmC,EACZ,EAAE;IACzB,MAAM,
|
|
1
|
+
{"version":3,"file":"search-operation.js","sourceRoot":"","sources":["../../../src/store/actions/search-operation.ts"],"names":[],"mappings":"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"}
|
package/dist/store/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare class DynamoDBStore extends BaseStore {
|
|
|
11
11
|
private readonly memoryTableName;
|
|
12
12
|
private readonly embedding?;
|
|
13
13
|
private readonly ttlDays?;
|
|
14
|
+
private readonly fallbackToLexicalOnEmbeddingFailure;
|
|
14
15
|
private readonly ownsClient;
|
|
15
16
|
/**
|
|
16
17
|
* Create a new DynamoDB store instance
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EACL,SAAS,EAMT,KAAK,SAAS,EACd,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EACL,SAAS,EAMT,KAAK,SAAS,EACd,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAU9B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAGpD,qBAAa,aAAc,SAAQ,SAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;IACvD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,mCAAmC,CAAU;IAC9D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IAErC;;;;;;;;;OASG;gBACS,OAAO,EAAE,oBAAoB;IAazC;;;;OAIG;IACH,OAAO,IAAI,IAAI;IAMf;;;;;;OAMG;IACH,OAAO,CAAC,SAAS;IAQjB;;;;;;;OAOG;IACG,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,EAChC,UAAU,EAAE,EAAE,EACd,MAAM,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;IAmChC;;;;;;OAMG;YACW,YAAY;IAc1B;;;;;OAKG;YACW,YAAY;IAgB1B;;;;;;OAMG;YACW,eAAe;IAgB7B;;;;;;OAMG;YACW,uBAAuB;CAatC"}
|