@carlonicora/nestjs-neo4jsonapi 2.7.2 → 2.8.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/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/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
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var AiConnectionResolverService_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.AiConnectionResolverService = void 0;
|
|
17
|
+
exports.toCandidate = toCandidate;
|
|
18
|
+
const common_1 = require("@nestjs/common");
|
|
19
|
+
const config_1 = require("@nestjs/config");
|
|
20
|
+
const event_emitter_1 = require("@nestjs/event-emitter");
|
|
21
|
+
const nestjs_cls_1 = require("nestjs-cls");
|
|
22
|
+
const ai_connection_repository_1 = require("../../../foundations/ai-connection/repositories/ai-connection.repository");
|
|
23
|
+
const ai_connection_encryption_service_1 = require("../../../foundations/ai-connection/services/ai-connection-encryption.service");
|
|
24
|
+
const logging_service_1 = require("../../logging/services/logging.service");
|
|
25
|
+
const ai_candidate_interface_1 = require("../interfaces/ai-candidate.interface");
|
|
26
|
+
/** How often the in-memory snapshot is rebuilt from the database. */
|
|
27
|
+
const SNAPSHOT_REFRESH_INTERVAL_MS = 60_000;
|
|
28
|
+
/** Cooldown used when `ai.connectionCooldownMinutes` is missing from config. */
|
|
29
|
+
const DEFAULT_COOLDOWN_MINUTES = 5;
|
|
30
|
+
/** Snapshot key for the chain that applies to every company. */
|
|
31
|
+
const GLOBAL_SCOPE = "global";
|
|
32
|
+
const KNOWN_CONNECTION_TYPES = new Set(ai_candidate_interface_1.AI_CONNECTION_TYPES);
|
|
33
|
+
const asString = (value) => typeof value === "string" && value !== "" ? value : undefined;
|
|
34
|
+
const asNumber = (value) => (typeof value === "number" ? value : undefined);
|
|
35
|
+
const asBoolean = (value) => (typeof value === "boolean" ? value : undefined);
|
|
36
|
+
/**
|
|
37
|
+
* Normalises one `AiConnection` node into the candidate shape `buildChatModel`
|
|
38
|
+
* (and its embedder/transcriber siblings) already consume.
|
|
39
|
+
*
|
|
40
|
+
* Pure on purpose: the decryptor is injected so the caller decides what a
|
|
41
|
+
* decryption failure means. It THROWS when a stored secret cannot be decrypted —
|
|
42
|
+
* {@link AiConnectionResolverService.refreshNow} catches that and skips the
|
|
43
|
+
* connection, so a single unreadable secret never takes the chain down
|
|
44
|
+
* (spec § 5 "Error handling").
|
|
45
|
+
*/
|
|
46
|
+
function toCandidate(connection, decrypt) {
|
|
47
|
+
return {
|
|
48
|
+
source: "db",
|
|
49
|
+
connectionId: connection.id,
|
|
50
|
+
connectionType: connection.connectionType,
|
|
51
|
+
provider: connection.provider,
|
|
52
|
+
apiKey: connection.apiKey ? decrypt(connection.apiKey) : "",
|
|
53
|
+
model: connection.model ?? "",
|
|
54
|
+
url: connection.url ?? "",
|
|
55
|
+
region: connection.region,
|
|
56
|
+
instance: connection.instance,
|
|
57
|
+
apiVersion: connection.apiVersion,
|
|
58
|
+
googleCredentialsBase64: connection.googleCredentialsBase64
|
|
59
|
+
? decrypt(connection.googleCredentialsBase64)
|
|
60
|
+
: undefined,
|
|
61
|
+
allowFallbacks: connection.allowFallbacks,
|
|
62
|
+
reasoningEffort: connection.reasoningEffort,
|
|
63
|
+
maxOutputTokens: connection.maxOutputTokens,
|
|
64
|
+
dimensions: connection.dimensions,
|
|
65
|
+
inputCostPer1MTokens: connection.inputCostPer1MTokens,
|
|
66
|
+
outputCostPer1MTokens: connection.outputCostPer1MTokens,
|
|
67
|
+
cachedInputCostPer1MTokens: connection.cachedInputCostPer1MTokens,
|
|
68
|
+
costPerMinute: connection.costPerMinute,
|
|
69
|
+
costPerPage: connection.costPerPage,
|
|
70
|
+
directUrl: connection.directUrl,
|
|
71
|
+
language: connection.language,
|
|
72
|
+
directFormat: connection.directFormat,
|
|
73
|
+
directProvider: connection.directProvider,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Resolves the ordered fallback chain for an AI connection type.
|
|
78
|
+
*
|
|
79
|
+
* Holds an in-memory snapshot of every enabled `AiConnection` node (decrypted,
|
|
80
|
+
* grouped into chains by `(connectionType, companyId | null)`, ordered by
|
|
81
|
+
* `position`), refreshed at boot, every 60s, and immediately on any admin write
|
|
82
|
+
* in this process (`AI_CONNECTIONS_CHANGED_EVENT`).
|
|
83
|
+
*
|
|
84
|
+
* The snapshot exists because `ModelService.getLLM()` is synchronous and called
|
|
85
|
+
* directly by several library services: resolution must stay a pure sync lookup
|
|
86
|
+
* with no signature ripple (spec § 2).
|
|
87
|
+
*
|
|
88
|
+
* Failure ALWAYS degrades toward today's `.env` behaviour, never toward "no AI"
|
|
89
|
+
* (spec § 5): an empty table, a failed refresh, an undecryptable secret or an
|
|
90
|
+
* unknown connection type all leave the `.env` candidate in place, and nothing
|
|
91
|
+
* on the `resolve()` hot path throws.
|
|
92
|
+
*/
|
|
93
|
+
let AiConnectionResolverService = AiConnectionResolverService_1 = class AiConnectionResolverService {
|
|
94
|
+
constructor(repository, encryption, cls, configService, logger) {
|
|
95
|
+
this.repository = repository;
|
|
96
|
+
this.encryption = encryption;
|
|
97
|
+
this.cls = cls;
|
|
98
|
+
this.configService = configService;
|
|
99
|
+
this.logger = logger;
|
|
100
|
+
/** `${connectionType}|${companyId ?? "global"}` → ordered candidates. */
|
|
101
|
+
this.snapshot = new Map();
|
|
102
|
+
/** connectionId → epoch ms before which the candidate is skipped. */
|
|
103
|
+
this.cooldownUntil = new Map();
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Loads the first snapshot and starts the periodic refresh. Neither is
|
|
107
|
+
* awaited and neither can reject: boot must never depend on the database
|
|
108
|
+
* holding AI connection rows (spec § 5).
|
|
109
|
+
*/
|
|
110
|
+
onModuleInit() {
|
|
111
|
+
void this.refreshNow().catch((error) => this.warn("initial snapshot load failed", error));
|
|
112
|
+
this.refreshTimer = setInterval(() => {
|
|
113
|
+
void this.refreshNow().catch((error) => this.warn("scheduled snapshot refresh failed", error));
|
|
114
|
+
}, SNAPSHOT_REFRESH_INTERVAL_MS);
|
|
115
|
+
// Never hold the process open for a cache refresh.
|
|
116
|
+
this.refreshTimer.unref?.();
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The ordered candidates to try for `type`, best first.
|
|
120
|
+
*
|
|
121
|
+
* Per-company chain when the request's company has one, otherwise the global
|
|
122
|
+
* chain; the `.env` block is ALWAYS appended last. Candidates inside their
|
|
123
|
+
* cooldown window are dropped — unless that empties the list, in which case
|
|
124
|
+
* the full chain is returned anyway (fail-open, spec § 2).
|
|
125
|
+
*
|
|
126
|
+
* Never throws.
|
|
127
|
+
*/
|
|
128
|
+
resolve(type) {
|
|
129
|
+
const candidates = [];
|
|
130
|
+
try {
|
|
131
|
+
const companyId = this.currentCompanyId();
|
|
132
|
+
if (companyId) {
|
|
133
|
+
const scoped = this.snapshot.get(this.chainKey(type, companyId));
|
|
134
|
+
if (scoped?.length)
|
|
135
|
+
candidates.push(...scoped);
|
|
136
|
+
}
|
|
137
|
+
if (candidates.length === 0) {
|
|
138
|
+
const global = this.snapshot.get(this.chainKey(type, undefined));
|
|
139
|
+
if (global?.length)
|
|
140
|
+
candidates.push(...global);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
// A broken CLS/snapshot read degrades to the env candidate alone.
|
|
145
|
+
this.warn(`chain lookup failed for "${type}"`, error);
|
|
146
|
+
candidates.length = 0;
|
|
147
|
+
}
|
|
148
|
+
candidates.push(this.buildEnvCandidate(type));
|
|
149
|
+
const now = Date.now();
|
|
150
|
+
const healthy = candidates.filter((candidate) => (this.cooldownUntil.get(candidate.connectionId) ?? 0) <= now);
|
|
151
|
+
return healthy.length > 0 ? healthy : candidates;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Parks a connection for `ai.connectionCooldownMinutes` after a transient
|
|
155
|
+
* failure (429 / 5xx / network). The `.env` candidate is tracked under
|
|
156
|
+
* `env:<type>` like any other, so a dead env fallback cannot block recovery.
|
|
157
|
+
*/
|
|
158
|
+
markFailure(connectionId) {
|
|
159
|
+
if (!connectionId)
|
|
160
|
+
return;
|
|
161
|
+
this.cooldownUntil.set(connectionId, Date.now() + this.cooldownMinutes * 60_000);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Rebuilds the snapshot from the database. Also the handler for admin writes
|
|
165
|
+
* in this process; other processes catch up at the next scheduled refresh.
|
|
166
|
+
*
|
|
167
|
+
* A read failure keeps the PREVIOUS snapshot — a database blip must not wipe
|
|
168
|
+
* working configuration (spec § 5).
|
|
169
|
+
*/
|
|
170
|
+
async refreshNow() {
|
|
171
|
+
let connections;
|
|
172
|
+
try {
|
|
173
|
+
connections = await this.readConnections();
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
this.warn("snapshot refresh failed — keeping the previous snapshot", error);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const next = new Map();
|
|
180
|
+
const ordered = [...(connections ?? [])].sort((a, b) => (a?.position ?? 0) - (b?.position ?? 0));
|
|
181
|
+
for (const connection of ordered) {
|
|
182
|
+
if (!connection || connection.enabled === false)
|
|
183
|
+
continue;
|
|
184
|
+
if (!KNOWN_CONNECTION_TYPES.has(connection.connectionType)) {
|
|
185
|
+
this.warn(`skipping connection ${connection.id}: unknown connectionType "${connection.connectionType}"`);
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
let candidate;
|
|
189
|
+
try {
|
|
190
|
+
candidate = toCandidate(connection, (value) => this.encryption.decrypt(value));
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
this.warn(`skipping connection ${connection.id}: stored secret could not be decrypted`, error);
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
const key = this.chainKey(candidate.connectionType, connection.companyId);
|
|
197
|
+
const chain = next.get(key);
|
|
198
|
+
if (chain)
|
|
199
|
+
chain.push(candidate);
|
|
200
|
+
else
|
|
201
|
+
next.set(key, [candidate]);
|
|
202
|
+
}
|
|
203
|
+
this.snapshot = next;
|
|
204
|
+
}
|
|
205
|
+
// --- internals ----------------------------------------------------------
|
|
206
|
+
/**
|
|
207
|
+
* Reads every connection inside a CLS context: the refresh runs outside any
|
|
208
|
+
* HTTP request, and the query plumbing reads CLS (`companyId`) unconditionally.
|
|
209
|
+
*/
|
|
210
|
+
readConnections() {
|
|
211
|
+
if (typeof this.cls?.run === "function") {
|
|
212
|
+
return this.cls.run(async () => this.repository.findAllForResolver());
|
|
213
|
+
}
|
|
214
|
+
return this.repository.findAllForResolver();
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* The company of the current request, or undefined when there is none.
|
|
218
|
+
*
|
|
219
|
+
* Optional-call plus a silent catch: the resolver is also used by workers and
|
|
220
|
+
* boot-time code with no CLS context at all, which is an ordinary state and
|
|
221
|
+
* must not log or throw — it simply means "use the global chain".
|
|
222
|
+
*/
|
|
223
|
+
currentCompanyId() {
|
|
224
|
+
try {
|
|
225
|
+
const companyId = this.cls?.get?.("companyId");
|
|
226
|
+
return typeof companyId === "string" && companyId !== "" ? companyId : undefined;
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
chainKey(type, companyId) {
|
|
233
|
+
return `${type}|${companyId ?? GLOBAL_SCOPE}`;
|
|
234
|
+
}
|
|
235
|
+
get aiConfig() {
|
|
236
|
+
try {
|
|
237
|
+
return this.configService?.get("ai");
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
return undefined;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
get cooldownMinutes() {
|
|
244
|
+
// `connectionCooldownMinutes` is added to the `ai` block by the config task;
|
|
245
|
+
// default defensively so this works even when the read returns undefined.
|
|
246
|
+
const ai = this.aiConfig;
|
|
247
|
+
const configured = ai?.connectionCooldownMinutes;
|
|
248
|
+
return typeof configured === "number" && configured > 0 ? configured : DEFAULT_COOLDOWN_MINUTES;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* The `.env` block for a type, mapped field-for-field onto a candidate. This
|
|
252
|
+
* is the final link of every chain and the whole behaviour when the table is
|
|
253
|
+
* empty — with zero `AiConnection` nodes, resolution is byte-for-byte today's.
|
|
254
|
+
*/
|
|
255
|
+
buildEnvCandidate(type) {
|
|
256
|
+
const block = this.envBlockFor(type);
|
|
257
|
+
return {
|
|
258
|
+
source: "env",
|
|
259
|
+
connectionId: `env:${type}`,
|
|
260
|
+
connectionType: type,
|
|
261
|
+
provider: asString(block.provider) ?? "",
|
|
262
|
+
apiKey: asString(block.apiKey) ?? "",
|
|
263
|
+
model: asString(block.model) ?? "",
|
|
264
|
+
url: asString(block.url) ?? "",
|
|
265
|
+
region: asString(block.region),
|
|
266
|
+
instance: asString(block.instance),
|
|
267
|
+
apiVersion: asString(block.apiVersion),
|
|
268
|
+
googleCredentialsBase64: asString(block.googleCredentialsBase64),
|
|
269
|
+
allowFallbacks: asBoolean(block.allowFallbacks),
|
|
270
|
+
reasoningEffort: asString(block.reasoningEffort),
|
|
271
|
+
maxOutputTokens: asNumber(block.maxOutputTokens),
|
|
272
|
+
dimensions: asNumber(block.dimensions),
|
|
273
|
+
inputCostPer1MTokens: asNumber(block.inputCostPer1MTokens),
|
|
274
|
+
outputCostPer1MTokens: asNumber(block.outputCostPer1MTokens),
|
|
275
|
+
cachedInputCostPer1MTokens: asNumber(block.cachedInputCostPer1MTokens),
|
|
276
|
+
costPerMinute: asNumber(block.costPerMinute),
|
|
277
|
+
costPerPage: asNumber(block.costPerPage),
|
|
278
|
+
directUrl: asString(block.directUrl),
|
|
279
|
+
language: asString(block.language),
|
|
280
|
+
directFormat: asString(block.directFormat),
|
|
281
|
+
directProvider: asString(block.directProvider),
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
/** Same block mapping the admin API uses for `meta.envDefaults`. */
|
|
285
|
+
envBlockFor(type) {
|
|
286
|
+
const ai = this.aiConfig;
|
|
287
|
+
if (!ai)
|
|
288
|
+
return {};
|
|
289
|
+
switch (type) {
|
|
290
|
+
case "aiLite":
|
|
291
|
+
return (ai.aiLite ?? {});
|
|
292
|
+
case "aiLarge":
|
|
293
|
+
return (ai.aiLarge ?? {});
|
|
294
|
+
case "vision":
|
|
295
|
+
return (ai.vision ?? {});
|
|
296
|
+
case "audio":
|
|
297
|
+
return (ai.audio ?? {});
|
|
298
|
+
case "embedder":
|
|
299
|
+
return (ai.embedder ?? {});
|
|
300
|
+
case "transcriber":
|
|
301
|
+
return (ai.transcriber ?? {});
|
|
302
|
+
case "documentAi":
|
|
303
|
+
return (ai.documentAi ?? {});
|
|
304
|
+
default:
|
|
305
|
+
return (ai.ai ?? {});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
warn(message, error) {
|
|
309
|
+
const detail = error instanceof Error ? error.message : error !== undefined ? String(error) : undefined;
|
|
310
|
+
this.logger?.warn(detail ? `[AiConnectionResolver] ${message}: ${detail}` : `[AiConnectionResolver] ${message}`, AiConnectionResolverService_1.name);
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
exports.AiConnectionResolverService = AiConnectionResolverService;
|
|
314
|
+
__decorate([
|
|
315
|
+
(0, event_emitter_1.OnEvent)(ai_candidate_interface_1.AI_CONNECTIONS_CHANGED_EVENT),
|
|
316
|
+
__metadata("design:type", Function),
|
|
317
|
+
__metadata("design:paramtypes", []),
|
|
318
|
+
__metadata("design:returntype", Promise)
|
|
319
|
+
], AiConnectionResolverService.prototype, "refreshNow", null);
|
|
320
|
+
exports.AiConnectionResolverService = AiConnectionResolverService = AiConnectionResolverService_1 = __decorate([
|
|
321
|
+
(0, common_1.Injectable)(),
|
|
322
|
+
__param(4, (0, common_1.Optional)()),
|
|
323
|
+
__metadata("design:paramtypes", [ai_connection_repository_1.AiConnectionRepository,
|
|
324
|
+
ai_connection_encryption_service_1.AiConnectionEncryptionService,
|
|
325
|
+
nestjs_cls_1.ClsService,
|
|
326
|
+
config_1.ConfigService,
|
|
327
|
+
logging_service_1.AppLoggingService])
|
|
328
|
+
], AiConnectionResolverService);
|
|
329
|
+
//# sourceMappingURL=ai-connection-resolver.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-connection-resolver.service.js","sourceRoot":"","sources":["../../../../src/core/llm/services/ai-connection-resolver.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,6 +21,27 @@ export declare class EmbedderService {
|
|
|
21
21
|
private readonly tokenUsageRecorder?;
|
|
22
22
|
private readonly logger;
|
|
23
23
|
constructor(modelService: ModelService, config: ConfigService<BaseConfigInterface>, tokenUsageService?: TokenUsageService, tokenUsageRecorder?: TokenUsageRecorderInterface);
|
|
24
|
+
/**
|
|
25
|
+
* Runs ONE embedding invocation, with a single failover retry on a transient
|
|
26
|
+
* provider failure (429/5xx/socket-level — classified by exactly the rule
|
|
27
|
+
* `LLMService` uses).
|
|
28
|
+
*
|
|
29
|
+
* ONE retry only, and only when there is somewhere to go: the failed
|
|
30
|
+
* connection is put into cooldown and the embedder is rebuilt, so
|
|
31
|
+
* `getEmbedder()` resolves the NEXT healthy link of the chain. A chain of one
|
|
32
|
+
* (no DB-backed embedder connection — just the `.env` block) has nowhere to
|
|
33
|
+
* fail over to, so the rejection propagates immediately, exactly as it does
|
|
34
|
+
* today. Everything beyond that single re-resolution belongs to the BullMQ
|
|
35
|
+
* job retry that owns these calls (spec § 2, "Other modalities").
|
|
36
|
+
*/
|
|
37
|
+
private withCandidateFailover;
|
|
38
|
+
/**
|
|
39
|
+
* Puts the embedder connection currently in service into its cooldown window
|
|
40
|
+
* and returns it — or undefined when there is nothing to fail over to: no
|
|
41
|
+
* candidate-aware `ModelService`, a chain of one (`.env` only), or a registry
|
|
42
|
+
* that threw. Undefined means "behave exactly as before failover existed".
|
|
43
|
+
*/
|
|
44
|
+
private failCurrentEmbedderCandidate;
|
|
24
45
|
vectoriseText(params: {
|
|
25
46
|
text: string;
|
|
26
47
|
attribution?: EmbedderAttribution;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embedder.service.d.ts","sourceRoot":"","sources":["../../../../src/core/llm/services/embedder.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAwB,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAqB,MAAM,4BAA4B,CAAC;AAEpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,6DAA6D,CAAC;AAChG,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"embedder.service.d.ts","sourceRoot":"","sources":["../../../../src/core/llm/services/embedder.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAwB,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAqB,MAAM,4BAA4B,CAAC;AAEpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,6DAA6D,CAAC;AAChG,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAehE;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAcD,qBACa,eAAe;IAIxB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAIX,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC;IACL,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IAThF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoC;gBAGxC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,aAAa,CAAC,mBAAmB,CAAC,EAI9B,iBAAiB,CAAC,EAAE,iBAAiB,EACP,kBAAkB,CAAC,EAAE,2BAA2B;IAG7G;;;;;;;;;;;;OAYG;YACW,qBAAqB;IAgBnC;;;;;OAKG;IACH,OAAO,CAAC,4BAA4B;IAc9B,aAAa,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,mBAAmB,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IAWxF,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,WAAW,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IA6B5F;;;;;OAKG;YACW,YAAY;IAO1B;;;;OAIG;YACW,WAAW;IAOzB,OAAO,CAAC,kBAAkB;IAW1B;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAuB1B,qEAAqE;IACrE,OAAO,CAAC,gBAAgB;IAaxB;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAS1B;;;;;OAKG;IACH,OAAO,CAAC,QAAQ;IAYhB,0FAA0F;IAC1F,OAAO,CAAC,SAAS,CAA8B;IAE/C;;;;;;;;;OASG;YACW,YAAY;IA4B1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;YACW,qBAAqB;IASnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACH,OAAO,CAAC,kBAAkB;IAO1B;;;OAGG;IACH,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,WAAW;CAsBpB"}
|
|
@@ -21,6 +21,7 @@ const tokens_1 = require("../../../common/tokens");
|
|
|
21
21
|
const tokenusage_type_1 = require("../../../foundations/tokenusage/enums/tokenusage.type");
|
|
22
22
|
const tokenusage_service_1 = require("../../../foundations/tokenusage/services/tokenusage.service");
|
|
23
23
|
const model_service_1 = require("../../llm/services/model.service");
|
|
24
|
+
const llm_service_1 = require("./llm.service");
|
|
24
25
|
/**
|
|
25
26
|
* Ceiling for ONE embedding input. The provider hard cap is 8192 tokens
|
|
26
27
|
* (`400 Invalid 'input[0]': maximum input length is 8192 tokens` from
|
|
@@ -39,6 +40,54 @@ let EmbedderService = EmbedderService_1 = class EmbedderService {
|
|
|
39
40
|
this.tokenUsageRecorder = tokenUsageRecorder;
|
|
40
41
|
this.logger = new common_1.Logger(EmbedderService_1.name);
|
|
41
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Runs ONE embedding invocation, with a single failover retry on a transient
|
|
45
|
+
* provider failure (429/5xx/socket-level — classified by exactly the rule
|
|
46
|
+
* `LLMService` uses).
|
|
47
|
+
*
|
|
48
|
+
* ONE retry only, and only when there is somewhere to go: the failed
|
|
49
|
+
* connection is put into cooldown and the embedder is rebuilt, so
|
|
50
|
+
* `getEmbedder()` resolves the NEXT healthy link of the chain. A chain of one
|
|
51
|
+
* (no DB-backed embedder connection — just the `.env` block) has nowhere to
|
|
52
|
+
* fail over to, so the rejection propagates immediately, exactly as it does
|
|
53
|
+
* today. Everything beyond that single re-resolution belongs to the BullMQ
|
|
54
|
+
* job retry that owns these calls (spec § 2, "Other modalities").
|
|
55
|
+
*/
|
|
56
|
+
async withCandidateFailover(work) {
|
|
57
|
+
try {
|
|
58
|
+
return await work(this.modelService.getEmbedder());
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (!(0, llm_service_1.isTransientNetworkError)(error))
|
|
62
|
+
throw error;
|
|
63
|
+
const failed = this.failCurrentEmbedderCandidate();
|
|
64
|
+
if (!failed)
|
|
65
|
+
throw error;
|
|
66
|
+
this.logger.warn(`Embedder connection ${failed.connectionId} failed transiently — retrying once on the next candidate: ${String(error)}`);
|
|
67
|
+
return work(this.modelService.getEmbedder());
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Puts the embedder connection currently in service into its cooldown window
|
|
72
|
+
* and returns it — or undefined when there is nothing to fail over to: no
|
|
73
|
+
* candidate-aware `ModelService`, a chain of one (`.env` only), or a registry
|
|
74
|
+
* that threw. Undefined means "behave exactly as before failover existed".
|
|
75
|
+
*/
|
|
76
|
+
failCurrentEmbedderCandidate() {
|
|
77
|
+
const resolver = this.modelService;
|
|
78
|
+
if (typeof resolver.getCandidatesForType !== "function" || typeof resolver.notifyCandidateFailure !== "function")
|
|
79
|
+
return undefined;
|
|
80
|
+
try {
|
|
81
|
+
const candidates = resolver.getCandidatesForType("embedder") ?? [];
|
|
82
|
+
if (candidates.length < 2)
|
|
83
|
+
return undefined;
|
|
84
|
+
resolver.notifyCandidateFailure(candidates[0]);
|
|
85
|
+
return candidates[0];
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
42
91
|
async vectoriseText(params) {
|
|
43
92
|
try {
|
|
44
93
|
const result = await this.embedGuarded(params.text, params.attribution);
|
|
@@ -60,7 +109,7 @@ let EmbedderService = EmbedderService_1 = class EmbedderService {
|
|
|
60
109
|
// The texts that fit still travel as ONE provider batch, in input order —
|
|
61
110
|
// batching is why vectoriseTextBatch exists (chunk.repository.ts:405).
|
|
62
111
|
if (withinBudget.length > 0) {
|
|
63
|
-
const vectors = await this.
|
|
112
|
+
const vectors = await this.withCandidateFailover((embedder) => embedder.embedDocuments(withinBudget.map((index) => texts[index])));
|
|
64
113
|
withinBudget.forEach((index, position) => (result[index] = vectors[position]));
|
|
65
114
|
}
|
|
66
115
|
for (const index of oversized) {
|
|
@@ -84,7 +133,7 @@ let EmbedderService = EmbedderService_1 = class EmbedderService {
|
|
|
84
133
|
async embedGuarded(text, attribution) {
|
|
85
134
|
const slices = this.splitByTokenBudget(text);
|
|
86
135
|
if (slices.length === 1)
|
|
87
|
-
return this.
|
|
136
|
+
return this.withCandidateFailover((embedder) => embedder.embedQuery(text));
|
|
88
137
|
this.warnOversizedInput(text, slices.length, attribution);
|
|
89
138
|
return this.meanPool(await this.embedSlices(slices));
|
|
90
139
|
}
|
|
@@ -96,7 +145,7 @@ let EmbedderService = EmbedderService_1 = class EmbedderService {
|
|
|
96
145
|
async embedSlices(slices) {
|
|
97
146
|
const vectors = [];
|
|
98
147
|
for (const slice of slices)
|
|
99
|
-
vectors.push(await this.
|
|
148
|
+
vectors.push(await this.withCandidateFailover((embedder) => embedder.embedQuery(slice)));
|
|
100
149
|
return vectors;
|
|
101
150
|
}
|
|
102
151
|
warnOversizedInput(text, sliceCount, attribution) {
|
|
@@ -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
|
/**
|