@mcp-abap-adt/llm-agent 25.0.0 → 27.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/credentials/static.d.ts +9 -0
- package/dist/credentials/static.d.ts.map +1 -0
- package/dist/credentials/static.js +12 -0
- package/dist/credentials/static.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/builder.d.ts +11 -1
- package/dist/interfaces/builder.d.ts.map +1 -1
- package/dist/interfaces/collect-server-descriptors.d.ts +12 -0
- package/dist/interfaces/collect-server-descriptors.d.ts.map +1 -0
- package/dist/interfaces/collect-server-descriptors.js +19 -0
- package/dist/interfaces/collect-server-descriptors.js.map +1 -0
- package/dist/interfaces/index.d.ts +3 -2
- package/dist/interfaces/index.d.ts.map +1 -1
- package/dist/interfaces/index.js.map +1 -1
- package/dist/interfaces/mcp-connection-strategy.d.ts +29 -2
- package/dist/interfaces/mcp-connection-strategy.d.ts.map +1 -1
- package/dist/interfaces/mcp-server-from-factory.d.ts +15 -0
- package/dist/interfaces/mcp-server-from-factory.d.ts.map +1 -0
- package/dist/interfaces/mcp-server-from-factory.js +37 -0
- package/dist/interfaces/mcp-server-from-factory.js.map +1 -0
- package/dist/interfaces/mcp-server.d.ts +24 -0
- package/dist/interfaces/mcp-server.d.ts.map +1 -0
- package/dist/interfaces/mcp-server.js +2 -0
- package/dist/interfaces/mcp-server.js.map +1 -0
- package/dist/interfaces/pipeline-plugin.d.ts +16 -6
- package/dist/interfaces/pipeline-plugin.d.ts.map +1 -1
- package/dist/interfaces/plugin.d.ts +11 -3
- package/dist/interfaces/plugin.d.ts.map +1 -1
- package/dist/interfaces/rag.d.ts +133 -23
- package/dist/interfaces/rag.d.ts.map +1 -1
- package/dist/interfaces/rag.js.map +1 -1
- package/dist/interfaces/tool-catalog.d.ts +4 -2
- package/dist/interfaces/tool-catalog.d.ts.map +1 -1
- package/dist/interfaces/tool-catalog.js.map +1 -1
- package/dist/interfaces/types.d.ts +2 -1
- package/dist/interfaces/types.d.ts.map +1 -1
- package/dist/interfaces/types.js.map +1 -1
- package/dist/llm/base-llm-provider.d.ts +29 -4
- package/dist/llm/base-llm-provider.d.ts.map +1 -1
- package/dist/llm/base-llm-provider.js +45 -9
- package/dist/llm/base-llm-provider.js.map +1 -1
- package/dist/logger/normalise-logger.d.ts +28 -0
- package/dist/logger/normalise-logger.d.ts.map +1 -0
- package/dist/logger/normalise-logger.js +50 -0
- package/dist/logger/normalise-logger.js.map +1 -0
- package/dist/logger/text-logger.d.ts +14 -0
- package/dist/logger/text-logger.d.ts.map +1 -0
- package/dist/logger/text-logger.js +2 -0
- package/dist/logger/text-logger.js.map +1 -0
- package/dist/policy/fallback-llm-call-strategy.d.ts +3 -3
- package/dist/policy/fallback-llm-call-strategy.d.ts.map +1 -1
- package/dist/policy/fallback-llm-call-strategy.js +3 -2
- package/dist/policy/fallback-llm-call-strategy.js.map +1 -1
- package/dist/rag/catalog/index.d.ts +2 -0
- package/dist/rag/catalog/index.d.ts.map +1 -0
- package/dist/rag/catalog/index.js +2 -0
- package/dist/rag/catalog/index.js.map +1 -0
- package/dist/rag/catalog/validation.d.ts +56 -0
- package/dist/rag/catalog/validation.d.ts.map +1 -0
- package/dist/rag/catalog/validation.js +168 -0
- package/dist/rag/catalog/validation.js.map +1 -0
- package/dist/rag/corrections/errors.d.ts +69 -0
- package/dist/rag/corrections/errors.d.ts.map +1 -1
- package/dist/rag/corrections/errors.js +98 -0
- package/dist/rag/corrections/errors.js.map +1 -1
- package/dist/rag/identity-filter.d.ts +19 -0
- package/dist/rag/identity-filter.d.ts.map +1 -0
- package/dist/rag/identity-filter.js +31 -0
- package/dist/rag/identity-filter.js.map +1 -0
- package/dist/rag/in-memory-rag.d.ts +3 -1
- package/dist/rag/in-memory-rag.d.ts.map +1 -1
- package/dist/rag/in-memory-rag.js +20 -15
- package/dist/rag/in-memory-rag.js.map +1 -1
- package/dist/rag/index.d.ts +3 -0
- package/dist/rag/index.d.ts.map +1 -1
- package/dist/rag/index.js +2 -0
- package/dist/rag/index.js.map +1 -1
- package/dist/rag/mcp-tools/index.d.ts +1 -1
- package/dist/rag/mcp-tools/index.d.ts.map +1 -1
- package/dist/rag/mcp-tools/index.js.map +1 -1
- package/dist/rag/mcp-tools/rag-collection-tools.d.ts +36 -5
- package/dist/rag/mcp-tools/rag-collection-tools.d.ts.map +1 -1
- package/dist/rag/mcp-tools/rag-collection-tools.js +128 -54
- package/dist/rag/mcp-tools/rag-collection-tools.js.map +1 -1
- package/dist/rag/providers/base-provider.d.ts +8 -6
- package/dist/rag/providers/base-provider.d.ts.map +1 -1
- package/dist/rag/providers/base-provider.js +18 -0
- package/dist/rag/providers/base-provider.js.map +1 -1
- package/dist/rag/providers/in-memory-rag-provider.d.ts +11 -8
- package/dist/rag/providers/in-memory-rag-provider.d.ts.map +1 -1
- package/dist/rag/providers/in-memory-rag-provider.js +13 -5
- package/dist/rag/providers/in-memory-rag-provider.js.map +1 -1
- package/dist/rag/providers/vector-rag-provider.d.ts +11 -8
- package/dist/rag/providers/vector-rag-provider.d.ts.map +1 -1
- package/dist/rag/providers/vector-rag-provider.js +13 -5
- package/dist/rag/providers/vector-rag-provider.js.map +1 -1
- package/dist/rag/registry/index.d.ts +1 -0
- package/dist/rag/registry/index.d.ts.map +1 -1
- package/dist/rag/registry/index.js +1 -0
- package/dist/rag/registry/index.js.map +1 -1
- package/dist/rag/registry/simple-rag-registry.d.ts +90 -15
- package/dist/rag/registry/simple-rag-registry.d.ts.map +1 -1
- package/dist/rag/registry/simple-rag-registry.js +331 -57
- package/dist/rag/registry/simple-rag-registry.js.map +1 -1
- package/dist/rag/registry/store-key.d.ts +15 -0
- package/dist/rag/registry/store-key.d.ts.map +1 -0
- package/dist/rag/registry/store-key.js +25 -0
- package/dist/rag/registry/store-key.js.map +1 -0
- package/dist/rag/search-strategy.d.ts +9 -0
- package/dist/rag/search-strategy.d.ts.map +1 -1
- package/dist/rag/search-strategy.js +49 -22
- package/dist/rag/search-strategy.js.map +1 -1
- package/dist/rag/tokenizer.d.ts +17 -0
- package/dist/rag/tokenizer.d.ts.map +1 -0
- package/dist/rag/tokenizer.js +38 -0
- package/dist/rag/tokenizer.js.map +1 -0
- package/dist/rag/vector-rag.d.ts +2 -2
- package/dist/rag/vector-rag.d.ts.map +1 -1
- package/dist/rag/vector-rag.js +29 -21
- package/dist/rag/vector-rag.js.map +1 -1
- package/dist/resilience/embedder-resilience.d.ts +2 -2
- package/dist/resilience/embedder-resilience.d.ts.map +1 -1
- package/dist/resilience/embedder-resilience.js +3 -1
- package/dist/resilience/embedder-resilience.js.map +1 -1
- package/dist/testing/rag-filter-conformance.d.ts +60 -0
- package/dist/testing/rag-filter-conformance.d.ts.map +1 -0
- package/dist/testing/rag-filter-conformance.js +379 -0
- package/dist/testing/rag-filter-conformance.js.map +1 -0
- package/dist/types.d.ts +11 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -1
- package/dist/interfaces/failure-strategy.d.ts +0 -95
- package/dist/interfaces/failure-strategy.d.ts.map +0 -1
- package/dist/interfaces/failure-strategy.js +0 -96
- package/dist/interfaces/failure-strategy.js.map +0 -1
- package/dist/llm/rate-limit.d.ts +0 -165
- package/dist/llm/rate-limit.d.ts.map +0 -1
- package/dist/llm/rate-limit.js +0 -394
- package/dist/llm/rate-limit.js.map +0 -1
- package/dist/resilience/status.d.ts +0 -29
- package/dist/resilience/status.d.ts.map +0 -1
- package/dist/resilience/status.js +0 -51
- package/dist/resilience/status.js.map +0 -1
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conformance kit for the identity filter every `IRag` store must honour.
|
|
3
|
+
*
|
|
4
|
+
* `query(embedding, k, { ragFilter })` may carry `sessionId` and/or `userId`
|
|
5
|
+
* (the pipeline's `rag-query` stage sets them for `scope: 'session' | 'user'`).
|
|
6
|
+
* A store that ignores them lets one user's records surface in another
|
|
7
|
+
* user's context. The contract:
|
|
8
|
+
*
|
|
9
|
+
* - `ragFilter.sessionId` set → only records whose `metadata.sessionId`
|
|
10
|
+
* equals it; a record without `sessionId` is excluded.
|
|
11
|
+
* - `ragFilter.userId` set → the same for `metadata.userId`.
|
|
12
|
+
* - both set → both must match; neither set → no identity filtering.
|
|
13
|
+
* - the filter applies BEFORE top-k: a filtered query still returns up to `k`
|
|
14
|
+
* matching records.
|
|
15
|
+
*
|
|
16
|
+
* The same kit covers the other two filters every store applies:
|
|
17
|
+
*
|
|
18
|
+
* - `ragFilter.namespace` set → only records whose `metadata.namespace`
|
|
19
|
+
* equals it; a record without `namespace` is excluded. Not set → records of
|
|
20
|
+
* every namespace (for a store configured without a namespace of its own).
|
|
21
|
+
* - `metadata.ttl` (epoch seconds) in the past → the record is expired and
|
|
22
|
+
* never returned; a future or absent `ttl` keeps it.
|
|
23
|
+
* - both apply BEFORE top-k too.
|
|
24
|
+
*
|
|
25
|
+
* Framework-agnostic: each case throws (`node:assert`) on a violation, so a
|
|
26
|
+
* store package runs them under its own test runner:
|
|
27
|
+
*
|
|
28
|
+
* ```ts
|
|
29
|
+
* for (const c of ragFilterConformanceCases) {
|
|
30
|
+
* it(c.name, () => c.run(async () => new MyRag({ embedder: conformanceEmbedder() })));
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* Every case asks the factory for a FRESH, empty store and seeds it through
|
|
35
|
+
* `writer().upsertRaw`.
|
|
36
|
+
*/
|
|
37
|
+
import assert from 'node:assert/strict';
|
|
38
|
+
/** Dimension of {@link conformanceEmbedder}'s vectors. */
|
|
39
|
+
export const CONFORMANCE_EMBEDDING_DIM = 64;
|
|
40
|
+
function tokens(text) {
|
|
41
|
+
return text
|
|
42
|
+
.toLowerCase()
|
|
43
|
+
.split(/[^a-z0-9]+/)
|
|
44
|
+
.filter((t) => t.length > 1);
|
|
45
|
+
}
|
|
46
|
+
function hash(s) {
|
|
47
|
+
let h = 2166136261;
|
|
48
|
+
for (const ch of s) {
|
|
49
|
+
h ^= ch.charCodeAt(0);
|
|
50
|
+
h = Math.imul(h, 16777619);
|
|
51
|
+
}
|
|
52
|
+
return h >>> 0;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Deterministic bag-of-words embedder: every token lands in one of
|
|
56
|
+
* {@link CONFORMANCE_EMBEDDING_DIM} buckets, and the vector is L2-normalised.
|
|
57
|
+
* Texts that share tokens are close; texts that share none are orthogonal —
|
|
58
|
+
* which the top-k case relies on, and which keeps the conformance texts far
|
|
59
|
+
* apart enough that no store's near-duplicate merge folds two records.
|
|
60
|
+
*/
|
|
61
|
+
export function conformanceEmbedder() {
|
|
62
|
+
return {
|
|
63
|
+
async embed(text) {
|
|
64
|
+
const v = new Array(CONFORMANCE_EMBEDDING_DIM).fill(0);
|
|
65
|
+
for (const t of tokens(text))
|
|
66
|
+
v[hash(t) % CONFORMANCE_EMBEDDING_DIM] += 1;
|
|
67
|
+
const norm = Math.sqrt(v.reduce((s, x) => s + x * x, 0));
|
|
68
|
+
// A zero vector breaks cosine distance in real backends.
|
|
69
|
+
if (norm === 0) {
|
|
70
|
+
v[0] = 1;
|
|
71
|
+
return { vector: v };
|
|
72
|
+
}
|
|
73
|
+
return { vector: v.map((x) => x / norm) };
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async function seed(rag, records) {
|
|
78
|
+
const writer = rag.writer?.();
|
|
79
|
+
if (!writer)
|
|
80
|
+
throw new Error('store under test exposes no writer()');
|
|
81
|
+
for (const r of records) {
|
|
82
|
+
const res = await writer.upsertRaw(r.id, r.text, r.metadata);
|
|
83
|
+
if (!res.ok)
|
|
84
|
+
throw res.error;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async function queryIds(rag, text, k, ragFilter) {
|
|
88
|
+
const embedder = conformanceEmbedder();
|
|
89
|
+
const res = await rag.query({
|
|
90
|
+
text,
|
|
91
|
+
toVector: async () => (await embedder.embed(text)).vector,
|
|
92
|
+
}, k, ragFilter ? { ragFilter } : undefined);
|
|
93
|
+
if (!res.ok)
|
|
94
|
+
throw res.error;
|
|
95
|
+
return res.value.map((r) => String(r.metadata.id)).sort();
|
|
96
|
+
}
|
|
97
|
+
const Q = 'quarterly revenue forecast';
|
|
98
|
+
export const ragFilterConformanceCases = [
|
|
99
|
+
{
|
|
100
|
+
name: 'sessionId filter isolates two sessions',
|
|
101
|
+
async run(makeStore) {
|
|
102
|
+
const rag = await makeStore();
|
|
103
|
+
await seed(rag, [
|
|
104
|
+
{
|
|
105
|
+
id: 's1-a',
|
|
106
|
+
text: 'alpha harbour lighthouse',
|
|
107
|
+
metadata: { sessionId: 's1' },
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
id: 's2-a',
|
|
111
|
+
text: 'bravo mountain glacier',
|
|
112
|
+
metadata: { sessionId: 's2' },
|
|
113
|
+
},
|
|
114
|
+
]);
|
|
115
|
+
assert.deepEqual(await queryIds(rag, Q, 10, { sessionId: 's1' }), [
|
|
116
|
+
's1-a',
|
|
117
|
+
]);
|
|
118
|
+
assert.deepEqual(await queryIds(rag, Q, 10, { sessionId: 's2' }), [
|
|
119
|
+
's2-a',
|
|
120
|
+
]);
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: 'userId filter isolates two users',
|
|
125
|
+
async run(makeStore) {
|
|
126
|
+
const rag = await makeStore();
|
|
127
|
+
await seed(rag, [
|
|
128
|
+
{
|
|
129
|
+
id: 'u1-a',
|
|
130
|
+
text: 'charlie desert oasis',
|
|
131
|
+
metadata: { userId: 'u1' },
|
|
132
|
+
},
|
|
133
|
+
{ id: 'u2-a', text: 'delta forest canopy', metadata: { userId: 'u2' } },
|
|
134
|
+
]);
|
|
135
|
+
assert.deepEqual(await queryIds(rag, Q, 10, { userId: 'u1' }), ['u1-a']);
|
|
136
|
+
assert.deepEqual(await queryIds(rag, Q, 10, { userId: 'u2' }), ['u2-a']);
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: 'sessionId and userId together must both match',
|
|
141
|
+
async run(makeStore) {
|
|
142
|
+
const rag = await makeStore();
|
|
143
|
+
await seed(rag, [
|
|
144
|
+
{
|
|
145
|
+
id: 's1u1',
|
|
146
|
+
text: 'echo river delta',
|
|
147
|
+
metadata: { sessionId: 's1', userId: 'u1' },
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: 's1u2',
|
|
151
|
+
text: 'foxtrot volcano crater',
|
|
152
|
+
metadata: { sessionId: 's1', userId: 'u2' },
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
id: 's2u1',
|
|
156
|
+
text: 'golf tundra permafrost',
|
|
157
|
+
metadata: { sessionId: 's2', userId: 'u1' },
|
|
158
|
+
},
|
|
159
|
+
]);
|
|
160
|
+
assert.deepEqual(await queryIds(rag, Q, 10, { sessionId: 's1', userId: 'u1' }), ['s1u1']);
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: 'no identity filter returns records of every session and user',
|
|
165
|
+
async run(makeStore) {
|
|
166
|
+
const rag = await makeStore();
|
|
167
|
+
await seed(rag, [
|
|
168
|
+
{
|
|
169
|
+
id: 's1-a',
|
|
170
|
+
text: 'hotel savanna acacia',
|
|
171
|
+
metadata: { sessionId: 's1', userId: 'u1' },
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: 's2-a',
|
|
175
|
+
text: 'india reef coral',
|
|
176
|
+
metadata: { sessionId: 's2', userId: 'u2' },
|
|
177
|
+
},
|
|
178
|
+
]);
|
|
179
|
+
assert.deepEqual(await queryIds(rag, Q, 10), ['s1-a', 's2-a']);
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: 'a record without sessionId/userId is excluded under that filter',
|
|
184
|
+
async run(makeStore) {
|
|
185
|
+
const rag = await makeStore();
|
|
186
|
+
await seed(rag, [
|
|
187
|
+
{
|
|
188
|
+
id: 'owned',
|
|
189
|
+
text: 'juliet canyon mesa',
|
|
190
|
+
metadata: { sessionId: 's1', userId: 'u1' },
|
|
191
|
+
},
|
|
192
|
+
{ id: 'unowned', text: 'kilo prairie bison', metadata: {} },
|
|
193
|
+
]);
|
|
194
|
+
assert.deepEqual(await queryIds(rag, Q, 10, { sessionId: 's1' }), [
|
|
195
|
+
'owned',
|
|
196
|
+
]);
|
|
197
|
+
assert.deepEqual(await queryIds(rag, Q, 10, { userId: 'u1' }), ['owned']);
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
name: 'the filter applies before top-k: k counts only matching records',
|
|
202
|
+
async run(makeStore) {
|
|
203
|
+
const rag = await makeStore();
|
|
204
|
+
// The s2 records all share tokens with the query; the s1 record shares
|
|
205
|
+
// none, so an unfiltered top-1 is always an s2 record.
|
|
206
|
+
await seed(rag, [
|
|
207
|
+
{
|
|
208
|
+
id: 's2-a',
|
|
209
|
+
text: 'quarterly revenue forecast europe',
|
|
210
|
+
metadata: { sessionId: 's2' },
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
id: 's2-b',
|
|
214
|
+
text: 'quarterly revenue forecast asia',
|
|
215
|
+
metadata: { sessionId: 's2' },
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
id: 's2-c',
|
|
219
|
+
text: 'quarterly revenue forecast americas',
|
|
220
|
+
metadata: { sessionId: 's2' },
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
id: 's1-a',
|
|
224
|
+
text: 'lima penguin iceberg',
|
|
225
|
+
metadata: { sessionId: 's1' },
|
|
226
|
+
},
|
|
227
|
+
]);
|
|
228
|
+
assert.deepEqual(await queryIds(rag, Q, 1, { sessionId: 's1' }), [
|
|
229
|
+
's1-a',
|
|
230
|
+
]);
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
name: 'namespace filter returns only that namespace; none set returns all',
|
|
235
|
+
async run(makeStore) {
|
|
236
|
+
const rag = await makeStore();
|
|
237
|
+
await seed(rag, [
|
|
238
|
+
{
|
|
239
|
+
id: 'ns-a',
|
|
240
|
+
text: 'mike tundra reindeer',
|
|
241
|
+
metadata: { namespace: 'a' },
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
id: 'ns-b',
|
|
245
|
+
text: 'november jungle parrot',
|
|
246
|
+
metadata: { namespace: 'b' },
|
|
247
|
+
},
|
|
248
|
+
{ id: 'ns-none', text: 'oscar steppe falcon', metadata: {} },
|
|
249
|
+
]);
|
|
250
|
+
assert.deepEqual(await queryIds(rag, Q, 10, { namespace: 'a' }), [
|
|
251
|
+
'ns-a',
|
|
252
|
+
]);
|
|
253
|
+
assert.deepEqual(await queryIds(rag, Q, 10, { namespace: 'b' }), [
|
|
254
|
+
'ns-b',
|
|
255
|
+
]);
|
|
256
|
+
assert.deepEqual(await queryIds(rag, Q, 10), ['ns-a', 'ns-b', 'ns-none']);
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
name: 'the namespace filter applies before top-k',
|
|
261
|
+
async run(makeStore) {
|
|
262
|
+
const rag = await makeStore();
|
|
263
|
+
await seed(rag, [
|
|
264
|
+
{
|
|
265
|
+
id: 'b-1',
|
|
266
|
+
text: 'quarterly revenue forecast europe',
|
|
267
|
+
metadata: { namespace: 'b' },
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
id: 'b-2',
|
|
271
|
+
text: 'quarterly revenue forecast asia',
|
|
272
|
+
metadata: { namespace: 'b' },
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
id: 'a-1',
|
|
276
|
+
text: 'papa lagoon flamingo',
|
|
277
|
+
metadata: { namespace: 'a' },
|
|
278
|
+
},
|
|
279
|
+
]);
|
|
280
|
+
assert.deepEqual(await queryIds(rag, Q, 1, { namespace: 'a' }), ['a-1']);
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
name: 'an expired record (metadata.ttl in the past) is never returned',
|
|
285
|
+
async run(makeStore) {
|
|
286
|
+
const rag = await makeStore();
|
|
287
|
+
const now = Math.floor(Date.now() / 1000);
|
|
288
|
+
await seed(rag, [
|
|
289
|
+
{
|
|
290
|
+
id: 'expired',
|
|
291
|
+
text: 'quebec marsh heron',
|
|
292
|
+
metadata: { ttl: now - 3600 },
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
id: 'live',
|
|
296
|
+
text: 'romeo cliff eagle',
|
|
297
|
+
metadata: { ttl: now + 3600 },
|
|
298
|
+
},
|
|
299
|
+
{ id: 'no-ttl', text: 'sierra dune lizard', metadata: {} },
|
|
300
|
+
]);
|
|
301
|
+
assert.deepEqual(await queryIds(rag, Q, 10), ['live', 'no-ttl']);
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
name: 'a negative ttl is in the past, so the record is expired',
|
|
306
|
+
// A store that told "no ttl" apart from "ttl in the past" by `ttl >= 0`
|
|
307
|
+
// let ttl: -1 through as if it had none (found in Qdrant, PR #308).
|
|
308
|
+
async run(makeStore) {
|
|
309
|
+
const rag = await makeStore();
|
|
310
|
+
await seed(rag, [
|
|
311
|
+
{ id: 'negative', text: 'tango reef octopus', metadata: { ttl: -1 } },
|
|
312
|
+
{ id: 'no-ttl', text: 'uniform glade badger', metadata: {} },
|
|
313
|
+
]);
|
|
314
|
+
assert.deepEqual(await queryIds(rag, Q, 10), ['no-ttl']);
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
name: 'expiry applies before top-k',
|
|
319
|
+
async run(makeStore) {
|
|
320
|
+
const rag = await makeStore();
|
|
321
|
+
const now = Math.floor(Date.now() / 1000);
|
|
322
|
+
await seed(rag, [
|
|
323
|
+
{
|
|
324
|
+
id: 'old-1',
|
|
325
|
+
text: 'quarterly revenue forecast europe',
|
|
326
|
+
metadata: { ttl: now - 3600 },
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
id: 'old-2',
|
|
330
|
+
text: 'quarterly revenue forecast asia',
|
|
331
|
+
metadata: { ttl: now - 3600 },
|
|
332
|
+
},
|
|
333
|
+
{ id: 'fresh', text: 'tango pampas rhea', metadata: {} },
|
|
334
|
+
]);
|
|
335
|
+
assert.deepEqual(await queryIds(rag, Q, 1), ['fresh']);
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
name: 'namespace, expiry and identity filters combine',
|
|
340
|
+
async run(makeStore) {
|
|
341
|
+
const rag = await makeStore();
|
|
342
|
+
const now = Math.floor(Date.now() / 1000);
|
|
343
|
+
await seed(rag, [
|
|
344
|
+
{
|
|
345
|
+
id: 'a-live',
|
|
346
|
+
text: 'uniform bayou alligator',
|
|
347
|
+
metadata: { namespace: 'a', sessionId: 's1', ttl: now + 3600 },
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
id: 'a-nottl',
|
|
351
|
+
text: 'victor fjord seal',
|
|
352
|
+
metadata: { namespace: 'a', sessionId: 's1' },
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
id: 'a-expired',
|
|
356
|
+
text: 'whiskey atoll turtle',
|
|
357
|
+
metadata: { namespace: 'a', sessionId: 's1', ttl: now - 3600 },
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
id: 'a-other-session',
|
|
361
|
+
text: 'xray moor grouse',
|
|
362
|
+
metadata: { namespace: 'a', sessionId: 's2' },
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
id: 'b-nottl',
|
|
366
|
+
text: 'yankee taiga lynx',
|
|
367
|
+
metadata: { namespace: 'b', sessionId: 's1' },
|
|
368
|
+
},
|
|
369
|
+
]);
|
|
370
|
+
assert.deepEqual(await queryIds(rag, Q, 10, { namespace: 'a', sessionId: 's1' }), ['a-live', 'a-nottl']);
|
|
371
|
+
assert.deepEqual(await queryIds(rag, Q, 10, { namespace: 'a' }), [
|
|
372
|
+
'a-live',
|
|
373
|
+
'a-nottl',
|
|
374
|
+
'a-other-session',
|
|
375
|
+
]);
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
];
|
|
379
|
+
//# sourceMappingURL=rag-filter-conformance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rag-filter-conformance.js","sourceRoot":"","sources":["../../src/testing/rag-filter-conformance.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -72,8 +72,17 @@ export interface LLMResponse {
|
|
|
72
72
|
usage?: LlmUsage;
|
|
73
73
|
}
|
|
74
74
|
export interface LLMProviderConfig {
|
|
75
|
-
/**
|
|
76
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Which 429 gate this provider's calls share, when the default is not what you
|
|
77
|
+
* meant.
|
|
78
|
+
*
|
|
79
|
+
* A rate limit is per account, so by default two providers holding different
|
|
80
|
+
* credentials get separate gates — see `BaseLLMProvider.credentialScope`. Two
|
|
81
|
+
* providers wrapping the same account in separate credential objects also get
|
|
82
|
+
* separate gates, which is safe but loses the coordination; naming the same
|
|
83
|
+
* scope on both puts them back on one. Not a secret: a label you choose.
|
|
84
|
+
*/
|
|
85
|
+
quotaScope?: string;
|
|
77
86
|
baseURL?: string;
|
|
78
87
|
model?: string;
|
|
79
88
|
temperature?: number;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD,MAAM,WAAW,OAAO;IACtB;;;;;;OAMG;IACH,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC/C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,iGAAiG;IACjG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uFAAuF;IACvF,UAAU,CAAC,EAAE,KAAK,CAAC;QACjB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,UAAU,CAAC;QACjB,QAAQ,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC;KAC/C,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;+EAG2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-abap-adt/llm-agent",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "27.0.1",
|
|
4
4
|
"description": "Core interfaces, types, and lightweight default implementations for LLM agent orchestration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"import": "./dist/index.js",
|
|
12
12
|
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./testing/rag-filter-conformance": {
|
|
15
|
+
"types": "./dist/testing/rag-filter-conformance.d.ts",
|
|
16
|
+
"import": "./dist/testing/rag-filter-conformance.js",
|
|
17
|
+
"default": "./dist/testing/rag-filter-conformance.js"
|
|
13
18
|
}
|
|
14
19
|
},
|
|
15
20
|
"files": [
|
|
@@ -24,6 +29,8 @@
|
|
|
24
29
|
"test": "node --import tsx/esm --test --test-reporter=spec 'src/**/*.test.ts'"
|
|
25
30
|
},
|
|
26
31
|
"dependencies": {
|
|
32
|
+
"@mcp-abap-adt/interfaces-auth": "^1.1.0",
|
|
33
|
+
"@mcp-abap-adt/interfaces-utils": "^1.0.0",
|
|
27
34
|
"zod": "^4.5.4"
|
|
28
35
|
},
|
|
29
36
|
"license": "LGPL-3.0-only",
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* What a provider does when a call fails for a reason nobody named an interval
|
|
3
|
-
* for: a `500`, a `502`, a dropped connection, a socket that answers nothing.
|
|
4
|
-
*
|
|
5
|
-
* The sibling of `IThrottleStrategy`, and deliberately not the same seam.
|
|
6
|
-
* Throttling is the SERVER governing the pace: it returns `429`, it names a
|
|
7
|
-
* delay in `Retry-After`, and the only honest thing to do is observe that
|
|
8
|
-
* delay or report it. Here nobody names anything. A `502` says the request
|
|
9
|
-
* failed; it says nothing at all about when the next one might work.
|
|
10
|
-
*
|
|
11
|
-
* So any waiting here rests on a number, and this library has none to give.
|
|
12
|
-
* How long to wait, and how many times, depends on who is waiting at the other
|
|
13
|
-
* end — a batch job and a caller on a sixty-second connection want opposite
|
|
14
|
-
* things, and the difference is invisible from in here. The consumer decides,
|
|
15
|
-
* the same way it decides about throttling.
|
|
16
|
-
*
|
|
17
|
-
* Two ship:
|
|
18
|
-
*
|
|
19
|
-
* - `ReportFailure` — never waits. The failure goes up as it arrived, and the
|
|
20
|
-
* caller decides. This is what happens when nothing is configured.
|
|
21
|
-
* - `RetryWithBackoff` — the classic policy, with its numbers named by whoever
|
|
22
|
-
* constructs it rather than defaulted in here.
|
|
23
|
-
*/
|
|
24
|
-
/** What the transport said, for a strategy to decide on. */
|
|
25
|
-
export interface FailureContext {
|
|
26
|
-
/** HTTP status, when the failure carried one. */
|
|
27
|
-
status?: number;
|
|
28
|
-
/** Which attempt just failed. 1-based. */
|
|
29
|
-
attempt: number;
|
|
30
|
-
/** How long this call has already spent waiting between attempts. */
|
|
31
|
-
waitedMs: number;
|
|
32
|
-
/** Whether anything was already streamed to the caller before the failure. */
|
|
33
|
-
midStream: boolean;
|
|
34
|
-
/** The failure itself, for a strategy that needs to look closer. */
|
|
35
|
-
error: unknown;
|
|
36
|
-
}
|
|
37
|
-
/** Wait this long, then either try again or give up. */
|
|
38
|
-
export interface FailureDecision {
|
|
39
|
-
waitMs: number;
|
|
40
|
-
retry: boolean;
|
|
41
|
-
/** Why, for the log and for the error the caller finally sees. */
|
|
42
|
-
reason?: string;
|
|
43
|
-
}
|
|
44
|
-
export interface IFailureStrategy {
|
|
45
|
-
readonly name: string;
|
|
46
|
-
decide(ctx: FailureContext): FailureDecision;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Never retry. What happens when nothing is configured.
|
|
50
|
-
*
|
|
51
|
-
* The failure goes up untouched, and the caller — who knows whether anyone is
|
|
52
|
-
* waiting on the other end, and whether the work is worth repeating — decides
|
|
53
|
-
* whether to ask again.
|
|
54
|
-
*/
|
|
55
|
-
export declare class ReportFailure implements IFailureStrategy {
|
|
56
|
-
readonly name = "report-failure";
|
|
57
|
-
decide(): FailureDecision;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Try again a fixed number of times, doubling the wait each time.
|
|
61
|
-
*
|
|
62
|
-
* The policy this library used to install on everyone by default. It still
|
|
63
|
-
* ships, because it is a reasonable thing to want; what changed is that its
|
|
64
|
-
* numbers now belong to whoever writes them down. There are no defaults here
|
|
65
|
-
* on purpose — a default would be this library guessing again, one layer in.
|
|
66
|
-
*
|
|
67
|
-
* `statuses` is the set worth repeating. A `500` or `502` is usually the
|
|
68
|
-
* provider having a bad second; a `400` is the request itself, and repeating
|
|
69
|
-
* it just fails again more slowly. A failure carrying no status is not
|
|
70
|
-
* retried: without one there is nothing to tell a blip from a bug.
|
|
71
|
-
*
|
|
72
|
-
* `midStreamHints` opts into the harder case — a stream that failed after it
|
|
73
|
-
* had already yielded. Retrying that replays the whole stream, so it happens
|
|
74
|
-
* only for failures whose message matches one of these, and never by default.
|
|
75
|
-
*/
|
|
76
|
-
export declare class RetryWithBackoff implements IFailureStrategy {
|
|
77
|
-
readonly name = "retry-with-backoff";
|
|
78
|
-
private readonly attempts;
|
|
79
|
-
private readonly firstWaitMs;
|
|
80
|
-
private readonly statuses;
|
|
81
|
-
private readonly midStreamHints;
|
|
82
|
-
constructor(options: {
|
|
83
|
-
/** How many times to try again after the first failure. */
|
|
84
|
-
attempts: number;
|
|
85
|
-
/** The first wait. Each subsequent one doubles it. */
|
|
86
|
-
firstWaitMs: number;
|
|
87
|
-
/** Statuses worth repeating. */
|
|
88
|
-
statuses: readonly number[];
|
|
89
|
-
/** Message fragments that make a mid-stream failure worth replaying. */
|
|
90
|
-
midStreamHints?: readonly string[];
|
|
91
|
-
});
|
|
92
|
-
decide({ status, attempt, midStream, error, }: FailureContext): FailureDecision;
|
|
93
|
-
private matchesHint;
|
|
94
|
-
}
|
|
95
|
-
//# sourceMappingURL=failure-strategy.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"failure-strategy.d.ts","sourceRoot":"","sources":["../../src/interfaces/failure-strategy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,SAAS,EAAE,OAAO,CAAC;IACnB,oEAAoE;IACpE,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,GAAG,EAAE,cAAc,GAAG,eAAe,CAAC;CAC9C;AAED;;;;;;GAMG;AACH,qBAAa,aAAc,YAAW,gBAAgB;IACpD,QAAQ,CAAC,IAAI,oBAAoB;IAEjC,MAAM,IAAI,eAAe;CAG1B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAiB,YAAW,gBAAgB;IACvD,QAAQ,CAAC,IAAI,wBAAwB;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;IAC/C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoB;gBAEvC,OAAO,EAAE;QACnB,2DAA2D;QAC3D,QAAQ,EAAE,MAAM,CAAC;QACjB,sDAAsD;QACtD,WAAW,EAAE,MAAM,CAAC;QACpB,gCAAgC;QAChC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;QAC5B,wEAAwE;QACxE,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;KACpC;IAOD,MAAM,CAAC,EACL,MAAM,EACN,OAAO,EACP,SAAS,EACT,KAAK,GACN,EAAE,cAAc,GAAG,eAAe;IAuBnC,OAAO,CAAC,WAAW;CAKpB"}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* What a provider does when a call fails for a reason nobody named an interval
|
|
3
|
-
* for: a `500`, a `502`, a dropped connection, a socket that answers nothing.
|
|
4
|
-
*
|
|
5
|
-
* The sibling of `IThrottleStrategy`, and deliberately not the same seam.
|
|
6
|
-
* Throttling is the SERVER governing the pace: it returns `429`, it names a
|
|
7
|
-
* delay in `Retry-After`, and the only honest thing to do is observe that
|
|
8
|
-
* delay or report it. Here nobody names anything. A `502` says the request
|
|
9
|
-
* failed; it says nothing at all about when the next one might work.
|
|
10
|
-
*
|
|
11
|
-
* So any waiting here rests on a number, and this library has none to give.
|
|
12
|
-
* How long to wait, and how many times, depends on who is waiting at the other
|
|
13
|
-
* end — a batch job and a caller on a sixty-second connection want opposite
|
|
14
|
-
* things, and the difference is invisible from in here. The consumer decides,
|
|
15
|
-
* the same way it decides about throttling.
|
|
16
|
-
*
|
|
17
|
-
* Two ship:
|
|
18
|
-
*
|
|
19
|
-
* - `ReportFailure` — never waits. The failure goes up as it arrived, and the
|
|
20
|
-
* caller decides. This is what happens when nothing is configured.
|
|
21
|
-
* - `RetryWithBackoff` — the classic policy, with its numbers named by whoever
|
|
22
|
-
* constructs it rather than defaulted in here.
|
|
23
|
-
*/
|
|
24
|
-
import { isRetryableStatus } from '../resilience/status.js';
|
|
25
|
-
/**
|
|
26
|
-
* Never retry. What happens when nothing is configured.
|
|
27
|
-
*
|
|
28
|
-
* The failure goes up untouched, and the caller — who knows whether anyone is
|
|
29
|
-
* waiting on the other end, and whether the work is worth repeating — decides
|
|
30
|
-
* whether to ask again.
|
|
31
|
-
*/
|
|
32
|
-
export class ReportFailure {
|
|
33
|
-
name = 'report-failure';
|
|
34
|
-
decide() {
|
|
35
|
-
return { waitMs: 0, retry: false, reason: 'reported' };
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Try again a fixed number of times, doubling the wait each time.
|
|
40
|
-
*
|
|
41
|
-
* The policy this library used to install on everyone by default. It still
|
|
42
|
-
* ships, because it is a reasonable thing to want; what changed is that its
|
|
43
|
-
* numbers now belong to whoever writes them down. There are no defaults here
|
|
44
|
-
* on purpose — a default would be this library guessing again, one layer in.
|
|
45
|
-
*
|
|
46
|
-
* `statuses` is the set worth repeating. A `500` or `502` is usually the
|
|
47
|
-
* provider having a bad second; a `400` is the request itself, and repeating
|
|
48
|
-
* it just fails again more slowly. A failure carrying no status is not
|
|
49
|
-
* retried: without one there is nothing to tell a blip from a bug.
|
|
50
|
-
*
|
|
51
|
-
* `midStreamHints` opts into the harder case — a stream that failed after it
|
|
52
|
-
* had already yielded. Retrying that replays the whole stream, so it happens
|
|
53
|
-
* only for failures whose message matches one of these, and never by default.
|
|
54
|
-
*/
|
|
55
|
-
export class RetryWithBackoff {
|
|
56
|
-
name = 'retry-with-backoff';
|
|
57
|
-
attempts;
|
|
58
|
-
firstWaitMs;
|
|
59
|
-
statuses;
|
|
60
|
-
midStreamHints;
|
|
61
|
-
constructor(options) {
|
|
62
|
-
this.attempts = options.attempts;
|
|
63
|
-
this.firstWaitMs = options.firstWaitMs;
|
|
64
|
-
this.statuses = new Set(options.statuses);
|
|
65
|
-
this.midStreamHints = options.midStreamHints ?? [];
|
|
66
|
-
}
|
|
67
|
-
decide({ status, attempt, midStream, error, }) {
|
|
68
|
-
if (attempt > this.attempts) {
|
|
69
|
-
return { waitMs: 0, retry: false, reason: 'attempts' };
|
|
70
|
-
}
|
|
71
|
-
const worthRepeating = midStream
|
|
72
|
-
? this.matchesHint(error)
|
|
73
|
-
: status !== undefined
|
|
74
|
-
? this.statuses.has(status)
|
|
75
|
-
: // No structured status: fall back to the shared word-boundary match on
|
|
76
|
-
// the message, because every provider rewraps its transport error and
|
|
77
|
-
// the status is often only in the prose by the time it reaches here.
|
|
78
|
-
isRetryableStatus(error, [...this.statuses]);
|
|
79
|
-
if (!worthRepeating) {
|
|
80
|
-
return {
|
|
81
|
-
waitMs: 0,
|
|
82
|
-
retry: false,
|
|
83
|
-
reason: midStream ? 'mid-stream' : 'not-transient',
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
// attempt is 1-based, so the first retry waits exactly firstWaitMs.
|
|
87
|
-
return { waitMs: this.firstWaitMs * 2 ** (attempt - 1), retry: true };
|
|
88
|
-
}
|
|
89
|
-
matchesHint(error) {
|
|
90
|
-
if (this.midStreamHints.length === 0)
|
|
91
|
-
return false;
|
|
92
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
93
|
-
return this.midStreamHints.some((hint) => message.includes(hint));
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
//# sourceMappingURL=failure-strategy.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"failure-strategy.js","sourceRoot":"","sources":["../../src/interfaces/failure-strategy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AA6B5D;;;;;;GAMG;AACH,MAAM,OAAO,aAAa;IACf,IAAI,GAAG,gBAAgB,CAAC;IAEjC,MAAM;QACJ,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACzD,CAAC;CACF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,gBAAgB;IAClB,IAAI,GAAG,oBAAoB,CAAC;IACpB,QAAQ,CAAS;IACjB,WAAW,CAAS;IACpB,QAAQ,CAAsB;IAC9B,cAAc,CAAoB;IAEnD,YAAY,OASX;QACC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC;IACrD,CAAC;IAED,MAAM,CAAC,EACL,MAAM,EACN,OAAO,EACP,SAAS,EACT,KAAK,GACU;QACf,IAAI,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5B,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QACzD,CAAC;QACD,MAAM,cAAc,GAAG,SAAS;YAC9B,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;YACzB,CAAC,CAAC,MAAM,KAAK,SAAS;gBACpB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;gBAC3B,CAAC,CAAC,uEAAuE;oBACvE,sEAAsE;oBACtE,qEAAqE;oBACrE,iBAAiB,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnD,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,OAAO;gBACL,MAAM,EAAE,CAAC;gBACT,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,eAAe;aACnD,CAAC;QACJ,CAAC;QACD,oEAAoE;QACpE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,WAAW,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACxE,CAAC;IAEO,WAAW,CAAC,KAAc;QAChC,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACnD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IACpE,CAAC;CACF"}
|