@carlonicora/nestjs-neo4jsonapi 2.7.2 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/graph.creator/services/graph.creator.service.d.ts +82 -0
- package/dist/agents/graph.creator/services/graph.creator.service.d.ts.map +1 -1
- package/dist/agents/graph.creator/services/graph.creator.service.js +43 -10
- package/dist/agents/graph.creator/services/graph.creator.service.js.map +1 -1
- package/dist/agents/index.d.ts +1 -1
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +7 -1
- package/dist/agents/index.js.map +1 -1
- package/dist/config/base.config.d.ts.map +1 -1
- package/dist/config/base.config.js +4 -0
- package/dist/config/base.config.js.map +1 -1
- package/dist/config/interfaces/config.ai.interface.d.ts +5 -0
- package/dist/config/interfaces/config.ai.interface.d.ts.map +1 -1
- package/dist/config/interfaces/config.prompts.interface.d.ts +15 -0
- package/dist/config/interfaces/config.prompts.interface.d.ts.map +1 -1
- package/dist/core/llm/index.d.ts +2 -0
- package/dist/core/llm/index.d.ts.map +1 -1
- package/dist/core/llm/index.js +2 -0
- package/dist/core/llm/index.js.map +1 -1
- package/dist/core/llm/interfaces/ai-candidate.interface.d.ts +32 -0
- package/dist/core/llm/interfaces/ai-candidate.interface.d.ts.map +1 -0
- package/dist/core/llm/interfaces/ai-candidate.interface.js +15 -0
- package/dist/core/llm/interfaces/ai-candidate.interface.js.map +1 -0
- package/dist/core/llm/llm.module.d.ts.map +1 -1
- package/dist/core/llm/llm.module.js +6 -1
- package/dist/core/llm/llm.module.js.map +1 -1
- package/dist/core/llm/services/ai-connection-resolver.service.d.ts +107 -0
- package/dist/core/llm/services/ai-connection-resolver.service.d.ts.map +1 -0
- package/dist/core/llm/services/ai-connection-resolver.service.js +329 -0
- package/dist/core/llm/services/ai-connection-resolver.service.js.map +1 -0
- package/dist/core/llm/services/embedder.service.d.ts +21 -0
- package/dist/core/llm/services/embedder.service.d.ts.map +1 -1
- package/dist/core/llm/services/embedder.service.js +52 -3
- package/dist/core/llm/services/embedder.service.js.map +1 -1
- package/dist/core/llm/services/llm.service.d.ts +65 -18
- package/dist/core/llm/services/llm.service.d.ts.map +1 -1
- package/dist/core/llm/services/llm.service.js +214 -70
- package/dist/core/llm/services/llm.service.js.map +1 -1
- package/dist/core/llm/services/model.service.d.ts +79 -2
- package/dist/core/llm/services/model.service.d.ts.map +1 -1
- package/dist/core/llm/services/model.service.js +289 -31
- package/dist/core/llm/services/model.service.js.map +1 -1
- package/dist/core/llm/services/vision.llm.service.d.ts +25 -1
- package/dist/core/llm/services/vision.llm.service.d.ts.map +1 -1
- package/dist/core/llm/services/vision.llm.service.js +74 -33
- package/dist/core/llm/services/vision.llm.service.js.map +1 -1
- package/dist/foundations/ai-connection/ai-connection.module.d.ts +5 -0
- package/dist/foundations/ai-connection/ai-connection.module.d.ts.map +1 -0
- package/dist/foundations/ai-connection/ai-connection.module.js +37 -0
- package/dist/foundations/ai-connection/ai-connection.module.js.map +1 -0
- package/dist/foundations/ai-connection/controllers/ai-connection.controller.d.ts +32 -0
- package/dist/foundations/ai-connection/controllers/ai-connection.controller.d.ts.map +1 -0
- package/dist/foundations/ai-connection/controllers/ai-connection.controller.js +162 -0
- package/dist/foundations/ai-connection/controllers/ai-connection.controller.js.map +1 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.post.dto.d.ts +41 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.post.dto.d.ts.map +1 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.post.dto.js +189 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.post.dto.js.map +1 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.put.dto.d.ts +42 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.put.dto.d.ts.map +1 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.put.dto.js +179 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.put.dto.js.map +1 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.reorder.dto.d.ts +8 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.reorder.dto.d.ts.map +1 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.reorder.dto.js +38 -0
- package/dist/foundations/ai-connection/dtos/ai-connection.reorder.dto.js.map +1 -0
- package/dist/foundations/ai-connection/entities/ai-connection.d.ts +57 -0
- package/dist/foundations/ai-connection/entities/ai-connection.d.ts.map +1 -0
- package/dist/foundations/ai-connection/entities/ai-connection.js +73 -0
- package/dist/foundations/ai-connection/entities/ai-connection.js.map +1 -0
- package/dist/foundations/ai-connection/entities/ai-connection.meta.d.ts +3 -0
- package/dist/foundations/ai-connection/entities/ai-connection.meta.d.ts.map +1 -0
- package/dist/foundations/ai-connection/entities/ai-connection.meta.js +10 -0
- package/dist/foundations/ai-connection/entities/ai-connection.meta.js.map +1 -0
- package/dist/foundations/ai-connection/index.d.ts +12 -0
- package/dist/foundations/ai-connection/index.d.ts.map +1 -0
- package/dist/foundations/ai-connection/index.js +35 -0
- package/dist/foundations/ai-connection/index.js.map +1 -0
- package/dist/foundations/ai-connection/registry/ai-provider.registry.d.ts +54 -0
- package/dist/foundations/ai-connection/registry/ai-provider.registry.d.ts.map +1 -0
- package/dist/foundations/ai-connection/registry/ai-provider.registry.js +255 -0
- package/dist/foundations/ai-connection/registry/ai-provider.registry.js.map +1 -0
- package/dist/foundations/ai-connection/repositories/ai-connection.repository.d.ts +52 -0
- package/dist/foundations/ai-connection/repositories/ai-connection.repository.d.ts.map +1 -0
- package/dist/foundations/ai-connection/repositories/ai-connection.repository.js +85 -0
- package/dist/foundations/ai-connection/repositories/ai-connection.repository.js.map +1 -0
- package/dist/foundations/ai-connection/services/ai-connection-encryption.service.d.ts +52 -0
- package/dist/foundations/ai-connection/services/ai-connection-encryption.service.d.ts.map +1 -0
- package/dist/foundations/ai-connection/services/ai-connection-encryption.service.js +148 -0
- package/dist/foundations/ai-connection/services/ai-connection-encryption.service.js.map +1 -0
- package/dist/foundations/ai-connection/services/ai-connection.service.d.ts +79 -0
- package/dist/foundations/ai-connection/services/ai-connection.service.d.ts.map +1 -0
- package/dist/foundations/ai-connection/services/ai-connection.service.js +184 -0
- package/dist/foundations/ai-connection/services/ai-connection.service.js.map +1 -0
- package/dist/foundations/foundations.modules.d.ts.map +1 -1
- package/dist/foundations/foundations.modules.js +2 -0
- package/dist/foundations/foundations.modules.js.map +1 -1
- package/dist/foundations/index.d.ts +1 -0
- package/dist/foundations/index.d.ts.map +1 -1
- package/dist/foundations/index.js +1 -0
- package/dist/foundations/index.js.map +1 -1
- package/dist/foundations/tokenusage/services/tokenusage.service.d.ts +29 -0
- package/dist/foundations/tokenusage/services/tokenusage.service.d.ts.map +1 -1
- package/dist/foundations/tokenusage/services/tokenusage.service.js +15 -3
- package/dist/foundations/tokenusage/services/tokenusage.service.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embedder.service.js","sourceRoot":"","sources":["../../../../src/core/llm/services/embedder.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAsE;AACtE,2CAA+C;AAC/C,6CAAwE;AACxE,mDAA2F;AAE3F,2FAAuF;AACvF,oGAAgG;AAChG,oEAAgE;
|
|
1
|
+
{"version":3,"file":"embedder.service.js","sourceRoot":"","sources":["../../../../src/core/llm/services/embedder.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,6 +19,30 @@ export { injectOpenRouterProvider } from "./openrouter-fetch";
|
|
|
19
19
|
* name and message because the concrete class differs per transport.
|
|
20
20
|
*/
|
|
21
21
|
export declare function isTimeoutError(error: unknown): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* True for a failure that means the request never reached a working provider,
|
|
24
|
+
* and is therefore worth another attempt: a DNS/socket-level error code, an
|
|
25
|
+
* HTTP 429 or 5xx, or the message text either of those arrives as.
|
|
26
|
+
*
|
|
27
|
+
* All three are checked because the same failure wears different clothes per
|
|
28
|
+
* transport: undici puts the code on `error.cause.code` behind a bare
|
|
29
|
+
* `TypeError: fetch failed`, the OpenAI SDK puts the status on the error and
|
|
30
|
+
* the code in the message, and LangChain re-wraps both in a plain `Error`.
|
|
31
|
+
*
|
|
32
|
+
* Deliberately NOT transient: a stall that burned its whole deadline
|
|
33
|
+
* ({@link LLMTimeoutError}), a refusal (402/403), a malformed request (400) or
|
|
34
|
+
* a parse failure. Those either already had their retry (`call()` re-issues a
|
|
35
|
+
* timed-out attempt once, escalating the OpenRouter pin) or will fail
|
|
36
|
+
* identically forever. The 429 vocabulary matches the one
|
|
37
|
+
* `VisionLLMService.isRateLimitError` retries on, so the two agree on what a
|
|
38
|
+
* rate limit looks like.
|
|
39
|
+
*
|
|
40
|
+
* Exported as a standalone function (with {@link LLMService} keeping a private
|
|
41
|
+
* method that delegates to it) so the other modality services — which have no
|
|
42
|
+
* `LLMService` dependency and must not grow one — classify a failure by exactly
|
|
43
|
+
* the same rule before failing a connection over to the next candidate.
|
|
44
|
+
*/
|
|
45
|
+
export declare function isTransientNetworkError(err: unknown): boolean;
|
|
22
46
|
/**
|
|
23
47
|
* Thrown when a provider call burns its whole deadline without settling.
|
|
24
48
|
* Distinguishable from a provider error so callers can treat a stall
|
|
@@ -126,24 +150,41 @@ export declare class LLMService {
|
|
|
126
150
|
*/
|
|
127
151
|
private runBounded;
|
|
128
152
|
/**
|
|
129
|
-
*
|
|
130
|
-
* and
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
* All three are checked because the same failure wears different clothes per
|
|
134
|
-
* transport: undici puts the code on `error.cause.code` behind a bare
|
|
135
|
-
* `TypeError: fetch failed`, the OpenAI SDK puts the status on the error and
|
|
136
|
-
* the code in the message, and LangChain re-wraps both in a plain `Error`.
|
|
137
|
-
*
|
|
138
|
-
* Deliberately NOT transient: a stall that burned its whole deadline
|
|
139
|
-
* ({@link LLMTimeoutError}), a refusal (402/403), a malformed request (400) or
|
|
140
|
-
* a parse failure. Those either already had their retry (`call()` re-issues a
|
|
141
|
-
* timed-out attempt once, escalating the OpenRouter pin) or will fail
|
|
142
|
-
* identically forever. The 429 vocabulary matches the one
|
|
143
|
-
* `VisionLLMService.isRateLimitError` retries on, so the two agree on what a
|
|
144
|
-
* rate limit looks like.
|
|
153
|
+
* See the module-level {@link isTransientNetworkError} for the classification
|
|
154
|
+
* rule and why it lives outside the class. Kept as a method because it is part
|
|
155
|
+
* of this service's shape (spec harnesses stub and assert on it) — the
|
|
156
|
+
* unqualified call below resolves to the module function, not to itself.
|
|
145
157
|
*/
|
|
146
158
|
private isTransientNetworkError;
|
|
159
|
+
/**
|
|
160
|
+
* Ordered failover candidates for a chat tier, newest health state applied.
|
|
161
|
+
*
|
|
162
|
+
* EMPTY means "no candidate machinery available" (a `ModelService` double
|
|
163
|
+
* without `getCandidates`, or a resolution failure) — every caller then
|
|
164
|
+
* behaves exactly as it did before failover existed. A resolution failure is
|
|
165
|
+
* logged and swallowed rather than thrown: losing the chain must degrade to
|
|
166
|
+
* the configured tier, never break the call.
|
|
167
|
+
*/
|
|
168
|
+
private resolveCandidates;
|
|
169
|
+
/**
|
|
170
|
+
* Puts the candidate that just failed transiently into its cooldown window, so
|
|
171
|
+
* the next resolution skips it. Best-effort in every direction: no candidate,
|
|
172
|
+
* no candidate-aware `ModelService`, or a throwing registry all leave the call
|
|
173
|
+
* itself untouched — bookkeeping must never turn a retryable failure into a
|
|
174
|
+
* hard one.
|
|
175
|
+
*/
|
|
176
|
+
private markCandidateFailure;
|
|
177
|
+
/**
|
|
178
|
+
* The cost rates to bill this call at, or undefined to keep the config-block
|
|
179
|
+
* rates.
|
|
180
|
+
*
|
|
181
|
+
* ONLY a DB-backed connection supplies rates: an `.env` candidate is the very
|
|
182
|
+
* config block `computeCost` already reads, so passing its numbers back in
|
|
183
|
+
* would be a no-op at best and a rounding difference at worst. A DB connection
|
|
184
|
+
* that prices nothing also returns undefined, so it bills at the tier rate
|
|
185
|
+
* instead of silently costing zero.
|
|
186
|
+
*/
|
|
187
|
+
private ratesForCandidate;
|
|
147
188
|
/**
|
|
148
189
|
* Sleeps the jittered backoff for one transient retry and says so in the log.
|
|
149
190
|
* ±20% jitter so a fleet of workers knocked out by the same DNS blip does not
|
|
@@ -153,13 +194,19 @@ export declare class LLMService {
|
|
|
153
194
|
/**
|
|
154
195
|
* Runs a provider call under {@link runBounded}, retrying it when — and only
|
|
155
196
|
* when — it failed for a transient network reason
|
|
156
|
-
* ({@link isTransientNetworkError}). Two extra attempts, with the
|
|
157
|
-
* jittered waits {@link TRANSIENT_RETRY_WAITS_MS} explains.
|
|
197
|
+
* ({@link isTransientNetworkError}). Two extra attempts by default, with the
|
|
198
|
+
* long jittered waits {@link TRANSIENT_RETRY_WAITS_MS} explains.
|
|
158
199
|
*
|
|
159
200
|
* Owns a FRESH AbortController per attempt: a controller that has already
|
|
160
201
|
* aborted stays aborted forever, so re-using one would make every retry abort
|
|
161
202
|
* before it sent a byte. `work` therefore receives the signal rather than
|
|
162
203
|
* capturing one from the caller.
|
|
204
|
+
*
|
|
205
|
+
* `work` also receives the ATTEMPT INDEX, which is what turns this retry into
|
|
206
|
+
* a failover: `call()` uses it to pick the n-th connection of the chain, so
|
|
207
|
+
* attempt 2 of a 429 storm talks to a different provider instead of knocking
|
|
208
|
+
* on the same closed door. Callers that pass no `options` keep today's budget
|
|
209
|
+
* (three attempts, the two configured waits) exactly.
|
|
163
210
|
*/
|
|
164
211
|
private runWithTransientRetry;
|
|
165
212
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm.service.d.ts","sourceRoot":"","sources":["../../../../src/core/llm/services/llm.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,WAAW,EAA4C,MAAM,0BAA0B,CAAC;AAE5G,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG/C,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAwB,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAqB,MAAM,4BAA4B,CAAC;AAEpF,OAAO,
|
|
1
|
+
{"version":3,"file":"llm.service.d.ts","sourceRoot":"","sources":["../../../../src/core/llm/services/llm.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -48,6 +48,7 @@ var LLMService_1;
|
|
|
48
48
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
49
|
exports.LLMService = exports.LLMTimeoutError = exports.injectOpenRouterProvider = void 0;
|
|
50
50
|
exports.isTimeoutError = isTimeoutError;
|
|
51
|
+
exports.isTransientNetworkError = isTransientNetworkError;
|
|
51
52
|
const openai_compatible_1 = require("@ai-sdk/openai-compatible");
|
|
52
53
|
const messages_1 = require("@langchain/core/messages");
|
|
53
54
|
const prompts_1 = require("@langchain/core/prompts");
|
|
@@ -135,6 +136,65 @@ function isTimeoutError(error) {
|
|
|
135
136
|
name === "APIConnectionTimeoutError" ||
|
|
136
137
|
/aborted due to timeout|timed? ?out|Request was aborted/i.test(message));
|
|
137
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* True for a failure that means the request never reached a working provider,
|
|
141
|
+
* and is therefore worth another attempt: a DNS/socket-level error code, an
|
|
142
|
+
* HTTP 429 or 5xx, or the message text either of those arrives as.
|
|
143
|
+
*
|
|
144
|
+
* All three are checked because the same failure wears different clothes per
|
|
145
|
+
* transport: undici puts the code on `error.cause.code` behind a bare
|
|
146
|
+
* `TypeError: fetch failed`, the OpenAI SDK puts the status on the error and
|
|
147
|
+
* the code in the message, and LangChain re-wraps both in a plain `Error`.
|
|
148
|
+
*
|
|
149
|
+
* Deliberately NOT transient: a stall that burned its whole deadline
|
|
150
|
+
* ({@link LLMTimeoutError}), a refusal (402/403), a malformed request (400) or
|
|
151
|
+
* a parse failure. Those either already had their retry (`call()` re-issues a
|
|
152
|
+
* timed-out attempt once, escalating the OpenRouter pin) or will fail
|
|
153
|
+
* identically forever. The 429 vocabulary matches the one
|
|
154
|
+
* `VisionLLMService.isRateLimitError` retries on, so the two agree on what a
|
|
155
|
+
* rate limit looks like.
|
|
156
|
+
*
|
|
157
|
+
* Exported as a standalone function (with {@link LLMService} keeping a private
|
|
158
|
+
* method that delegates to it) so the other modality services — which have no
|
|
159
|
+
* `LLMService` dependency and must not grow one — classify a failure by exactly
|
|
160
|
+
* the same rule before failing a connection over to the next candidate.
|
|
161
|
+
*/
|
|
162
|
+
function isTransientNetworkError(err) {
|
|
163
|
+
if (err === undefined || err === null)
|
|
164
|
+
return false;
|
|
165
|
+
const candidate = err;
|
|
166
|
+
const cause = candidate.cause;
|
|
167
|
+
const codes = [candidate.code, cause?.code];
|
|
168
|
+
if (codes.some((code) => typeof code === "string" && TRANSIENT_ERROR_CODES.has(code)))
|
|
169
|
+
return true;
|
|
170
|
+
const statuses = [candidate.status, candidate.statusCode, candidate.response?.status, cause?.status];
|
|
171
|
+
if (statuses.some((status) => typeof status === "number" && (status === 429 || (status >= 500 && status <= 599))))
|
|
172
|
+
return true;
|
|
173
|
+
const own = err instanceof Error ? err.message : String(err);
|
|
174
|
+
const causeMessage = cause instanceof Error ? cause.message : "";
|
|
175
|
+
const haystack = `${own} ${causeMessage}`.toLowerCase();
|
|
176
|
+
for (const code of TRANSIENT_ERROR_CODES)
|
|
177
|
+
if (haystack.includes(code.toLowerCase()))
|
|
178
|
+
return true;
|
|
179
|
+
return (haystack.includes("socket hang up") ||
|
|
180
|
+
haystack.includes("fetch failed") ||
|
|
181
|
+
haystack.includes("network error") ||
|
|
182
|
+
haystack.includes("econnaborted") ||
|
|
183
|
+
// 429 / rate limiting — matched as a whole word so a token count never
|
|
184
|
+
// reads as a status code.
|
|
185
|
+
/\b429\b/.test(haystack) ||
|
|
186
|
+
haystack.includes("rate limit") ||
|
|
187
|
+
haystack.includes("resource exhausted") ||
|
|
188
|
+
haystack.includes("too many requests") ||
|
|
189
|
+
// 5xx. Only the codes providers actually emit, again whole-word: a blanket
|
|
190
|
+
// /5\d\d/ would retry "context length 512 exceeded" forever.
|
|
191
|
+
/\b(500|502|503|504|529)\b/.test(haystack) ||
|
|
192
|
+
haystack.includes("internal server error") ||
|
|
193
|
+
haystack.includes("bad gateway") ||
|
|
194
|
+
haystack.includes("service unavailable") ||
|
|
195
|
+
haystack.includes("gateway timeout") ||
|
|
196
|
+
haystack.includes("overloaded"));
|
|
197
|
+
}
|
|
138
198
|
/**
|
|
139
199
|
* Thrown when a provider call burns its whole deadline without settling.
|
|
140
200
|
* Distinguishable from a provider error so callers can treat a stall
|
|
@@ -372,68 +432,95 @@ let LLMService = LLMService_1 = class LLMService {
|
|
|
372
432
|
}
|
|
373
433
|
}
|
|
374
434
|
/**
|
|
375
|
-
*
|
|
376
|
-
* and
|
|
377
|
-
*
|
|
435
|
+
* See the module-level {@link isTransientNetworkError} for the classification
|
|
436
|
+
* rule and why it lives outside the class. Kept as a method because it is part
|
|
437
|
+
* of this service's shape (spec harnesses stub and assert on it) — the
|
|
438
|
+
* unqualified call below resolves to the module function, not to itself.
|
|
439
|
+
*/
|
|
440
|
+
isTransientNetworkError(err) {
|
|
441
|
+
return isTransientNetworkError(err);
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Ordered failover candidates for a chat tier, newest health state applied.
|
|
378
445
|
*
|
|
379
|
-
*
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
*
|
|
446
|
+
* EMPTY means "no candidate machinery available" (a `ModelService` double
|
|
447
|
+
* without `getCandidates`, or a resolution failure) — every caller then
|
|
448
|
+
* behaves exactly as it did before failover existed. A resolution failure is
|
|
449
|
+
* logged and swallowed rather than thrown: losing the chain must degrade to
|
|
450
|
+
* the configured tier, never break the call.
|
|
451
|
+
*/
|
|
452
|
+
resolveCandidates(modelWeight) {
|
|
453
|
+
const resolver = this.modelService;
|
|
454
|
+
if (typeof resolver.getCandidates !== "function")
|
|
455
|
+
return [];
|
|
456
|
+
try {
|
|
457
|
+
return resolver.getCandidates(modelWeight) ?? [];
|
|
458
|
+
}
|
|
459
|
+
catch (error) {
|
|
460
|
+
this.logger.warn(`AI candidate resolution failed — using the configured tier only: ${String(error)}`);
|
|
461
|
+
return [];
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Puts the candidate that just failed transiently into its cooldown window, so
|
|
466
|
+
* the next resolution skips it. Best-effort in every direction: no candidate,
|
|
467
|
+
* no candidate-aware `ModelService`, or a throwing registry all leave the call
|
|
468
|
+
* itself untouched — bookkeeping must never turn a retryable failure into a
|
|
469
|
+
* hard one.
|
|
470
|
+
*/
|
|
471
|
+
markCandidateFailure(candidate) {
|
|
472
|
+
if (!candidate)
|
|
473
|
+
return;
|
|
474
|
+
const resolver = this.modelService;
|
|
475
|
+
if (typeof resolver.notifyCandidateFailure !== "function")
|
|
476
|
+
return;
|
|
477
|
+
try {
|
|
478
|
+
resolver.notifyCandidateFailure(candidate);
|
|
479
|
+
}
|
|
480
|
+
catch (error) {
|
|
481
|
+
this.logger.warn(`Marking AI candidate ${candidate.connectionId} as failed did not succeed: ${String(error)}`);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* The cost rates to bill this call at, or undefined to keep the config-block
|
|
486
|
+
* rates.
|
|
383
487
|
*
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
* a
|
|
387
|
-
*
|
|
388
|
-
*
|
|
389
|
-
* `VisionLLMService.isRateLimitError` retries on, so the two agree on what a
|
|
390
|
-
* rate limit looks like.
|
|
488
|
+
* ONLY a DB-backed connection supplies rates: an `.env` candidate is the very
|
|
489
|
+
* config block `computeCost` already reads, so passing its numbers back in
|
|
490
|
+
* would be a no-op at best and a rounding difference at worst. A DB connection
|
|
491
|
+
* that prices nothing also returns undefined, so it bills at the tier rate
|
|
492
|
+
* instead of silently costing zero.
|
|
391
493
|
*/
|
|
392
|
-
|
|
393
|
-
if (
|
|
394
|
-
return
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
return
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
if (haystack.includes(code.toLowerCase()))
|
|
408
|
-
return true;
|
|
409
|
-
return (haystack.includes("socket hang up") ||
|
|
410
|
-
haystack.includes("fetch failed") ||
|
|
411
|
-
haystack.includes("network error") ||
|
|
412
|
-
haystack.includes("econnaborted") ||
|
|
413
|
-
// 429 / rate limiting — matched as a whole word so a token count never
|
|
414
|
-
// reads as a status code.
|
|
415
|
-
/\b429\b/.test(haystack) ||
|
|
416
|
-
haystack.includes("rate limit") ||
|
|
417
|
-
haystack.includes("resource exhausted") ||
|
|
418
|
-
haystack.includes("too many requests") ||
|
|
419
|
-
// 5xx. Only the codes providers actually emit, again whole-word: a blanket
|
|
420
|
-
// /5\d\d/ would retry "context length 512 exceeded" forever.
|
|
421
|
-
/\b(500|502|503|504|529)\b/.test(haystack) ||
|
|
422
|
-
haystack.includes("internal server error") ||
|
|
423
|
-
haystack.includes("bad gateway") ||
|
|
424
|
-
haystack.includes("service unavailable") ||
|
|
425
|
-
haystack.includes("gateway timeout") ||
|
|
426
|
-
haystack.includes("overloaded"));
|
|
494
|
+
ratesForCandidate(candidate) {
|
|
495
|
+
if (!candidate || candidate.source !== "db")
|
|
496
|
+
return undefined;
|
|
497
|
+
const { inputCostPer1MTokens, outputCostPer1MTokens, cachedInputCostPer1MTokens } = candidate;
|
|
498
|
+
if (inputCostPer1MTokens === undefined &&
|
|
499
|
+
outputCostPer1MTokens === undefined &&
|
|
500
|
+
cachedInputCostPer1MTokens === undefined)
|
|
501
|
+
return undefined;
|
|
502
|
+
// Only the prices the connection actually sets travel: an explicitly
|
|
503
|
+
// undefined key would still have to be reasoned about downstream.
|
|
504
|
+
return {
|
|
505
|
+
...(inputCostPer1MTokens !== undefined ? { inputCostPer1MTokens } : {}),
|
|
506
|
+
...(outputCostPer1MTokens !== undefined ? { outputCostPer1MTokens } : {}),
|
|
507
|
+
...(cachedInputCostPer1MTokens !== undefined ? { cachedInputCostPer1MTokens } : {}),
|
|
508
|
+
};
|
|
427
509
|
}
|
|
428
510
|
/**
|
|
429
511
|
* Sleeps the jittered backoff for one transient retry and says so in the log.
|
|
430
512
|
* ±20% jitter so a fleet of workers knocked out by the same DNS blip does not
|
|
431
513
|
* come back in lockstep and knock it out again.
|
|
432
514
|
*/
|
|
433
|
-
async waitBeforeTransientRetry(label, attempt, error
|
|
434
|
-
|
|
515
|
+
async waitBeforeTransientRetry(label, attempt, error,
|
|
516
|
+
/** Total attempts this run budgets — only the log text uses it. Defaults to today's 3. */
|
|
517
|
+
maxAttempts = TRANSIENT_RETRY_WAITS_MS.length + 1) {
|
|
518
|
+
// The wait index clamps to the LAST configured backoff: a failover chain can
|
|
519
|
+
// budget more attempts than there are configured waits, and every extra one
|
|
520
|
+
// waits the longest wait rather than reading past the end of the array.
|
|
521
|
+
const base = TRANSIENT_RETRY_WAITS_MS[Math.min(attempt, TRANSIENT_RETRY_WAITS_MS.length - 1)];
|
|
435
522
|
const waitMs = Math.round(base * (0.8 + Math.random() * 0.4));
|
|
436
|
-
this.logger.warn(`[${label}] transient network failure on attempt ${attempt + 1}/${
|
|
523
|
+
this.logger.warn(`[${label}] transient network failure on attempt ${attempt + 1}/${maxAttempts} — ` +
|
|
437
524
|
`retrying in ${Math.round(waitMs / 1000)}s: ${error instanceof Error ? error.message : String(error)}`);
|
|
438
525
|
await new Promise((resolve) => {
|
|
439
526
|
const timer = setTimeout(resolve, waitMs);
|
|
@@ -443,27 +530,35 @@ let LLMService = LLMService_1 = class LLMService {
|
|
|
443
530
|
/**
|
|
444
531
|
* Runs a provider call under {@link runBounded}, retrying it when — and only
|
|
445
532
|
* when — it failed for a transient network reason
|
|
446
|
-
* ({@link isTransientNetworkError}). Two extra attempts, with the
|
|
447
|
-
* jittered waits {@link TRANSIENT_RETRY_WAITS_MS} explains.
|
|
533
|
+
* ({@link isTransientNetworkError}). Two extra attempts by default, with the
|
|
534
|
+
* long jittered waits {@link TRANSIENT_RETRY_WAITS_MS} explains.
|
|
448
535
|
*
|
|
449
536
|
* Owns a FRESH AbortController per attempt: a controller that has already
|
|
450
537
|
* aborted stays aborted forever, so re-using one would make every retry abort
|
|
451
538
|
* before it sent a byte. `work` therefore receives the signal rather than
|
|
452
539
|
* capturing one from the caller.
|
|
540
|
+
*
|
|
541
|
+
* `work` also receives the ATTEMPT INDEX, which is what turns this retry into
|
|
542
|
+
* a failover: `call()` uses it to pick the n-th connection of the chain, so
|
|
543
|
+
* attempt 2 of a 429 storm talks to a different provider instead of knocking
|
|
544
|
+
* on the same closed door. Callers that pass no `options` keep today's budget
|
|
545
|
+
* (three attempts, the two configured waits) exactly.
|
|
453
546
|
*/
|
|
454
|
-
async runWithTransientRetry(label, attemptTimeoutMs, work) {
|
|
547
|
+
async runWithTransientRetry(label, attemptTimeoutMs, work, options) {
|
|
548
|
+
const maxAttempts = options?.maxAttempts ?? TRANSIENT_RETRY_WAITS_MS.length + 1;
|
|
455
549
|
for (let attempt = 0;; attempt++) {
|
|
456
550
|
const controller = new AbortController();
|
|
457
551
|
try {
|
|
458
|
-
return await this.runBounded(label, attemptTimeoutMs, controller, () => work(controller.signal));
|
|
552
|
+
return await this.runBounded(label, attemptTimeoutMs, controller, () => work(controller.signal, attempt));
|
|
459
553
|
}
|
|
460
554
|
catch (error) {
|
|
461
|
-
if (attempt >=
|
|
555
|
+
if (attempt >= maxAttempts - 1 || !this.isTransientNetworkError(error))
|
|
462
556
|
throw error;
|
|
557
|
+
options?.onTransientFailure?.(attempt, error);
|
|
463
558
|
// The attempt is over; release whatever socket it may still hold before
|
|
464
559
|
// waiting out the backoff.
|
|
465
560
|
controller.abort();
|
|
466
|
-
await this.waitBeforeTransientRetry(label, attempt, error);
|
|
561
|
+
await this.waitBeforeTransientRetry(label, attempt, error, maxAttempts);
|
|
467
562
|
}
|
|
468
563
|
}
|
|
469
564
|
}
|
|
@@ -490,7 +585,14 @@ let LLMService = LLMService_1 = class LLMService {
|
|
|
490
585
|
* {@link persistUsageOnFailure}, which writes nothing at all: there the
|
|
491
586
|
* provider was never reached, so there is no call to make visible.
|
|
492
587
|
*/
|
|
493
|
-
async persistUsage(params, tokens
|
|
588
|
+
async persistUsage(params, tokens,
|
|
589
|
+
/**
|
|
590
|
+
* Rates of the AI connection that actually served the call — see
|
|
591
|
+
* {@link ratesForCandidate}. Omitted (the default, and always so for
|
|
592
|
+
* `.env`-served calls) the recorder prices the call from the config block,
|
|
593
|
+
* exactly as before.
|
|
594
|
+
*/
|
|
595
|
+
rates) {
|
|
494
596
|
// Attribution is opt-in: the caller decides which entity this usage is
|
|
495
597
|
// recorded against. With no relationship, there is nothing to attribute to,
|
|
496
598
|
// so we skip — the package stays domain-agnostic.
|
|
@@ -498,14 +600,21 @@ let LLMService = LLMService_1 = class LLMService {
|
|
|
498
600
|
return;
|
|
499
601
|
const measured = tokens.input + tokens.output + (tokens.cached ?? 0) > 0;
|
|
500
602
|
try {
|
|
501
|
-
|
|
603
|
+
// Built as a variable rather than inline so `rates` reaches the package
|
|
604
|
+
// TokenUsageService without widening the published
|
|
605
|
+
// `TokenUsageRecorderInterface`: an application recorder that predates
|
|
606
|
+
// per-connection rates simply ignores the extra key and keeps pricing
|
|
607
|
+
// from its own config, which is the correct degradation.
|
|
608
|
+
const usage = {
|
|
502
609
|
tokens,
|
|
503
610
|
type: params.tokenUsageType ?? tokenusage_type_1.TokenUsageType.TextGeneration,
|
|
504
611
|
relationshipId: params.relationshipId,
|
|
505
612
|
relationshipType: params.relationshipType,
|
|
506
613
|
modelWeight: params.modelWeight,
|
|
507
614
|
...(measured ? {} : { applyMinimum: false }),
|
|
508
|
-
|
|
615
|
+
...(rates ? { rates } : {}),
|
|
616
|
+
};
|
|
617
|
+
await (this.tokenUsageRecorder ?? this.tokenUsageService).recordTokenUsage(usage);
|
|
509
618
|
}
|
|
510
619
|
catch (err) {
|
|
511
620
|
this.logger.warn(`TokenUsage persistence failed — continuing: ${String(err)}`);
|
|
@@ -528,10 +637,12 @@ let LLMService = LLMService_1 = class LLMService {
|
|
|
528
637
|
* Never throws (delegates to {@link persistUsage}), so it can sit in a catch
|
|
529
638
|
* block without masking the original error.
|
|
530
639
|
*/
|
|
531
|
-
async persistUsageOnFailure(params, tokens
|
|
640
|
+
async persistUsageOnFailure(params, tokens,
|
|
641
|
+
/** See {@link persistUsage}: rates of the connection that served the call. */
|
|
642
|
+
rates) {
|
|
532
643
|
if (tokens.input + tokens.output + (tokens.cached ?? 0) === 0)
|
|
533
644
|
return;
|
|
534
|
-
await this.persistUsage(params, tokens);
|
|
645
|
+
await this.persistUsage(params, tokens, rates);
|
|
535
646
|
}
|
|
536
647
|
/**
|
|
537
648
|
* Converts AgentMessageType to LangChain BaseMessage
|
|
@@ -805,14 +916,38 @@ let LLMService = LLMService_1 = class LLMService {
|
|
|
805
916
|
// promise settles even if the provider never answers.
|
|
806
917
|
const attemptTimeoutMs = this.attemptTimeoutMs(params.timeout);
|
|
807
918
|
const label = `${params.metadata?.nodeName ?? "llm.call"}:${aiConfig.model}`;
|
|
919
|
+
// The ordered fallback chain for this tier. Empty when no candidate-aware
|
|
920
|
+
// ModelService is present; a single `.env` candidate when nothing is
|
|
921
|
+
// configured in the database — in both cases the retry below is byte-for-byte
|
|
922
|
+
// today's three attempts against one connection.
|
|
923
|
+
const candidates = this.resolveCandidates(modelWeight);
|
|
924
|
+
// Failover on 429/5xx walks the chain: at least today's 3 attempts, one per
|
|
925
|
+
// candidate when the chain is longer, capped at 6 (spec § 2).
|
|
926
|
+
const maxAttempts = Math.min(6, Math.max(TRANSIENT_RETRY_WAITS_MS.length + 1, candidates.length));
|
|
927
|
+
// The candidate the SUCCESSFUL attempt used — it, not the first link of the
|
|
928
|
+
// chain, is what the call is billed at.
|
|
929
|
+
let servingCandidate = candidates[0];
|
|
808
930
|
try {
|
|
809
931
|
// The abort signal now comes from the retry wrapper, which owns a fresh
|
|
810
932
|
// controller per attempt — a reused one would abort every retry instantly.
|
|
811
|
-
const result = await this.runWithTransientRetry(label, attemptTimeoutMs, (signal
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
933
|
+
const result = await this.runWithTransientRetry(label, attemptTimeoutMs, (signal, attempt) => {
|
|
934
|
+
// Attempt n uses candidate n, clamped to the last one: a chain shorter
|
|
935
|
+
// than the attempt budget keeps retrying its final link, which is the
|
|
936
|
+
// `.env` block.
|
|
937
|
+
const candidateIndex = candidates.length > 0 ? Math.min(attempt, candidates.length - 1) : undefined;
|
|
938
|
+
if (candidateIndex !== undefined)
|
|
939
|
+
servingCandidate = candidates[candidateIndex];
|
|
940
|
+
return this._invokeOriginal(params, session, (i, o, c) => {
|
|
941
|
+
totalInput += i;
|
|
942
|
+
totalOutput += o;
|
|
943
|
+
totalCached += c;
|
|
944
|
+
}, (kind) => parseFallbacks.push(kind), (w) => warnings.push(w), { attemptTimeoutMs, signal, label, candidateIndex });
|
|
945
|
+
}, {
|
|
946
|
+
maxAttempts,
|
|
947
|
+
// The candidate that just failed goes into cooldown, so the next
|
|
948
|
+
// resolution — this call's next attempt included — skips it.
|
|
949
|
+
onTransientFailure: (attempt) => this.markCandidateFailure(candidates[Math.min(attempt, candidates.length - 1)]),
|
|
950
|
+
});
|
|
816
951
|
session.close({
|
|
817
952
|
finalStatus: "success",
|
|
818
953
|
totalTokens: { input: totalInput, output: totalOutput, cached: totalCached },
|
|
@@ -824,7 +959,7 @@ let LLMService = LLMService_1 = class LLMService {
|
|
|
824
959
|
relationshipId: params.relationshipId,
|
|
825
960
|
relationshipType: params.relationshipType,
|
|
826
961
|
modelWeight,
|
|
827
|
-
}, { input: totalInput, output: totalOutput, cached: totalCached });
|
|
962
|
+
}, { input: totalInput, output: totalOutput, cached: totalCached }, this.ratesForCandidate(servingCandidate));
|
|
828
963
|
const finalResult = { ...result, modelWeight };
|
|
829
964
|
// Write-through on a miss so the next identical cacheable call hits.
|
|
830
965
|
if (cacheKey && this.cache)
|
|
@@ -851,7 +986,10 @@ let LLMService = LLMService_1 = class LLMService {
|
|
|
851
986
|
relationshipId: params.relationshipId,
|
|
852
987
|
relationshipType: params.relationshipType,
|
|
853
988
|
modelWeight,
|
|
854
|
-
}, { input: totalInput, output: totalOutput, cached: totalCached }
|
|
989
|
+
}, { input: totalInput, output: totalOutput, cached: totalCached },
|
|
990
|
+
// Billed at the LAST candidate tried — the one whose failure ended the
|
|
991
|
+
// call and whose provider charged for whatever it served.
|
|
992
|
+
this.ratesForCandidate(servingCandidate));
|
|
855
993
|
console.error("[LLMService] Error calling LLM:", error);
|
|
856
994
|
// The message text is load-bearing — callers match on "LLM service error:"
|
|
857
995
|
// — so it stays byte-for-byte identical, and the original error rides along
|
|
@@ -870,6 +1008,9 @@ let LLMService = LLMService_1 = class LLMService {
|
|
|
870
1008
|
// `label` is the SAME string the watchdog prints in `runBounded`, threaded
|
|
871
1009
|
// in so a reader can tie an iteration line to the `still pending` lines of
|
|
872
1010
|
// the very same call rather than guessing across two naming schemes.
|
|
1011
|
+
// `candidateIndex` selects which link of the tier's fallback chain builds the
|
|
1012
|
+
// model for THIS attempt; absent (direct callers, tests, no candidate-aware
|
|
1013
|
+
// ModelService) it resolves the first healthy candidate exactly as before.
|
|
873
1014
|
bounds) {
|
|
874
1015
|
const label = bounds?.label ?? "llm.call";
|
|
875
1016
|
// Optional: Validate input parameters against schema
|
|
@@ -902,6 +1043,9 @@ let LLMService = LLMService_1 = class LLMService {
|
|
|
902
1043
|
disableThinking: params.disableThinking,
|
|
903
1044
|
reasoningEffort: params.reasoningEffort,
|
|
904
1045
|
timeoutMs: bounds?.attemptTimeoutMs ?? params.timeout,
|
|
1046
|
+
// Spread rather than always passed: without a chain the argument object
|
|
1047
|
+
// stays exactly the one every existing caller already built.
|
|
1048
|
+
...(bounds?.candidateIndex !== undefined ? { candidateIndex: bounds.candidateIndex } : {}),
|
|
905
1049
|
});
|
|
906
1050
|
// Build config options for the invocation
|
|
907
1051
|
const configOptions = {};
|