@dbx-tools/appkit-model-gateway 0.9.189 → 0.9.193
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 +6 -0
- package/index.ts +7 -1
- package/lib/index.d.ts +7 -1
- package/lib/index.js +6 -2
- package/lib/src/ai-decide.d.ts +50 -0
- package/lib/src/ai-decide.js +406 -0
- package/lib/src/gateway.d.ts +6 -2
- package/lib/src/gateway.js +72 -16
- package/lib/src/model-context.d.ts +32 -0
- package/lib/src/model-context.js +270 -0
- package/lib/src/models.d.ts +3 -3
- package/lib/src/models.js +55 -8
- package/lib/src/reasoning-adapt.js +2 -5
- package/lib/src/routes.js +18 -2
- package/lib/src/smart-router.d.ts +4 -7
- package/lib/src/smart-router.js +7 -175
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/src/ai-decide.ts +552 -0
- package/src/gateway.ts +96 -14
- package/src/model-context.ts +306 -0
- package/src/models.ts +66 -4
- package/src/reasoning-adapt.ts +1 -5
- package/src/routes.ts +16 -0
- package/src/smart-router.ts +8 -187
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Databricks AI Functions `ai_decide` model selection.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { getExecutionContext } from "@databricks/appkit";
|
|
7
|
+
import { closeCache, createCache, getOrSet } from "@dbx-tools/cache";
|
|
8
|
+
import { refreshWorkspaceClientAuthentication } from "@dbx-tools/databricks";
|
|
9
|
+
import { endpointCapabilities, modelMetadataFor, selection, versionTuple } from "@dbx-tools/model";
|
|
10
|
+
import { isRecord, log, toError } from "@dbx-tools/shared-core";
|
|
11
|
+
import { ModelClass } from "@dbx-tools/shared-model";
|
|
12
|
+
import { AiDecideModelFiltersSchema, AiDecideObservationSchema, AiDecideStrategySchema, } from "@dbx-tools/shared-model-gateway";
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
import { AppKitSmartRouterProbeStore, SmartRouterContextBuilder, SmartRouterProbeRecordSchema, } from "./smart-router.js";
|
|
15
|
+
const AI_DECIDE_PATH = "/api/2.0/ai-functions/ai-decide";
|
|
16
|
+
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
17
|
+
const PROBE_KEY = "ai-decide-v1";
|
|
18
|
+
const POSITIVE_PROBE_TTL_MS = 5 * 60_000;
|
|
19
|
+
const NEGATIVE_PROBE_TTL_MS = 30_000;
|
|
20
|
+
const PROBE_CACHE_TTL_MS = POSITIVE_PROBE_TTL_MS * 2;
|
|
21
|
+
const logger = log.logger("appkit/model-gateway/ai-decide");
|
|
22
|
+
const AiDecideChoiceAnswerSchema = z
|
|
23
|
+
.object({
|
|
24
|
+
type: z.literal("choice"),
|
|
25
|
+
choice: z.string().trim().min(1),
|
|
26
|
+
probabilities: z.record(z.string(), z.number().min(0).max(1)).optional(),
|
|
27
|
+
confidence: z.number().min(0).max(1).optional(),
|
|
28
|
+
})
|
|
29
|
+
.passthrough();
|
|
30
|
+
const AiDecideTaskComplexitySchema = z.enum(["simple", "standard", "advanced"]);
|
|
31
|
+
const AiDecideTaskComplexityAnswerSchema = z
|
|
32
|
+
.object({
|
|
33
|
+
type: z.literal("choice"),
|
|
34
|
+
choice: AiDecideTaskComplexitySchema,
|
|
35
|
+
})
|
|
36
|
+
.passthrough();
|
|
37
|
+
const AiDecideTaskComplexityResponseSchema = z
|
|
38
|
+
.object({
|
|
39
|
+
response: z
|
|
40
|
+
.object({
|
|
41
|
+
answers: z
|
|
42
|
+
.object({
|
|
43
|
+
task_complexity: AiDecideTaskComplexityAnswerSchema,
|
|
44
|
+
})
|
|
45
|
+
.passthrough(),
|
|
46
|
+
})
|
|
47
|
+
.passthrough(),
|
|
48
|
+
metadata: z.object({ version: z.string() }).passthrough().optional(),
|
|
49
|
+
})
|
|
50
|
+
.passthrough();
|
|
51
|
+
const AiDecideModelResponseSchema = z
|
|
52
|
+
.object({
|
|
53
|
+
response: z
|
|
54
|
+
.object({
|
|
55
|
+
answers: z
|
|
56
|
+
.object({
|
|
57
|
+
model: AiDecideChoiceAnswerSchema,
|
|
58
|
+
})
|
|
59
|
+
.passthrough(),
|
|
60
|
+
})
|
|
61
|
+
.passthrough(),
|
|
62
|
+
metadata: z.object({ version: z.string() }).passthrough().optional(),
|
|
63
|
+
})
|
|
64
|
+
.passthrough();
|
|
65
|
+
/** Select the best sufficient live foundation model through Databricks `ai_decide`. */
|
|
66
|
+
export class AiDecideRouterService {
|
|
67
|
+
invoke;
|
|
68
|
+
probeStore;
|
|
69
|
+
context = new SmartRouterContextBuilder();
|
|
70
|
+
probes = new WeakMap();
|
|
71
|
+
probeCaches = new Set();
|
|
72
|
+
constructor(invoke = invokeAiDecide, probeStore = new AppKitSmartRouterProbeStore()) {
|
|
73
|
+
this.invoke = invoke;
|
|
74
|
+
this.probeStore = probeStore;
|
|
75
|
+
}
|
|
76
|
+
async select(input, endpoints, client = undefined, options = {}) {
|
|
77
|
+
const workspaceClient = client ?? getExecutionContext().client;
|
|
78
|
+
const strategy = AiDecideStrategySchema.parse(options.strategy ?? "balanced");
|
|
79
|
+
const filters = AiDecideModelFiltersSchema.parse(options.filters ?? {});
|
|
80
|
+
const candidates = modelCandidates(endpoints, filters);
|
|
81
|
+
if (candidates.length === 0) {
|
|
82
|
+
throw new AiDecideRouterError(400, "No eligible foundation models are available");
|
|
83
|
+
}
|
|
84
|
+
if (candidates.length === 1) {
|
|
85
|
+
const [endpoint] = candidates;
|
|
86
|
+
return {
|
|
87
|
+
endpoint: endpoint,
|
|
88
|
+
observation: AiDecideObservationSchema.parse({
|
|
89
|
+
selectedModel: endpoint.name,
|
|
90
|
+
strategy,
|
|
91
|
+
confidence: 1,
|
|
92
|
+
probabilities: { [endpoint.name]: 1 },
|
|
93
|
+
latencyMs: 0,
|
|
94
|
+
}),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const context = await this.context.analyze(input);
|
|
98
|
+
if (!context.task) {
|
|
99
|
+
throw new AiDecideRouterError(400, "ai_decide input contains no routable text");
|
|
100
|
+
}
|
|
101
|
+
const currentRequest = [...context.events]
|
|
102
|
+
.reverse()
|
|
103
|
+
.find((event) => event.role === "user")?.text;
|
|
104
|
+
const currentTask = currentRequest ?? context.task;
|
|
105
|
+
const taskComplexityBody = {
|
|
106
|
+
state: {
|
|
107
|
+
task: currentTask,
|
|
108
|
+
current_request: currentTask,
|
|
109
|
+
},
|
|
110
|
+
questions: {
|
|
111
|
+
task_complexity: {
|
|
112
|
+
type: "choice",
|
|
113
|
+
instructions: "Classify the current request only. Choose advanced when a complete answer needs dependencies, configuration, APIs, and multiple code artifacts; architecture, debugging, or several interacting constraints. Choose standard for a focused implementation or analysis with limited moving parts. Choose simple only for short factual, creative, formatting, or explanation requests.",
|
|
114
|
+
criteria: {
|
|
115
|
+
simple: "One direct answer or artifact with little reasoning or implementation risk.",
|
|
116
|
+
standard: "Focused implementation or analysis with limited interacting requirements.",
|
|
117
|
+
advanced: "Multiple implementation artifacts or interacting technical constraints where completeness and correctness require stronger reasoning.",
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
options: { version: "1.0" },
|
|
122
|
+
};
|
|
123
|
+
const buildDecision = (decisionCandidates, taskComplexity) => {
|
|
124
|
+
const labels = new Map(decisionCandidates.map((endpoint, index) => [`model_${index + 1}`, endpoint]));
|
|
125
|
+
const criteria = Object.fromEntries([...labels].map(([label, endpoint], index) => [
|
|
126
|
+
label,
|
|
127
|
+
candidateDescription(endpoint, index + 1),
|
|
128
|
+
]));
|
|
129
|
+
return {
|
|
130
|
+
labels,
|
|
131
|
+
body: {
|
|
132
|
+
state: {
|
|
133
|
+
task: currentTask,
|
|
134
|
+
current_request: currentTask,
|
|
135
|
+
...(context.events.length > 1 ? { conversation_context: context.task } : {}),
|
|
136
|
+
conversation_turns: context.events.filter((event) => event.role === "user").length,
|
|
137
|
+
context_tokens: context.tokenCount,
|
|
138
|
+
completion_requirement: "The selected model must answer the current request accurately and completely in one response. Partial or truncated output is insufficient.",
|
|
139
|
+
task_complexity: taskComplexity,
|
|
140
|
+
strategy,
|
|
141
|
+
candidates: decisionCandidates.map((endpoint, index) => candidateState(endpoint, index + 1)),
|
|
142
|
+
},
|
|
143
|
+
questions: {
|
|
144
|
+
model: {
|
|
145
|
+
type: "choice",
|
|
146
|
+
instructions: `${strategyInstructions(strategy)} The task has already been classified as ${taskComplexity}.`,
|
|
147
|
+
criteria,
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
options: { version: "1.0" },
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
const startedAt = performance.now();
|
|
155
|
+
const signal = options.signal ?? new AbortController().signal;
|
|
156
|
+
let decision;
|
|
157
|
+
let response;
|
|
158
|
+
try {
|
|
159
|
+
const taskComplexity = AiDecideTaskComplexityResponseSchema.parse(await this.invoke(workspaceClient, taskComplexityBody, signal, options.timeoutMs ?? DEFAULT_TIMEOUT_MS)).response.answers.task_complexity.choice;
|
|
160
|
+
decision = buildDecision(sufficientCandidates(candidates, taskComplexity), taskComplexity);
|
|
161
|
+
response = AiDecideModelResponseSchema.parse(await this.invoke(workspaceClient, decision.body, signal, options.timeoutMs ?? DEFAULT_TIMEOUT_MS));
|
|
162
|
+
this.setProbeValue(workspaceClient, true);
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
this.setProbeValue(workspaceClient, false);
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
const answer = response.response.answers.model;
|
|
169
|
+
const selected = decision.labels.get(answer.choice);
|
|
170
|
+
if (!selected) {
|
|
171
|
+
throw new AiDecideRouterError(502, `ai_decide selected unknown candidate ${answer.choice}`);
|
|
172
|
+
}
|
|
173
|
+
const probabilities = answer.probabilities
|
|
174
|
+
? Object.fromEntries(Object.entries(answer.probabilities).flatMap(([label, probability]) => {
|
|
175
|
+
const endpoint = decision.labels.get(label);
|
|
176
|
+
return endpoint ? [[endpoint.name, probability]] : [];
|
|
177
|
+
}))
|
|
178
|
+
: undefined;
|
|
179
|
+
return {
|
|
180
|
+
endpoint: selected,
|
|
181
|
+
observation: AiDecideObservationSchema.parse({
|
|
182
|
+
selectedModel: selected.name,
|
|
183
|
+
strategy,
|
|
184
|
+
...(answer.confidence !== undefined ? { confidence: answer.confidence } : {}),
|
|
185
|
+
...(probabilities && Object.keys(probabilities).length > 0 ? { probabilities } : {}),
|
|
186
|
+
latencyMs: Math.round(performance.now() - startedAt),
|
|
187
|
+
}),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/** Probe and memoize whether the active workspace identity can call `ai_decide`. */
|
|
191
|
+
async isEnabled(endpoints, client = undefined) {
|
|
192
|
+
if (modelCandidates(endpoints, AiDecideModelFiltersSchema.parse({})).length < 2) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
let workspaceClient;
|
|
196
|
+
try {
|
|
197
|
+
workspaceClient = client ?? getExecutionContext().client;
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
const cache = this.probeCache(workspaceClient);
|
|
203
|
+
const probe = await getOrSet(cache, PROBE_KEY, () => this.loadProbe(endpoints, workspaceClient), {
|
|
204
|
+
ttl: PROBE_CACHE_TTL_MS,
|
|
205
|
+
refreshAfterWrite: (value) => this.probeTtl(value.enabled),
|
|
206
|
+
});
|
|
207
|
+
return probe?.enabled ?? false;
|
|
208
|
+
}
|
|
209
|
+
/** Stop process-local probe caches after active refreshes settle. */
|
|
210
|
+
dispose() {
|
|
211
|
+
for (const cache of this.probeCaches)
|
|
212
|
+
void closeCache(cache);
|
|
213
|
+
this.probeCaches.clear();
|
|
214
|
+
}
|
|
215
|
+
async loadProbe(endpoints, client) {
|
|
216
|
+
const stored = await this.readStoredProbe(client);
|
|
217
|
+
if (stored && stored.expiresAt > Date.now())
|
|
218
|
+
return stored;
|
|
219
|
+
const enabled = await this.select("Choose the lowest-latency sufficient model for a one-sentence factual answer.", endpoints, client, { strategy: "latency", timeoutMs: DEFAULT_TIMEOUT_MS })
|
|
220
|
+
.then(() => true)
|
|
221
|
+
.catch((error) => {
|
|
222
|
+
logger.debug("ai_decide capability probe unavailable", { error: toError(error) });
|
|
223
|
+
return false;
|
|
224
|
+
});
|
|
225
|
+
const probe = this.probeRecord(enabled);
|
|
226
|
+
await this.writeStoredProbe(probe, client);
|
|
227
|
+
return probe;
|
|
228
|
+
}
|
|
229
|
+
setProbeValue(client, enabled) {
|
|
230
|
+
const probe = this.probeRecord(enabled);
|
|
231
|
+
void this.writeProcessProbe(this.probeCache(client), probe);
|
|
232
|
+
void this.writeStoredProbe(probe, client);
|
|
233
|
+
}
|
|
234
|
+
probeRecord(enabled) {
|
|
235
|
+
return { enabled, expiresAt: Date.now() + this.probeTtl(enabled) };
|
|
236
|
+
}
|
|
237
|
+
probeTtl(enabled) {
|
|
238
|
+
return enabled ? POSITIVE_PROBE_TTL_MS : NEGATIVE_PROBE_TTL_MS;
|
|
239
|
+
}
|
|
240
|
+
async readStoredProbe(client) {
|
|
241
|
+
try {
|
|
242
|
+
const parsed = SmartRouterProbeRecordSchema.safeParse(await this.probeStore.get(PROBE_KEY, client));
|
|
243
|
+
return parsed.success ? parsed.data : undefined;
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
logger.debug("ai_decide probe cache read failed", { error: toError(error) });
|
|
247
|
+
return undefined;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
async writeProcessProbe(cache, probe) {
|
|
251
|
+
try {
|
|
252
|
+
await cache.set(PROBE_KEY, probe, { ttl: PROBE_CACHE_TTL_MS });
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
logger.debug("ai_decide process probe cache write failed", { error: toError(error) });
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
async writeStoredProbe(probe, client) {
|
|
259
|
+
try {
|
|
260
|
+
await this.probeStore.set(PROBE_KEY, probe, Math.max(1, Math.ceil(PROBE_CACHE_TTL_MS / 1_000)), client);
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
logger.debug("ai_decide probe cache write failed", { error: toError(error) });
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
probeCache(client) {
|
|
267
|
+
const owner = client.config && typeof client.config === "object" ? client.config : client;
|
|
268
|
+
let cache = this.probes.get(owner);
|
|
269
|
+
if (!cache) {
|
|
270
|
+
cache = createCache({ maxEntries: 1, useClone: false });
|
|
271
|
+
this.probes.set(owner, cache);
|
|
272
|
+
this.probeCaches.add(cache);
|
|
273
|
+
}
|
|
274
|
+
return cache;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/** HTTP failure returned by the Databricks AI Functions router. */
|
|
278
|
+
export class AiDecideRouterError extends Error {
|
|
279
|
+
status;
|
|
280
|
+
constructor(status, message) {
|
|
281
|
+
super(message);
|
|
282
|
+
this.status = status;
|
|
283
|
+
this.name = "AiDecideRouterError";
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function modelCandidates(endpoints, filters) {
|
|
287
|
+
const families = filters.families?.map((family) => family.toLowerCase());
|
|
288
|
+
return selection
|
|
289
|
+
.lookupModels(endpoints, {
|
|
290
|
+
...(filters.modelClass ? { modelClass: filters.modelClass } : {}),
|
|
291
|
+
modelSource: filters.modelSource,
|
|
292
|
+
...(filters.requiresTools !== undefined ? { requiresTools: filters.requiresTools } : {}),
|
|
293
|
+
...(filters.requiresStructuredOutput !== undefined
|
|
294
|
+
? { requiresStructuredOutput: filters.requiresStructuredOutput }
|
|
295
|
+
: {}),
|
|
296
|
+
limit: filters.maxCandidates,
|
|
297
|
+
}, { preferSystemModels: true })
|
|
298
|
+
.map(({ endpoint }) => endpoint)
|
|
299
|
+
.filter((endpoint) => !families || (endpoint.family && families.includes(endpoint.family.toLowerCase())));
|
|
300
|
+
}
|
|
301
|
+
function sufficientCandidates(candidates, taskComplexity) {
|
|
302
|
+
const classOrder = {
|
|
303
|
+
simple: [ModelClass.ChatFast, ModelClass.ChatBalanced, ModelClass.ChatThinking],
|
|
304
|
+
standard: [ModelClass.ChatBalanced, ModelClass.ChatThinking, ModelClass.ChatFast],
|
|
305
|
+
advanced: [ModelClass.ChatThinking, ModelClass.ChatBalanced, ModelClass.ChatFast],
|
|
306
|
+
}[taskComplexity];
|
|
307
|
+
for (const modelClass of classOrder) {
|
|
308
|
+
const sufficient = candidates.filter((endpoint) => endpoint.class === modelClass);
|
|
309
|
+
if (sufficient.length > 0)
|
|
310
|
+
return sufficient;
|
|
311
|
+
}
|
|
312
|
+
return [...candidates];
|
|
313
|
+
}
|
|
314
|
+
function candidateState(endpoint, rank) {
|
|
315
|
+
const capabilities = endpointCapabilities(endpoint);
|
|
316
|
+
return {
|
|
317
|
+
id: endpoint.name,
|
|
318
|
+
rank,
|
|
319
|
+
display_name: endpoint.displayName,
|
|
320
|
+
family: endpoint.family,
|
|
321
|
+
version: versionTuple(endpoint.name),
|
|
322
|
+
class: endpoint.class,
|
|
323
|
+
profile: endpoint.profile,
|
|
324
|
+
benchmarks: candidateBenchmarks(endpoint),
|
|
325
|
+
capabilities: {
|
|
326
|
+
chat: capabilities.chat,
|
|
327
|
+
tools: capabilities.tools,
|
|
328
|
+
structured_output: endpoint.supportsStructuredOutput === true,
|
|
329
|
+
reasoning_efforts: endpoint.reasoningEfforts ?? [],
|
|
330
|
+
},
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
function candidateDescription(endpoint, rank) {
|
|
334
|
+
const benchmarks = candidateBenchmarks(endpoint);
|
|
335
|
+
return {
|
|
336
|
+
model: endpoint.name,
|
|
337
|
+
rank,
|
|
338
|
+
family: endpoint.family ?? null,
|
|
339
|
+
version: versionTuple(endpoint.name),
|
|
340
|
+
capability_class: endpoint.class ?? null,
|
|
341
|
+
quality_score: endpoint.profile?.quality ?? null,
|
|
342
|
+
speed_score: endpoint.profile?.speed ?? null,
|
|
343
|
+
cost_score: endpoint.profile?.cost ?? null,
|
|
344
|
+
measured_quality_percentile: benchmarks.quality_percentile,
|
|
345
|
+
normalized_response_time_ms: benchmarks.normalized_response_time_ms,
|
|
346
|
+
time_to_first_token_ms: benchmarks.time_to_first_token_ms,
|
|
347
|
+
output_tokens_per_second: benchmarks.output_tokens_per_second,
|
|
348
|
+
supports_tools: endpointCapabilities(endpoint).tools,
|
|
349
|
+
supports_structured_output: endpoint.supportsStructuredOutput === true,
|
|
350
|
+
reasoning_efforts: endpoint.reasoningEfforts ?? [],
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
function candidateBenchmarks(endpoint) {
|
|
354
|
+
const metadata = modelMetadataFor(endpoint);
|
|
355
|
+
return {
|
|
356
|
+
quality_percentile: metadata.rating?.score ?? null,
|
|
357
|
+
normalized_response_time_ms: metadata.latencyScore?.score ?? null,
|
|
358
|
+
time_to_first_token_ms: metadata.latencyScore?.measurements.timeToFirstTokenMs ?? null,
|
|
359
|
+
output_tokens_per_second: metadata.latencyScore?.measurements.outputTokensPerSecond ?? null,
|
|
360
|
+
successful_run_count: metadata.latencyScore?.measurements.successfulRunCount ?? null,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
function strategyInstructions(strategy) {
|
|
364
|
+
const objective = {
|
|
365
|
+
balanced: "Choose the smallest and least expensive model that is still likely to answer the task accurately and completely.",
|
|
366
|
+
quality: "Choose the model most likely to produce the highest-quality correct answer.",
|
|
367
|
+
cost: "Choose the lowest-cost model that is still sufficient for the task. Keep premier and newer unscored models eligible when they are materially more likely to complete the request correctly. When candidates have similar expected answer quality and completeness, prefer lower cost over lower latency.",
|
|
368
|
+
latency: "Choose the fastest model that is still sufficient for the task.",
|
|
369
|
+
}[strategy];
|
|
370
|
+
return `${objective} Judge current_request as the work that must be completed now; use task only as conversation context, and do not let simpler earlier turns reduce the current request's difficulty. A model is sufficient only if it is likely to produce a complete, correct answer in one response. Treat partial or truncated output as insufficient. Software implementation that requires dependencies, configuration, APIs, and multiple code artifacts needs materially more quality than a short explanation, even when the request itself is concise. Optimize for the selected strategy only among sufficient candidates. Use the supplied rank, version, capability class, quality, measured latency, throughput, cost, tool, structured-output, family, and reasoning metadata. Lower normalized_response_time_ms and time_to_first_token_ms are faster; higher output_tokens_per_second and measured_quality_percentile are better. Treat a newer unscored model as potentially stronger than an older scored predecessor rather than penalizing missing profile scores. Prefer simpler models for genuinely simple requests and reserve stronger models for implementation, multi-constraint reasoning, architecture, and debugging.`;
|
|
371
|
+
}
|
|
372
|
+
async function invokeAiDecide(client, body, signal, timeoutMs) {
|
|
373
|
+
const host = (await client.config.getHost()).toString();
|
|
374
|
+
const url = new URL(AI_DECIDE_PATH, host);
|
|
375
|
+
const headers = new Headers({ "content-type": "application/json" });
|
|
376
|
+
await client.config.authenticate(headers);
|
|
377
|
+
const combinedSignal = AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)]);
|
|
378
|
+
let response = await fetch(url, {
|
|
379
|
+
method: "POST",
|
|
380
|
+
headers,
|
|
381
|
+
body: JSON.stringify(body),
|
|
382
|
+
signal: combinedSignal,
|
|
383
|
+
});
|
|
384
|
+
if (response.status === 401 && (await refreshWorkspaceClientAuthentication(client))) {
|
|
385
|
+
await response.body?.cancel();
|
|
386
|
+
headers.delete("authorization");
|
|
387
|
+
headers.delete("x-databricks-workspace-id");
|
|
388
|
+
await client.config.authenticate(headers);
|
|
389
|
+
response = await fetch(url, {
|
|
390
|
+
method: "POST",
|
|
391
|
+
headers,
|
|
392
|
+
body: JSON.stringify(body),
|
|
393
|
+
signal: combinedSignal,
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
if (!response.ok) {
|
|
397
|
+
const detail = (await response.text().catch(() => "")).trim().slice(0, 500);
|
|
398
|
+
throw new AiDecideRouterError(response.status, `Databricks ai_decide failed with HTTP ${response.status}${detail ? `: ${detail}` : ""}`);
|
|
399
|
+
}
|
|
400
|
+
const value = (await response.json());
|
|
401
|
+
if (isRecord(value) && typeof value.error_message === "string" && value.error_message) {
|
|
402
|
+
throw new AiDecideRouterError(502, value.error_message);
|
|
403
|
+
}
|
|
404
|
+
return value;
|
|
405
|
+
}
|
|
406
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWktZGVjaWRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FpLWRlY2lkZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBRUgsT0FBTyxFQUFFLG1CQUFtQixFQUF3QixNQUFNLG9CQUFvQixDQUFDO0FBQy9FLE9BQU8sRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxvQ0FBb0MsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzdFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxnQkFBZ0IsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDbkcsT0FBTyxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDaEUsT0FBTyxFQUFFLFVBQVUsRUFBK0IsTUFBTSx5QkFBeUIsQ0FBQztBQUNsRixPQUFPLEVBQ0wsMEJBQTBCLEVBQzFCLHlCQUF5QixFQUN6QixzQkFBc0IsR0FLdkIsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBRXhCLE9BQU8sRUFDTCwyQkFBMkIsRUFDM0IseUJBQXlCLEVBQ3pCLDRCQUE0QixHQUc3QixNQUFNLG1CQUFtQixDQUFDO0FBRTNCLE1BQU0sY0FBYyxHQUFHLGlDQUFpQyxDQUFDO0FBQ3pELE1BQU0sa0JBQWtCLEdBQUcsTUFBTSxDQUFDO0FBQ2xDLE1BQU0sU0FBUyxHQUFHLGNBQWMsQ0FBQztBQUNqQyxNQUFNLHFCQUFxQixHQUFHLENBQUMsR0FBRyxNQUFNLENBQUM7QUFDekMsTUFBTSxxQkFBcUIsR0FBRyxNQUFNLENBQUM7QUFDckMsTUFBTSxrQkFBa0IsR0FBRyxxQkFBcUIsR0FBRyxDQUFDLENBQUM7QUFDckQsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0s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QUFFLEdBQUcsQ0FBQyxDQUFDO1FBQzVFLE1BQU0sSUFBSSxtQkFBbUIsQ0FDM0IsUUFBUSxDQUFDLE1BQU0sRUFDZix5Q0FBeUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUN6RixDQUFDO0lBQ0osQ0FBQztJQUNELE1BQU0sS0FBSyxHQUFHLENBQUMsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQVksQ0FBQztJQUNqRCxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxPQUFPLEtBQUssQ0FBQyxhQUFhLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUN0RixNQUFNLElBQUksbUJBQW1CLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBEYXRhYnJpY2tzIEFJIEZ1bmN0aW9ucyBgYWlfZGVjaWRlYCBtb2RlbCBzZWxlY3Rpb24uXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IGdldEV4ZWN1dGlvbkNvbnRleHQsIHR5cGUgV29ya3NwYWNlQ2xpZW50IH0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuaW1wb3J0IHsgY2xvc2VDYWNoZSwgY3JlYXRlQ2FjaGUsIGdldE9yU2V0IH0gZnJvbSBcIkBkYngtdG9vbHMvY2FjaGVcIjtcbmltcG9ydCB7IHJlZnJlc2hXb3Jrc3BhY2VDbGllbnRBdXRoZW50aWNhdGlvbiB9IGZyb20gXCJAZGJ4LXRvb2xzL2RhdGFicmlja3NcIjtcbmltcG9ydCB7IGVuZHBvaW50Q2FwYWJpbGl0aWVzLCBtb2RlbE1ldGFkYXRhRm9yLCBzZWxlY3Rpb24sIHZlcnNpb25UdXBsZSB9IGZyb20gXCJAZGJ4LXRvb2xzL21vZGVsXCI7XG5pbXBvcnQgeyBpc1JlY29yZCwgbG9nLCB0b0Vycm9yIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IE1vZGVsQ2xhc3MsIHR5cGUgU2VydmluZ0VuZHBvaW50U3VtbWFyeSB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1tb2RlbFwiO1xuaW1wb3J0IHtcbiAgQWlEZWNpZGVNb2RlbEZpbHRlcnNTY2hlbWEsXG4gIEFpRGVjaWRlT2JzZXJ2YXRpb25TY2hlbWEsXG4gIEFpRGVjaWRlU3RyYXRlZ3lTY2hlbWEsXG4gIHR5cGUgQWlEZWNpZGVNb2RlbEZpbHRlcnMsXG4gIHR5cGUgQWlEZWNpZGVPYnNlcnZhdGlvbixcbiAgdHlwZSBBaURlY2lkZVN0cmF0ZWd5LFxuICB0eXBlIFJlc29sdmVkQWlEZWNpZGVNb2RlbEZpbHRlcnMsXG59IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1tb2RlbC1nYXRld2F5XCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuXG5pbXBvcnQge1xuICBBcHBLaXRTbWFydFJvdXRlclByb2JlU3RvcmUsXG4gIFNtYXJ0Um91dGVyQ29udGV4dEJ1aWxkZXIsXG4gIFNtYXJ0Um91dGVyUHJvYmVSZWNvcmRTY2hlbWEsXG4gIHR5cGUgU21hcnRSb3V0ZXJQcm9iZVJlY29yZCxcbiAgdHlwZSBTbWFydFJvdXRlclByb2JlU3RvcmUsXG59IGZyb20gXCIuL3NtYXJ0LXJvdXRlci50c1wiO1xuXG5jb25zdCBBSV9ERUNJREVfUEFUSCA9IFwiL2FwaS8yLjAvYWktZnVuY3Rpb25zL2FpLWRlY2lkZVwiO1xuY29uc3QgREVGQVVMVF9USU1FT1VUX01TID0gMTBfMDAwO1xuY29uc3QgUFJPQkVfS0VZID0gXCJhaS1kZWNpZGUtdjFcIjtcbmNvbnN0IFBPU0lUSVZFX1BST0JFX1RUTF9NUyA9IDUgKiA2MF8wMDA7XG5jb25zdCBORUdBVElWRV9QUk9CRV9UVExfTVMgPSAzMF8wMDA7XG5jb25zdCBQUk9CRV9DQUNIRV9UVExfTVMgPSBQT1NJVElWRV9QUk9CRV9UVExfTVMgKiAyO1xuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcImFwcGtpdC9tb2RlbC1nYXRld2F5L2FpLWRlY2lkZVwiKTtcblxuY29uc3QgQWlEZWNpZGVDaG9pY2VBbnN3ZXJTY2hlbWEgPSB6XG4gIC5vYmplY3Qoe1xuICAgIHR5cGU6IHoubGl0ZXJhbChcImNob2ljZVwiKSxcbiAgICBjaG9pY2U6IHouc3RyaW5nKCkudHJpbSgpLm1pbigxKSxcbiAgICBwcm9iYWJpbGl0aWVzOiB6LnJlY29yZCh6LnN0cmluZygpLCB6Lm51bWJlcigpLm1pbigwKS5tYXgoMSkpLm9wdGlvbmFsKCksXG4gICAgY29uZmlkZW5jZTogei5udW1iZXIoKS5taW4oMCkubWF4KDEpLm9wdGlvbmFsKCksXG4gIH0pXG4gIC5wYXNzdGhyb3VnaCgpO1xuXG5jb25zdCBBaURlY2lkZVRhc2tDb21wbGV4aXR5U2NoZW1hID0gei5lbnVtKFtcInNpbXBsZVwiLCBcInN0YW5kYXJkXCIsIFwiYWR2YW5jZWRcIl0pO1xuXG5jb25zdCBBaURlY2lkZVRhc2tDb21wbGV4aXR5QW5zd2VyU2NoZW1hID0gelxuICAub2JqZWN0KHtcbiAgICB0eXBlOiB6LmxpdGVyYWwoXCJjaG9pY2VcIiksXG4gICAgY2hvaWNlOiBBaURlY2lkZVRhc2tDb21wbGV4aXR5U2NoZW1hLFxuICB9KVxuICAucGFzc3Rocm91Z2goKTtcblxuY29uc3QgQWlEZWNpZGVUYXNrQ29tcGxleGl0eVJlc3BvbnNlU2NoZW1hID0gelxuICAub2JqZWN0KHtcbiAgICByZXNwb25zZTogelxuICAgICAgLm9iamVjdCh7XG4gICAgICAgIGFuc3dlcnM6IHpcbiAgICAgICAgICAub2JqZWN0KHtcbiAgICAgICAgICAgIHRhc2tfY29tcGxleGl0eTogQWlEZWNpZGVUYXNrQ29tcGxleGl0eUFuc3dlclNjaGVtYSxcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5wYXNzdGhyb3VnaCgpLFxuICAgICAgfSlcbiAgICAgIC5wYXNzdGhyb3VnaCgpLFxuICAgIG1ldGFkYXRhOiB6Lm9iamVjdCh7IHZlcnNpb246IHouc3RyaW5nKCkgfSkucGFzc3Rocm91Z2goKS5vcHRpb25hbCgpLFxuICB9KVxuICAucGFzc3Rocm91Z2goKTtcblxuY29uc3QgQWlEZWNpZGVNb2RlbFJlc3BvbnNlU2NoZW1hID0gelxuICAub2JqZWN0KHtcbiAgICByZXNwb25zZTogelxuICAgICAgLm9iamVjdCh7XG4gICAgICAgIGFuc3dlcnM6IHpcbiAgICAgICAgICAub2JqZWN0KHtcbiAgICAgICAgICAgIG1vZGVsOiBBaURlY2lkZUNob2ljZUFuc3dlclNjaGVtYSxcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5wYXNzdGhyb3VnaCgpLFxuICAgICAgfSlcbiAgICAgIC5wYXNzdGhyb3VnaCgpLFxuICAgIG1ldGFkYXRhOiB6Lm9iamVjdCh7IHZlcnNpb246IHouc3RyaW5nKCkgfSkucGFzc3Rocm91Z2goKS5vcHRpb25hbCgpLFxuICB9KVxuICAucGFzc3Rocm91Z2goKTtcblxuLyoqIFNlbGVjdGlvbiBwb2xpY3kgYWNjZXB0ZWQgYnkge0BsaW5rIEFpRGVjaWRlUm91dGVyU2VydmljZS5zZWxlY3R9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBBaURlY2lkZVNlbGVjdGlvbk9wdGlvbnMge1xuICByZWFkb25seSBzdHJhdGVneT86IEFpRGVjaWRlU3RyYXRlZ3k7XG4gIHJlYWRvbmx5IGZpbHRlcnM/OiBBaURlY2lkZU1vZGVsRmlsdGVycztcbiAgcmVhZG9ubHkgc2lnbmFsPzogQWJvcnRTaWduYWw7XG4gIHJlYWRvbmx5IHRpbWVvdXRNcz86IG51bWJlcjtcbn1cblxuLyoqIENvbmNyZXRlIGVuZHBvaW50IGFuZCBvYnNlcnZhYmxlIGRlY2lzaW9uIHJldHVybmVkIGJ5IGBhaV9kZWNpZGVgLiAqL1xuZXhwb3J0IGludGVyZmFjZSBBaURlY2lkZVNlbGVjdGlvbiB7XG4gIHJlYWRvbmx5IGVuZHBvaW50OiBTZXJ2aW5nRW5kcG9pbnRTdW1tYXJ5O1xuICByZWFkb25seSBvYnNlcnZhdGlvbjogQWlEZWNpZGVPYnNlcnZhdGlvbjtcbn1cblxudHlwZSBBaURlY2lkZUludm9rZXIgPSAoXG4gIGNsaWVudDogV29ya3NwYWNlQ2xpZW50LFxuICBib2R5OiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4sXG4gIHNpZ25hbDogQWJvcnRTaWduYWwsXG4gIHRpbWVvdXRNczogbnVtYmVyLFxuKSA9PiBQcm9taXNlPHVua25vd24+O1xuXG50eXBlIEFpRGVjaWRlUHJvYmVDYWNoZSA9IFJldHVyblR5cGU8dHlwZW9mIGNyZWF0ZUNhY2hlPjtcblxuLyoqIFNlbGVjdCB0aGUgYmVzdCBzdWZmaWNpZW50IGxpdmUgZm91bmRhdGlvbiBtb2RlbCB0aHJvdWdoIERhdGFicmlja3MgYGFpX2RlY2lkZWAuICovXG5leHBvcnQgY2xhc3MgQWlEZWNpZGVSb3V0ZXJTZXJ2aWNlIHtcbiAgcHJpdmF0ZSByZWFkb25seSBjb250ZXh0ID0gbmV3IFNtYXJ0Um91dGVyQ29udGV4dEJ1aWxkZXIoKTtcbiAgcHJpdmF0ZSByZWFkb25seSBwcm9iZXMgPSBuZXcgV2Vha01hcDxvYmplY3QsIEFpRGVjaWRlUHJvYmVDYWNoZT4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBwcm9iZUNhY2hlcyA9IG5ldyBTZXQ8QWlEZWNpZGVQcm9iZUNhY2hlPigpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgaW52b2tlOiBBaURlY2lkZUludm9rZXIgPSBpbnZva2VBaURlY2lkZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHByb2JlU3RvcmU6IFNtYXJ0Um91dGVyUHJvYmVTdG9yZSA9IG5ldyBBcHBLaXRTbWFydFJvdXRlclByb2JlU3RvcmUoKSxcbiAgKSB7fVxuXG4gIGFzeW5jIHNlbGVjdChcbiAgICBpbnB1dDogdW5rbm93bixcbiAgICBlbmRwb2ludHM6IHJlYWRvbmx5IFNlcnZpbmdFbmRwb2ludFN1bW1hcnlbXSxcbiAgICBjbGllbnQ6IFdvcmtzcGFjZUNsaWVudCB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZCxcbiAgICBvcHRpb25zOiBBaURlY2lkZVNlbGVjdGlvbk9wdGlvbnMgPSB7fSxcbiAgKTogUHJvbWlzZTxBaURlY2lkZVNlbGVjdGlvbj4ge1xuICAgIGNvbnN0IHdvcmtzcGFjZUNsaWVudCA9IGNsaWVudCA/PyBnZXRFeGVjdXRpb25Db250ZXh0KCkuY2xpZW50O1xuICAgIGNvbnN0IHN0cmF0ZWd5ID0gQWlEZWNpZGVTdHJhdGVneVNjaGVtYS5wYXJzZShvcHRpb25zLnN0cmF0ZWd5ID8/IFwiYmFsYW5jZWRcIik7XG4gICAgY29uc3QgZmlsdGVycyA9IEFpRGVjaWRlTW9kZWxGaWx0ZXJzU2NoZW1hLnBhcnNlKG9wdGlvbnMuZmlsdGVycyA/PyB7fSk7XG4gICAgY29uc3QgY2FuZGlkYXRlcyA9IG1vZGVsQ2FuZGlkYXRlcyhlbmRwb2ludHMsIGZpbHRlcnMpO1xuICAgIGlmIChjYW5kaWRhdGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEFpRGVjaWRlUm91dGVyRXJyb3IoNDAwLCBcIk5vIGVsaWdpYmxlIGZvdW5kYXRpb24gbW9kZWxzIGFyZSBhdmFpbGFibGVcIik7XG4gICAgfVxuICAgIGlmIChjYW5kaWRhdGVzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgY29uc3QgW2VuZHBvaW50XSA9IGNhbmRpZGF0ZXM7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBlbmRwb2ludDogZW5kcG9pbnQhLFxuICAgICAgICBvYnNlcnZhdGlvbjogQWlEZWNpZGVPYnNlcnZhdGlvblNjaGVtYS5wYXJzZSh7XG4gICAgICAgICAgc2VsZWN0ZWRNb2RlbDogZW5kcG9pbnQhLm5hbWUsXG4gICAgICAgICAgc3RyYXRlZ3ksXG4gICAgICAgICAgY29uZmlkZW5jZTogMSxcbiAgICAgICAgICBwcm9iYWJpbGl0aWVzOiB7IFtlbmRwb2ludCEubmFtZV06IDEgfSxcbiAgICAgICAgICBsYXRlbmN5TXM6IDAsXG4gICAgICAgIH0pLFxuICAgICAgfTtcbiAgICB9XG4gICAgY29uc3QgY29udGV4dCA9IGF3YWl0IHRoaXMuY29udGV4dC5hbmFseXplKGlucHV0KTtcbiAgICBpZiAoIWNvbnRleHQudGFzaykge1xuICAgICAgdGhyb3cgbmV3IEFpRGVjaWRlUm91dGVyRXJyb3IoNDAwLCBcImFpX2RlY2lkZSBpbnB1dCBjb250YWlucyBubyByb3V0YWJsZSB0ZXh0XCIpO1xuICAgIH1cbiAgICBjb25zdCBjdXJyZW50UmVxdWVzdCA9IFsuLi5jb250ZXh0LmV2ZW50c11cbiAgICAgIC5yZXZlcnNlKClcbiAgICAgIC5maW5kKChldmVudCkgPT4gZXZlbnQucm9sZSA9PT0gXCJ1c2VyXCIpPy50ZXh0O1xuICAgIGNvbnN0IGN1cnJlbnRUYXNrID0gY3VycmVudFJlcXVlc3QgPz8gY29udGV4dC50YXNrO1xuICAgIGNvbnN0IHRhc2tDb21wbGV4aXR5Qm9keSA9IHtcbiAgICAgIHN0YXRlOiB7XG4gICAgICAgIHRhc2s6IGN1cnJlbnRUYXNrLFxuICAgICAgICBjdXJyZW50X3JlcXVlc3Q6IGN1cnJlbnRUYXNrLFxuICAgICAgfSxcbiAgICAgIHF1ZXN0aW9uczoge1xuICAgICAgICB0YXNrX2NvbXBsZXhpdHk6IHtcbiAgICAgICAgICB0eXBlOiBcImNob2ljZVwiIGFzIGNvbnN0LFxuICAgICAgICAgIGluc3RydWN0aW9uczpcbiAgICAgICAgICAgIFwiQ2xhc3NpZnkgdGhlIGN1cnJlbnQgcmVxdWVzdCBvbmx5LiBDaG9vc2UgYWR2YW5jZWQgd2hlbiBhIGNvbXBsZXRlIGFuc3dlciBuZWVkcyBkZXBlbmRlbmNpZXMsIGNvbmZpZ3VyYXRpb24sIEFQSXMsIGFuZCBtdWx0aXBsZSBjb2RlIGFydGlmYWN0czsgYXJjaGl0ZWN0dXJlLCBkZWJ1Z2dpbmcsIG9yIHNldmVyYWwgaW50ZXJhY3RpbmcgY29uc3RyYWludHMuIENob29zZSBzdGFuZGFyZCBmb3IgYSBmb2N1c2VkIGltcGxlbWVudGF0aW9uIG9yIGFuYWx5c2lzIHdpdGggbGltaXRlZCBtb3ZpbmcgcGFydHMuIENob29zZSBzaW1wbGUgb25seSBmb3Igc2hvcnQgZmFjdHVhbCwgY3JlYXRpdmUsIGZvcm1hdHRpbmcsIG9yIGV4cGxhbmF0aW9uIHJlcXVlc3RzLlwiLFxuICAgICAgICAgIGNyaXRlcmlhOiB7XG4gICAgICAgICAgICBzaW1wbGU6IFwiT25lIGRpcmVjdCBhbnN3ZXIgb3IgYXJ0aWZhY3Qgd2l0aCBsaXR0bGUgcmVhc29uaW5nIG9yIGltcGxlbWVudGF0aW9uIHJpc2suXCIsXG4gICAgICAgICAgICBzdGFuZGFyZDogXCJGb2N1c2VkIGltcGxlbWVudGF0aW9uIG9yIGFuYWx5c2lzIHdpdGggbGltaXRlZCBpbnRlcmFjdGluZyByZXF1aXJlbWVudHMuXCIsXG4gICAgICAgICAgICBhZHZhbmNlZDpcbiAgICAgICAgICAgICAgXCJNdWx0aXBsZSBpbXBsZW1lbnRhdGlvbiBhcnRpZmFjdHMgb3IgaW50ZXJhY3RpbmcgdGVjaG5pY2FsIGNvbnN0cmFpbnRzIHdoZXJlIGNvbXBsZXRlbmVzcyBhbmQgY29ycmVjdG5lc3MgcmVxdWlyZSBzdHJvbmdlciByZWFzb25pbmcuXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBvcHRpb25zOiB7IHZlcnNpb246IFwiMS4wXCIgfSxcbiAgICB9O1xuICAgIGNvbnN0IGJ1aWxkRGVjaXNpb24gPSAoXG4gICAgICBkZWNpc2lvbkNhbmRpZGF0ZXM6IHJlYWRvbmx5IFNlcnZpbmdFbmRwb2ludFN1bW1hcnlbXSxcbiAgICAgIHRhc2tDb21wbGV4aXR5OiB6LmluZmVyPHR5cGVvZiBBaURlY2lkZVRhc2tDb21wbGV4aXR5U2NoZW1hPixcbiAgICApID0+IHtcbiAgICAgIGNvbnN0IGxhYmVscyA9IG5ldyBNYXAoXG4gICAgICAgIGRlY2lzaW9uQ2FuZGlkYXRlcy5tYXAoKGVuZHBvaW50LCBpbmRleCkgPT4gW2Btb2RlbF8ke2luZGV4ICsgMX1gLCBlbmRwb2ludF0pLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IGNyaXRlcmlhID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgICBbLi4ubGFiZWxzXS5tYXAoKFtsYWJlbCwgZW5kcG9pbnRdLCBpbmRleCkgPT4gW1xuICAgICAgICAgIGxhYmVsLFxuICAgICAgICAgIGNhbmRpZGF0ZURlc2NyaXB0aW9uKGVuZHBvaW50LCBpbmRleCArIDEpLFxuICAgICAgICBdKSxcbiAgICAgICk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBsYWJlbHMsXG4gICAgICAgIGJvZHk6IHtcbiAgICAgICAgICBzdGF0ZToge1xuICAgICAgICAgICAgdGFzazogY3VycmVudFRhc2ssXG4gICAgICAgICAgICBjdXJyZW50X3JlcXVlc3Q6IGN1cnJlbnRUYXNrLFxuICAgICAgICAgICAgLi4uKGNvbnRleHQuZXZlbnRzLmxlbmd0aCA+IDEgPyB7IGNvbnZlcnNhdGlvbl9jb250ZXh0OiBjb250ZXh0LnRhc2sgfSA6IHt9KSxcbiAgICAgICAgICAgIGNvbnZlcnNhdGlvbl90dXJuczogY29udGV4dC5ldmVudHMuZmlsdGVyKChldmVudCkgPT4gZXZlbnQucm9sZSA9PT0gXCJ1c2VyXCIpLmxlbmd0aCxcbiAgICAgICAgICAgIGNvbnRleHRfdG9rZW5zOiBjb250ZXh0LnRva2VuQ291bnQsXG4gICAgICAgICAgICBjb21wbGV0aW9uX3JlcXVpcmVtZW50OlxuICAgICAgICAgICAgICBcIlRoZSBzZWxlY3RlZCBtb2RlbCBtdXN0IGFuc3dlciB0aGUgY3VycmVudCByZXF1ZXN0IGFjY3VyYXRlbHkgYW5kIGNvbXBsZXRlbHkgaW4gb25lIHJlc3BvbnNlLiBQYXJ0aWFsIG9yIHRydW5jYXRlZCBvdXRwdXQgaXMgaW5zdWZmaWNpZW50LlwiLFxuICAgICAgICAgICAgdGFza19jb21wbGV4aXR5OiB0YXNrQ29tcGxleGl0eSxcbiAgICAgICAgICAgIHN0cmF0ZWd5LFxuICAgICAgICAgICAgY2FuZGlkYXRlczogZGVjaXNpb25DYW5kaWRhdGVzLm1hcCgoZW5kcG9pbnQsIGluZGV4KSA9PlxuICAgICAgICAgICAgICBjYW5kaWRhdGVTdGF0ZShlbmRwb2ludCwgaW5kZXggKyAxKSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgfSxcbiAgICAgICAgICBxdWVzdGlvbnM6IHtcbiAgICAgICAgICAgIG1vZGVsOiB7XG4gICAgICAgICAgICAgIHR5cGU6IFwiY2hvaWNlXCIgYXMgY29uc3QsXG4gICAgICAgICAgICAgIGluc3RydWN0aW9uczogYCR7c3RyYXRlZ3lJbnN0cnVjdGlvbnMoc3RyYXRlZ3kpfSBUaGUgdGFzayBoYXMgYWxyZWFkeSBiZWVuIGNsYXNzaWZpZWQgYXMgJHt0YXNrQ29tcGxleGl0eX0uYCxcbiAgICAgICAgICAgICAgY3JpdGVyaWEsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgb3B0aW9uczogeyB2ZXJzaW9uOiBcIjEuMFwiIH0sXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH07XG4gICAgY29uc3Qgc3RhcnRlZEF0ID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgY29uc3Qgc2lnbmFsID0gb3B0aW9ucy5zaWduYWwgPz8gbmV3IEFib3J0Q29udHJvbGxlcigpLnNpZ25hbDtcbiAgICBsZXQgZGVjaXNpb246IFJldHVyblR5cGU8dHlwZW9mIGJ1aWxkRGVjaXNpb24+O1xuICAgIGxldCByZXNwb25zZTogei5pbmZlcjx0eXBlb2YgQWlEZWNpZGVNb2RlbFJlc3BvbnNlU2NoZW1hPjtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdGFza0NvbXBsZXhpdHkgPSBBaURlY2lkZVRhc2tDb21wbGV4aXR5UmVzcG9uc2VTY2hlbWEucGFyc2UoXG4gICAgICAgIGF3YWl0IHRoaXMuaW52b2tlKFxuICAgICAgICAgIHdvcmtzcGFjZUNsaWVudCxcbiAgICAgICAgICB0YXNrQ29tcGxleGl0eUJvZHksXG4gICAgICAgICAgc2lnbmFsLFxuICAgICAgICAgIG9wdGlvbnMudGltZW91dE1zID8/IERFRkFVTFRfVElNRU9VVF9NUyxcbiAgICAgICAgKSxcbiAgICAgICkucmVzcG9uc2UuYW5zd2Vycy50YXNrX2NvbXBsZXhpdHkuY2hvaWNlO1xuICAgICAgZGVjaXNpb24gPSBidWlsZERlY2lzaW9uKHN1ZmZpY2llbnRDYW5kaWRhdGVzKGNhbmRpZGF0ZXMsIHRhc2tDb21wbGV4aXR5KSwgdGFza0NvbXBsZXhpdHkpO1xuICAgICAgcmVzcG9uc2UgPSBBaURlY2lkZU1vZGVsUmVzcG9uc2VTY2hlbWEucGFyc2UoXG4gICAgICAgIGF3YWl0IHRoaXMuaW52b2tlKFxuICAgICAgICAgIHdvcmtzcGFjZUNsaWVudCxcbiAgICAgICAgICBkZWNpc2lvbi5ib2R5LFxuICAgICAgICAgIHNpZ25hbCxcbiAgICAgICAgICBvcHRpb25zLnRpbWVvdXRNcyA/PyBERUZBVUxUX1RJTUVPVVRfTVMsXG4gICAgICAgICksXG4gICAgICApO1xuICAgICAgdGhpcy5zZXRQcm9iZVZhbHVlKHdvcmtzcGFjZUNsaWVudCwgdHJ1ZSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMuc2V0UHJvYmVWYWx1ZSh3b3Jrc3BhY2VDbGllbnQsIGZhbHNlKTtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgICBjb25zdCBhbnN3ZXIgPSByZXNwb25zZS5yZXNwb25zZS5hbnN3ZXJzLm1vZGVsO1xuICAgIGNvbnN0IHNlbGVjdGVkID0gZGVjaXNpb24ubGFiZWxzLmdldChhbnN3ZXIuY2hvaWNlKTtcbiAgICBpZiAoIXNlbGVjdGVkKSB7XG4gICAgICB0aHJvdyBuZXcgQWlEZWNpZGVSb3V0ZXJFcnJvcig1MDIsIGBhaV9kZWNpZGUgc2VsZWN0ZWQgdW5rbm93biBjYW5kaWRhdGUgJHthbnN3ZXIuY2hvaWNlfWApO1xuICAgIH1cbiAgICBjb25zdCBwcm9iYWJpbGl0aWVzID0gYW5zd2VyLnByb2JhYmlsaXRpZXNcbiAgICAgID8gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgICAgIE9iamVjdC5lbnRyaWVzKGFuc3dlci5wcm9iYWJpbGl0aWVzKS5mbGF0TWFwKChbbGFiZWwsIHByb2JhYmlsaXR5XSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZW5kcG9pbnQgPSBkZWNpc2lvbi5sYWJlbHMuZ2V0KGxhYmVsKTtcbiAgICAgICAgICAgIHJldHVybiBlbmRwb2ludCA/IFtbZW5kcG9pbnQubmFtZSwgcHJvYmFiaWxpdHldIGFzIGNvbnN0XSA6IFtdO1xuICAgICAgICAgIH0pLFxuICAgICAgICApXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgICByZXR1cm4ge1xuICAgICAgZW5kcG9pbnQ6IHNlbGVjdGVkLFxuICAgICAgb2JzZXJ2YXRpb246IEFpRGVjaWRlT2JzZXJ2YXRpb25TY2hlbWEucGFyc2Uoe1xuICAgICAgICBzZWxlY3RlZE1vZGVsOiBzZWxlY3RlZC5uYW1lLFxuICAgICAgICBzdHJhdGVneSxcbiAgICAgICAgLi4uKGFuc3dlci5jb25maWRlbmNlICE9PSB1bmRlZmluZWQgPyB7IGNvbmZpZGVuY2U6IGFuc3dlci5jb25maWRlbmNlIH0gOiB7fSksXG4gICAgICAgIC4uLihwcm9iYWJpbGl0aWVzICYmIE9iamVjdC5rZXlzKHByb2JhYmlsaXRpZXMpLmxlbmd0aCA+IDAgPyB7IHByb2JhYmlsaXRpZXMgfSA6IHt9KSxcbiAgICAgICAgbGF0ZW5jeU1zOiBNYXRoLnJvdW5kKHBlcmZvcm1hbmNlLm5vdygpIC0gc3RhcnRlZEF0KSxcbiAgICAgIH0pLFxuICAgIH07XG4gIH1cblxuICAvKiogUHJvYmUgYW5kIG1lbW9pemUgd2hldGhlciB0aGUgYWN0aXZlIHdvcmtzcGFjZSBpZGVudGl0eSBjYW4gY2FsbCBgYWlfZGVjaWRlYC4gKi9cbiAgYXN5bmMgaXNFbmFibGVkKFxuICAgIGVuZHBvaW50czogcmVhZG9ubHkgU2VydmluZ0VuZHBvaW50U3VtbWFyeVtdLFxuICAgIGNsaWVudDogV29ya3NwYWNlQ2xpZW50IHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkLFxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAobW9kZWxDYW5kaWRhdGVzKGVuZHBvaW50cywgQWlEZWNpZGVNb2RlbEZpbHRlcnNTY2hlbWEucGFyc2Uoe30pKS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGxldCB3b3Jrc3BhY2VDbGllbnQ6IFdvcmtzcGFjZUNsaWVudDtcbiAgICB0cnkge1xuICAgICAgd29ya3NwYWNlQ2xpZW50ID0gY2xpZW50ID8/IGdldEV4ZWN1dGlvbkNvbnRleHQoKS5jbGllbnQ7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNvbnN0IGNhY2hlID0gdGhpcy5wcm9iZUNhY2hlKHdvcmtzcGFjZUNsaWVudCk7XG4gICAgY29uc3QgcHJvYmUgPSBhd2FpdCBnZXRPclNldChcbiAgICAgIGNhY2hlLFxuICAgICAgUFJPQkVfS0VZLFxuICAgICAgKCkgPT4gdGhpcy5sb2FkUHJvYmUoZW5kcG9pbnRzLCB3b3Jrc3BhY2VDbGllbnQpLFxuICAgICAge1xuICAgICAgICB0dGw6IFBST0JFX0NBQ0hFX1RUTF9NUyxcbiAgICAgICAgcmVmcmVzaEFmdGVyV3JpdGU6ICh2YWx1ZSkgPT4gdGhpcy5wcm9iZVR0bCh2YWx1ZS5lbmFibGVkKSxcbiAgICAgIH0sXG4gICAgKTtcbiAgICByZXR1cm4gcHJvYmU/LmVuYWJsZWQgPz8gZmFsc2U7XG4gIH1cblxuICAvKiogU3RvcCBwcm9jZXNzLWxvY2FsIHByb2JlIGNhY2hlcyBhZnRlciBhY3RpdmUgcmVmcmVzaGVzIHNldHRsZS4gKi9cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IGNhY2hlIG9mIHRoaXMucHJvYmVDYWNoZXMpIHZvaWQgY2xvc2VDYWNoZShjYWNoZSk7XG4gICAgdGhpcy5wcm9iZUNhY2hlcy5jbGVhcigpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBsb2FkUHJvYmUoXG4gICAgZW5kcG9pbnRzOiByZWFkb25seSBTZXJ2aW5nRW5kcG9pbnRTdW1tYXJ5W10sXG4gICAgY2xpZW50OiBXb3Jrc3BhY2VDbGllbnQsXG4gICk6IFByb21pc2U8U21hcnRSb3V0ZXJQcm9iZVJlY29yZD4ge1xuICAgIGNvbnN0IHN0b3JlZCA9IGF3YWl0IHRoaXMucmVhZFN0b3JlZFByb2JlKGNsaWVudCk7XG4gICAgaWYgKHN0b3JlZCAmJiBzdG9yZWQuZXhwaXJlc0F0ID4gRGF0ZS5ub3coKSkgcmV0dXJuIHN0b3JlZDtcbiAgICBjb25zdCBlbmFibGVkID0gYXdhaXQgdGhpcy5zZWxlY3QoXG4gICAgICBcIkNob29zZSB0aGUgbG93ZXN0LWxhdGVuY3kgc3VmZmljaWVudCBtb2RlbCBmb3IgYSBvbmUtc2VudGVuY2UgZmFjdHVhbCBhbnN3ZXIuXCIsXG4gICAgICBlbmRwb2ludHMsXG4gICAgICBjbGllbnQsXG4gICAgICB7IHN0cmF0ZWd5OiBcImxhdGVuY3lcIiwgdGltZW91dE1zOiBERUZBVUxUX1RJTUVPVVRfTVMgfSxcbiAgICApXG4gICAgICAudGhlbigoKSA9PiB0cnVlKVxuICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICBsb2dnZXIuZGVidWcoXCJhaV9kZWNpZGUgY2FwYWJpbGl0eSBwcm9iZSB1bmF2YWlsYWJsZVwiLCB7IGVycm9yOiB0b0Vycm9yKGVycm9yKSB9KTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSk7XG4gICAgY29uc3QgcHJvYmUgPSB0aGlzLnByb2JlUmVjb3JkKGVuYWJsZWQpO1xuICAgIGF3YWl0IHRoaXMud3JpdGVTdG9yZWRQcm9iZShwcm9iZSwgY2xpZW50KTtcbiAgICByZXR1cm4gcHJvYmU7XG4gIH1cblxuICBwcml2YXRlIHNldFByb2JlVmFsdWUoY2xpZW50OiBXb3Jrc3BhY2VDbGllbnQsIGVuYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBjb25zdCBwcm9iZSA9IHRoaXMucHJvYmVSZWNvcmQoZW5hYmxlZCk7XG4gICAgdm9pZCB0aGlzLndyaXRlUHJvY2Vzc1Byb2JlKHRoaXMucHJvYmVDYWNoZShjbGllbnQpLCBwcm9iZSk7XG4gICAgdm9pZCB0aGlzLndyaXRlU3RvcmVkUHJvYmUocHJvYmUsIGNsaWVudCk7XG4gIH1cblxuICBwcml2YXRlIHByb2JlUmVjb3JkKGVuYWJsZWQ6IGJvb2xlYW4pOiBTbWFydFJvdXRlclByb2JlUmVjb3JkIHtcbiAgICByZXR1cm4geyBlbmFibGVkLCBleHBpcmVzQXQ6IERhdGUubm93KCkgKyB0aGlzLnByb2JlVHRsKGVuYWJsZWQpIH07XG4gIH1cblxuICBwcml2YXRlIHByb2JlVHRsKGVuYWJsZWQ6IGJvb2xlYW4pOiBudW1iZXIge1xuICAgIHJldHVybiBlbmFibGVkID8gUE9TSVRJVkVfUFJPQkVfVFRMX01TIDogTkVHQVRJVkVfUFJPQkVfVFRMX01TO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWFkU3RvcmVkUHJvYmUoXG4gICAgY2xpZW50OiBXb3Jrc3BhY2VDbGllbnQsXG4gICk6IFByb21pc2U8U21hcnRSb3V0ZXJQcm9iZVJlY29yZCB8IHVuZGVmaW5lZD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSBTbWFydFJvdXRlclByb2JlUmVjb3JkU2NoZW1hLnNhZmVQYXJzZShcbiAgICAgICAgYXdhaXQgdGhpcy5wcm9iZVN0b3JlLmdldChQUk9CRV9LRVksIGNsaWVudCksXG4gICAgICApO1xuICAgICAgcmV0dXJuIHBhcnNlZC5zdWNjZXNzID8gcGFyc2VkLmRhdGEgOiB1bmRlZmluZWQ7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhcImFpX2RlY2lkZSBwcm9iZSBjYWNoZSByZWFkIGZhaWxlZFwiLCB7IGVycm9yOiB0b0Vycm9yKGVycm9yKSB9KTtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB3cml0ZVByb2Nlc3NQcm9iZShcbiAgICBjYWNoZTogQWlEZWNpZGVQcm9iZUNhY2hlLFxuICAgIHByb2JlOiBTbWFydFJvdXRlclByb2JlUmVjb3JkLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgY2FjaGUuc2V0KFBST0JFX0tFWSwgcHJvYmUsIHsgdHRsOiBQUk9CRV9DQUNIRV9UVExfTVMgfSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhcImFpX2RlY2lkZSBwcm9jZXNzIHByb2JlIGNhY2hlIHdyaXRlIGZhaWxlZFwiLCB7IGVycm9yOiB0b0Vycm9yKGVycm9yKSB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHdyaXRlU3RvcmVkUHJvYmUoXG4gICAgcHJvYmU6IFNtYXJ0Um91dGVyUHJvYmVSZWNvcmQsXG4gICAgY2xpZW50OiBXb3Jrc3BhY2VDbGllbnQsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLnByb2JlU3RvcmUuc2V0KFxuICAgICAgICBQUk9CRV9LRVksXG4gICAgICAgIHByb2JlLFxuICAgICAgICBNYXRoLm1heCgxLCBNYXRoLmNlaWwoUFJPQkVfQ0FDSEVfVFRMX01TIC8gMV8wMDApKSxcbiAgICAgICAgY2xpZW50LFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmRlYnVnKFwiYWlfZGVjaWRlIHByb2JlIGNhY2hlIHdyaXRlIGZhaWxlZFwiLCB7IGVycm9yOiB0b0Vycm9yKGVycm9yKSB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHByb2JlQ2FjaGUoY2xpZW50OiBXb3Jrc3BhY2VDbGllbnQpOiBBaURlY2lkZVByb2JlQ2FjaGUge1xuICAgIGNvbnN0IG93bmVyID1cbiAgICAgIGNsaWVudC5jb25maWcgJiYgdHlwZW9mIGNsaWVudC5jb25maWcgPT09IFwib2JqZWN0XCIgPyAoY2xpZW50LmNvbmZpZyBhcyBvYmplY3QpIDogY2xpZW50O1xuICAgIGxldCBjYWNoZSA9IHRoaXMucHJvYmVzLmdldChvd25lcik7XG4gICAgaWYgKCFjYWNoZSkge1xuICAgICAgY2FjaGUgPSBjcmVhdGVDYWNoZSh7IG1heEVudHJpZXM6IDEsIHVzZUNsb25lOiBmYWxzZSB9KTtcbiAgICAgIHRoaXMucHJvYmVzLnNldChvd25lciwgY2FjaGUpO1xuICAgICAgdGhpcy5wcm9iZUNhY2hlcy5hZGQoY2FjaGUpO1xuICAgIH1cbiAgICByZXR1cm4gY2FjaGU7XG4gIH1cbn1cblxuLyoqIEhUVFAgZmFpbHVyZSByZXR1cm5lZCBieSB0aGUgRGF0YWJyaWNrcyBBSSBGdW5jdGlvbnMgcm91dGVyLiAqL1xuZXhwb3J0IGNsYXNzIEFpRGVjaWRlUm91dGVyRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlYWRvbmx5IHN0YXR1czogbnVtYmVyLFxuICAgIG1lc3NhZ2U6IHN0cmluZyxcbiAgKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gICAgdGhpcy5uYW1lID0gXCJBaURlY2lkZVJvdXRlckVycm9yXCI7XG4gIH1cbn1cblxuZnVuY3Rpb24gbW9kZWxDYW5kaWRhdGVzKFxuICBlbmRwb2ludHM6IHJlYWRvbmx5IFNlcnZpbmdFbmRwb2ludFN1bW1hcnlbXSxcbiAgZmlsdGVyczogUmVzb2x2ZWRBaURlY2lkZU1vZGVsRmlsdGVycyxcbik6IFNlcnZpbmdFbmRwb2ludFN1bW1hcnlbXSB7XG4gIGNvbnN0IGZhbWlsaWVzID0gZmlsdGVycy5mYW1pbGllcz8ubWFwKChmYW1pbHkpID0+IGZhbWlseS50b0xvd2VyQ2FzZSgpKTtcbiAgcmV0dXJuIHNlbGVjdGlvblxuICAgIC5sb29rdXBNb2RlbHMoXG4gICAgICBlbmRwb2ludHMsXG4gICAgICB7XG4gICAgICAgIC4uLihmaWx0ZXJzLm1vZGVsQ2xhc3MgPyB7IG1vZGVsQ2xhc3M6IGZpbHRlcnMubW9kZWxDbGFzcyB9IDoge30pLFxuICAgICAgICBtb2RlbFNvdXJjZTogZmlsdGVycy5tb2RlbFNvdXJjZSxcbiAgICAgICAgLi4uKGZpbHRlcnMucmVxdWlyZXNUb29scyAhPT0gdW5kZWZpbmVkID8geyByZXF1aXJlc1Rvb2xzOiBmaWx0ZXJzLnJlcXVpcmVzVG9vbHMgfSA6IHt9KSxcbiAgICAgICAgLi4uKGZpbHRlcnMucmVxdWlyZXNTdHJ1Y3R1cmVkT3V0cHV0ICE9PSB1bmRlZmluZWRcbiAgICAgICAgICA/IHsgcmVxdWlyZXNTdHJ1Y3R1cmVkT3V0cHV0OiBmaWx0ZXJzLnJlcXVpcmVzU3RydWN0dXJlZE91dHB1dCB9XG4gICAgICAgICAgOiB7fSksXG4gICAgICAgIGxpbWl0OiBmaWx0ZXJzLm1heENhbmRpZGF0ZXMsXG4gICAgICB9LFxuICAgICAgeyBwcmVmZXJTeXN0ZW1Nb2RlbHM6IHRydWUgfSxcbiAgICApXG4gICAgLm1hcCgoeyBlbmRwb2ludCB9KSA9PiBlbmRwb2ludClcbiAgICAuZmlsdGVyKFxuICAgICAgKGVuZHBvaW50KSA9PlxuICAgICAgICAhZmFtaWxpZXMgfHwgKGVuZHBvaW50LmZhbWlseSAmJiBmYW1pbGllcy5pbmNsdWRlcyhlbmRwb2ludC5mYW1pbHkudG9Mb3dlckNhc2UoKSkpLFxuICAgICk7XG59XG5cbmZ1bmN0aW9uIHN1ZmZpY2llbnRDYW5kaWRhdGVzKFxuICBjYW5kaWRhdGVzOiByZWFkb25seSBTZXJ2aW5nRW5kcG9pbnRTdW1tYXJ5W10sXG4gIHRhc2tDb21wbGV4aXR5OiB6LmluZmVyPHR5cGVvZiBBaURlY2lkZVRhc2tDb21wbGV4aXR5U2NoZW1hPixcbik6IFNlcnZpbmdFbmRwb2ludFN1bW1hcnlbXSB7XG4gIGNvbnN0IGNsYXNzT3JkZXIgPSB7XG4gICAgc2ltcGxlOiBbTW9kZWxDbGFzcy5DaGF0RmFzdCwgTW9kZWxDbGFzcy5DaGF0QmFsYW5jZWQsIE1vZGVsQ2xhc3MuQ2hhdFRoaW5raW5nXSxcbiAgICBzdGFuZGFyZDogW01vZGVsQ2xhc3MuQ2hhdEJhbGFuY2VkLCBNb2RlbENsYXNzLkNoYXRUaGlua2luZywgTW9kZWxDbGFzcy5DaGF0RmFzdF0sXG4gICAgYWR2YW5jZWQ6IFtNb2RlbENsYXNzLkNoYXRUaGlua2luZywgTW9kZWxDbGFzcy5DaGF0QmFsYW5jZWQsIE1vZGVsQ2xhc3MuQ2hhdEZhc3RdLFxuICB9W3Rhc2tDb21wbGV4aXR5XTtcbiAgZm9yIChjb25zdCBtb2RlbENsYXNzIG9mIGNsYXNzT3JkZXIpIHtcbiAgICBjb25zdCBzdWZmaWNpZW50ID0gY2FuZGlkYXRlcy5maWx0ZXIoKGVuZHBvaW50KSA9PiBlbmRwb2ludC5jbGFzcyA9PT0gbW9kZWxDbGFzcyk7XG4gICAgaWYgKHN1ZmZpY2llbnQubGVuZ3RoID4gMCkgcmV0dXJuIHN1ZmZpY2llbnQ7XG4gIH1cbiAgcmV0dXJuIFsuLi5jYW5kaWRhdGVzXTtcbn1cblxuZnVuY3Rpb24gY2FuZGlkYXRlU3RhdGUoZW5kcG9pbnQ6IFNlcnZpbmdFbmRwb2ludFN1bW1hcnksIHJhbms6IG51bWJlcik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgY29uc3QgY2FwYWJpbGl0aWVzID0gZW5kcG9pbnRDYXBhYmlsaXRpZXMoZW5kcG9pbnQpO1xuICByZXR1cm4ge1xuICAgIGlkOiBlbmRwb2ludC5uYW1lLFxuICAgIHJhbmssXG4gICAgZGlzcGxheV9uYW1lOiBlbmRwb2ludC5kaXNwbGF5TmFtZSxcbiAgICBmYW1pbHk6IGVuZHBvaW50LmZhbWlseSxcbiAgICB2ZXJzaW9uOiB2ZXJzaW9uVHVwbGUoZW5kcG9pbnQubmFtZSksXG4gICAgY2xhc3M6IGVuZHBvaW50LmNsYXNzLFxuICAgIHByb2ZpbGU6IGVuZHBvaW50LnByb2ZpbGUsXG4gICAgYmVuY2htYXJrczogY2FuZGlkYXRlQmVuY2htYXJrcyhlbmRwb2ludCksXG4gICAgY2FwYWJpbGl0aWVzOiB7XG4gICAgICBjaGF0OiBjYXBhYmlsaXRpZXMuY2hhdCxcbiAgICAgIHRvb2xzOiBjYXBhYmlsaXRpZXMudG9vbHMsXG4gICAgICBzdHJ1Y3R1cmVkX291dHB1dDogZW5kcG9pbnQuc3VwcG9ydHNTdHJ1Y3R1cmVkT3V0cHV0ID09PSB0cnVlLFxuICAgICAgcmVhc29uaW5nX2VmZm9ydHM6IGVuZHBvaW50LnJlYXNvbmluZ0VmZm9ydHMgPz8gW10sXG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gY2FuZGlkYXRlRGVzY3JpcHRpb24oXG4gIGVuZHBvaW50OiBTZXJ2aW5nRW5kcG9pbnRTdW1tYXJ5LFxuICByYW5rOiBudW1iZXIsXG4pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIGNvbnN0IGJlbmNobWFya3MgPSBjYW5kaWRhdGVCZW5jaG1hcmtzKGVuZHBvaW50KTtcbiAgcmV0dXJuIHtcbiAgICBtb2RlbDogZW5kcG9pbnQubmFtZSxcbiAgICByYW5rLFxuICAgIGZhbWlseTogZW5kcG9pbnQuZmFtaWx5ID8/IG51bGwsXG4gICAgdmVyc2lvbjogdmVyc2lvblR1cGxlKGVuZHBvaW50Lm5hbWUpLFxuICAgIGNhcGFiaWxpdHlfY2xhc3M6IGVuZHBvaW50LmNsYXNzID8/IG51bGwsXG4gICAgcXVhbGl0eV9zY29yZTogZW5kcG9pbnQucHJvZmlsZT8ucXVhbGl0eSA/PyBudWxsLFxuICAgIHNwZWVkX3Njb3JlOiBlbmRwb2ludC5wcm9maWxlPy5zcGVlZCA/PyBudWxsLFxuICAgIGNvc3Rfc2NvcmU6IGVuZHBvaW50LnByb2ZpbGU/LmNvc3QgPz8gbnVsbCxcbiAgICBtZWFzdXJlZF9xdWFsaXR5X3BlcmNlbnRpbGU6IGJlbmNobWFya3MucXVhbGl0eV9wZXJjZW50aWxlLFxuICAgIG5vcm1hbGl6ZWRfcmVzcG9uc2VfdGltZV9tczogYmVuY2htYXJrcy5ub3JtYWxpemVkX3Jlc3BvbnNlX3RpbWVfbXMsXG4gICAgdGltZV90b19maXJzdF90b2tlbl9tczogYmVuY2htYXJrcy50aW1lX3RvX2ZpcnN0X3Rva2VuX21zLFxuICAgIG91dHB1dF90b2tlbnNfcGVyX3NlY29uZDogYmVuY2htYXJrcy5vdXRwdXRfdG9rZW5zX3Blcl9zZWNvbmQsXG4gICAgc3VwcG9ydHNfdG9vbHM6IGVuZHBvaW50Q2FwYWJpbGl0aWVzKGVuZHBvaW50KS50b29scyxcbiAgICBzdXBwb3J0c19zdHJ1Y3R1cmVkX291dHB1dDogZW5kcG9pbnQuc3VwcG9ydHNTdHJ1Y3R1cmVkT3V0cHV0ID09PSB0cnVlLFxuICAgIHJlYXNvbmluZ19lZmZvcnRzOiBlbmRwb2ludC5yZWFzb25pbmdFZmZvcnRzID8/IFtdLFxuICB9O1xufVxuXG5mdW5jdGlvbiBjYW5kaWRhdGVCZW5jaG1hcmtzKGVuZHBvaW50OiBTZXJ2aW5nRW5kcG9pbnRTdW1tYXJ5KTogUmVjb3JkPHN0cmluZywgbnVtYmVyIHwgbnVsbD4ge1xuICBjb25zdCBtZXRhZGF0YSA9IG1vZGVsTWV0YWRhdGFGb3IoZW5kcG9pbnQpO1xuICByZXR1cm4ge1xuICAgIHF1YWxpdHlfcGVyY2VudGlsZTogbWV0YWRhdGEucmF0aW5nPy5zY29yZSA/PyBudWxsLFxuICAgIG5vcm1hbGl6ZWRfcmVzcG9uc2VfdGltZV9tczogbWV0YWRhdGEubGF0ZW5jeVNjb3JlPy5zY29yZSA/PyBudWxsLFxuICAgIHRpbWVfdG9fZmlyc3RfdG9rZW5fbXM6IG1ldGFkYXRhLmxhdGVuY3lTY29yZT8ubWVhc3VyZW1lbnRzLnRpbWVUb0ZpcnN0VG9rZW5NcyA/PyBudWxsLFxuICAgIG91dHB1dF90b2tlbnNfcGVyX3NlY29uZDogbWV0YWRhdGEubGF0ZW5jeVNjb3JlPy5tZWFzdXJlbWVudHMub3V0cHV0VG9rZW5zUGVyU2Vjb25kID8/IG51bGwsXG4gICAgc3VjY2Vzc2Z1bF9ydW5fY291bnQ6IG1ldGFkYXRhLmxhdGVuY3lTY29yZT8ubWVhc3VyZW1lbnRzLnN1Y2Nlc3NmdWxSdW5Db3VudCA/PyBudWxsLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzdHJhdGVneUluc3RydWN0aW9ucyhzdHJhdGVneTogQWlEZWNpZGVTdHJhdGVneSk6IHN0cmluZyB7XG4gIGNvbnN0IG9iamVjdGl2ZSA9IHtcbiAgICBiYWxhbmNlZDpcbiAgICAgIFwiQ2hvb3NlIHRoZSBzbWFsbGVzdCBhbmQgbGVhc3QgZXhwZW5zaXZlIG1vZGVsIHRoYXQgaXMgc3RpbGwgbGlrZWx5IHRvIGFuc3dlciB0aGUgdGFzayBhY2N1cmF0ZWx5IGFuZCBjb21wbGV0ZWx5LlwiLFxuICAgIHF1YWxpdHk6IFwiQ2hvb3NlIHRoZSBtb2RlbCBtb3N0IGxpa2VseSB0byBwcm9kdWNlIHRoZSBoaWdoZXN0LXF1YWxpdHkgY29ycmVjdCBhbnN3ZXIuXCIsXG4gICAgY29zdDogXCJDaG9vc2UgdGhlIGxvd2VzdC1jb3N0IG1vZGVsIHRoYXQgaXMgc3RpbGwgc3VmZmljaWVudCBmb3IgdGhlIHRhc2suIEtlZXAgcHJlbWllciBhbmQgbmV3ZXIgdW5zY29yZWQgbW9kZWxzIGVsaWdpYmxlIHdoZW4gdGhleSBhcmUgbWF0ZXJpYWxseSBtb3JlIGxpa2VseSB0byBjb21wbGV0ZSB0aGUgcmVxdWVzdCBjb3JyZWN0bHkuIFdoZW4gY2FuZGlkYXRlcyBoYXZlIHNpbWlsYXIgZXhwZWN0ZWQgYW5zd2VyIHF1YWxpdHkgYW5kIGNvbXBsZXRlbmVzcywgcHJlZmVyIGxvd2VyIGNvc3Qgb3ZlciBsb3dlciBsYXRlbmN5LlwiLFxuICAgIGxhdGVuY3k6IFwiQ2hvb3NlIHRoZSBmYXN0ZXN0IG1vZGVsIHRoYXQgaXMgc3RpbGwgc3VmZmljaWVudCBmb3IgdGhlIHRhc2suXCIsXG4gIH1bc3RyYXRlZ3ldO1xuICByZXR1cm4gYCR7b2JqZWN0aXZlfSBKdWRnZSBjdXJyZW50X3JlcXVlc3QgYXMgdGhlIHdvcmsgdGhhdCBtdXN0IGJlIGNvbXBsZXRlZCBub3c7IHVzZSB0YXNrIG9ubHkgYXMgY29udmVyc2F0aW9uIGNvbnRleHQsIGFuZCBkbyBub3QgbGV0IHNpbXBsZXIgZWFybGllciB0dXJucyByZWR1Y2UgdGhlIGN1cnJlbnQgcmVxdWVzdCdzIGRpZmZpY3VsdHkuIEEgbW9kZWwgaXMgc3VmZmljaWVudCBvbmx5IGlmIGl0IGlzIGxpa2VseSB0byBwcm9kdWNlIGEgY29tcGxldGUsIGNvcnJlY3QgYW5zd2VyIGluIG9uZSByZXNwb25zZS4gVHJlYXQgcGFydGlhbCBvciB0cnVuY2F0ZWQgb3V0cHV0IGFzIGluc3VmZmljaWVudC4gU29mdHdhcmUgaW1wbGVtZW50YXRpb24gdGhhdCByZXF1aXJlcyBkZXBlbmRlbmNpZXMsIGNvbmZpZ3VyYXRpb24sIEFQSXMsIGFuZCBtdWx0aXBsZSBjb2RlIGFydGlmYWN0cyBuZWVkcyBtYXRlcmlhbGx5IG1vcmUgcXVhbGl0eSB0aGFuIGEgc2hvcnQgZXhwbGFuYXRpb24sIGV2ZW4gd2hlbiB0aGUgcmVxdWVzdCBpdHNlbGYgaXMgY29uY2lzZS4gT3B0aW1pemUgZm9yIHRoZSBzZWxlY3RlZCBzdHJhdGVneSBvbmx5IGFtb25nIHN1ZmZpY2llbnQgY2FuZGlkYXRlcy4gVXNlIHRoZSBzdXBwbGllZCByYW5rLCB2ZXJzaW9uLCBjYXBhYmlsaXR5IGNsYXNzLCBxdWFsaXR5LCBtZWFzdXJlZCBsYXRlbmN5LCB0aHJvdWdocHV0LCBjb3N0LCB0b29sLCBzdHJ1Y3R1cmVkLW91dHB1dCwgZmFtaWx5LCBhbmQgcmVhc29uaW5nIG1ldGFkYXRhLiBMb3dlciBub3JtYWxpemVkX3Jlc3BvbnNlX3RpbWVfbXMgYW5kIHRpbWVfdG9fZmlyc3RfdG9rZW5fbXMgYXJlIGZhc3RlcjsgaGlnaGVyIG91dHB1dF90b2tlbnNfcGVyX3NlY29uZCBhbmQgbWVhc3VyZWRfcXVhbGl0eV9wZXJjZW50aWxlIGFyZSBiZXR0ZXIuIFRyZWF0IGEgbmV3ZXIgdW5zY29yZWQgbW9kZWwgYXMgcG90ZW50aWFsbHkgc3Ryb25nZXIgdGhhbiBhbiBvbGRlciBzY29yZWQgcHJlZGVjZXNzb3IgcmF0aGVyIHRoYW4gcGVuYWxpemluZyBtaXNzaW5nIHByb2ZpbGUgc2NvcmVzLiBQcmVmZXIgc2ltcGxlciBtb2RlbHMgZm9yIGdlbnVpbmVseSBzaW1wbGUgcmVxdWVzdHMgYW5kIHJlc2VydmUgc3Ryb25nZXIgbW9kZWxzIGZvciBpbXBsZW1lbnRhdGlvbiwgbXVsdGktY29uc3RyYWludCByZWFzb25pbmcsIGFyY2hpdGVjdHVyZSwgYW5kIGRlYnVnZ2luZy5gO1xufVxuXG5hc3luYyBmdW5jdGlvbiBpbnZva2VBaURlY2lkZShcbiAgY2xpZW50OiBXb3Jrc3BhY2VDbGllbnQsXG4gIGJvZHk6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+PixcbiAgc2lnbmFsOiBBYm9ydFNpZ25hbCxcbiAgdGltZW91dE1zOiBudW1iZXIsXG4pOiBQcm9taXNlPHVua25vd24+IHtcbiAgY29uc3QgaG9zdCA9IChhd2FpdCBjbGllbnQuY29uZmlnLmdldEhvc3QoKSkudG9TdHJpbmcoKTtcbiAgY29uc3QgdXJsID0gbmV3IFVSTChBSV9ERUNJREVfUEFUSCwgaG9zdCk7XG4gIGNvbnN0IGhlYWRlcnMgPSBuZXcgSGVhZGVycyh7IFwiY29udGVudC10eXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiIH0pO1xuICBhd2FpdCBjbGllbnQuY29uZmlnLmF1dGhlbnRpY2F0ZShoZWFkZXJzKTtcbiAgY29uc3QgY29tYmluZWRTaWduYWwgPSBBYm9ydFNpZ25hbC5hbnkoW3NpZ25hbCwgQWJvcnRTaWduYWwudGltZW91dCh0aW1lb3V0TXMpXSk7XG4gIGxldCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHVybCwge1xuICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgaGVhZGVycyxcbiAgICBib2R5OiBKU09OLnN0cmluZ2lmeShib2R5KSxcbiAgICBzaWduYWw6IGNvbWJpbmVkU2lnbmFsLFxuICB9KTtcbiAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gNDAxICYmIChhd2FpdCByZWZyZXNoV29ya3NwYWNlQ2xpZW50QXV0aGVudGljYXRpb24oY2xpZW50KSkpIHtcbiAgICBhd2FpdCByZXNwb25zZS5ib2R5Py5jYW5jZWwoKTtcbiAgICBoZWFkZXJzLmRlbGV0ZShcImF1dGhvcml6YXRpb25cIik7XG4gICAgaGVhZGVycy5kZWxldGUoXCJ4LWRhdGFicmlja3Mtd29ya3NwYWNlLWlkXCIpO1xuICAgIGF3YWl0IGNsaWVudC5jb25maWcuYXV0aGVudGljYXRlKGhlYWRlcnMpO1xuICAgIHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsLCB7XG4gICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgaGVhZGVycyxcbiAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KGJvZHkpLFxuICAgICAgc2lnbmFsOiBjb21iaW5lZFNpZ25hbCxcbiAgICB9KTtcbiAgfVxuICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgY29uc3QgZGV0YWlsID0gKGF3YWl0IHJlc3BvbnNlLnRleHQoKS5jYXRjaCgoKSA9PiBcIlwiKSkudHJpbSgpLnNsaWNlKDAsIDUwMCk7XG4gICAgdGhyb3cgbmV3IEFpRGVjaWRlUm91dGVyRXJyb3IoXG4gICAgICByZXNwb25zZS5zdGF0dXMsXG4gICAgICBgRGF0YWJyaWNrcyBhaV9kZWNpZGUgZmFpbGVkIHdpdGggSFRUUCAke3Jlc3BvbnNlLnN0YXR1c30ke2RldGFpbCA/IGA6ICR7ZGV0YWlsfWAgOiBcIlwifWAsXG4gICAgKTtcbiAgfVxuICBjb25zdCB2YWx1ZSA9IChhd2FpdCByZXNwb25zZS5qc29uKCkpIGFzIHVua25vd247XG4gIGlmIChpc1JlY29yZCh2YWx1ZSkgJiYgdHlwZW9mIHZhbHVlLmVycm9yX21lc3NhZ2UgPT09IFwic3RyaW5nXCIgJiYgdmFsdWUuZXJyb3JfbWVzc2FnZSkge1xuICAgIHRocm93IG5ldyBBaURlY2lkZVJvdXRlckVycm9yKDUwMiwgdmFsdWUuZXJyb3JfbWVzc2FnZSk7XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufVxuIl19
|
package/lib/src/gateway.d.ts
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
-
import { type ServingEndpointSummary, type ModelClass as ModelClassType } from "@dbx-tools/shared-model";
|
|
6
|
+
import { type ModelSource, type ServingEndpointSummary, type ModelClass as ModelClassType } from "@dbx-tools/shared-model";
|
|
7
7
|
import type { ClientProtocol, ModelCapabilityOverride, ModelListResponse, SmartRouterMode } from "@dbx-tools/shared-model-gateway";
|
|
8
|
+
import { AiDecideRouterService } from "./ai-decide.ts";
|
|
8
9
|
import { type ModelRegistry } from "./registry.ts";
|
|
9
10
|
import { type SmartRouterService, type SmartRouterStore } from "./smart-router.ts";
|
|
10
11
|
/** Model gateway runtime configuration. */
|
|
@@ -18,6 +19,7 @@ export interface ModelGatewayOptions {
|
|
|
18
19
|
readonly smartRouterTimeoutMs?: number;
|
|
19
20
|
readonly smartRouterService?: SmartRouterService;
|
|
20
21
|
readonly smartRouterStore?: SmartRouterStore;
|
|
22
|
+
readonly aiDecideService?: AiDecideRouterService;
|
|
21
23
|
readonly overrides?: readonly ModelCapabilityOverride[];
|
|
22
24
|
readonly model?: string;
|
|
23
25
|
readonly modelClass?: ModelClassType;
|
|
@@ -32,13 +34,14 @@ export declare class ModelGatewayError extends Error {
|
|
|
32
34
|
export declare class ModelGateway {
|
|
33
35
|
private readonly registry;
|
|
34
36
|
private readonly smartRouter?;
|
|
37
|
+
private readonly aiDecide;
|
|
35
38
|
private readonly smartRouterMode;
|
|
36
39
|
private readonly model?;
|
|
37
40
|
private readonly modelClass?;
|
|
38
41
|
private readonly preferSystemModels;
|
|
39
42
|
constructor(options?: ModelGatewayOptions, registry?: ModelRegistry);
|
|
40
43
|
/** Return the live OpenAI model list, including Codex metadata when requested. */
|
|
41
|
-
models(originator?: string, search?: string): Promise<ModelListResponse>;
|
|
44
|
+
models(originator?: string, search?: string, modelSource?: ModelSource | "all", includeMetadata?: boolean): Promise<ModelListResponse>;
|
|
42
45
|
/** Resolve and execute one inference request. */
|
|
43
46
|
inference(protocol: ClientProtocol, body: Readonly<Record<string, unknown>>, headers: Headers, signal: AbortSignal): Promise<Response>;
|
|
44
47
|
/** Refresh the active principal's model catalogue. */
|
|
@@ -55,6 +58,7 @@ export declare function gatewayModelSelection(body: Readonly<Record<string, unkn
|
|
|
55
58
|
readonly modelClass?: ModelClassType;
|
|
56
59
|
}, protocol?: ClientProtocol): {
|
|
57
60
|
readonly smartRouter?: boolean;
|
|
61
|
+
readonly aiDecide?: boolean;
|
|
58
62
|
readonly model?: string;
|
|
59
63
|
readonly modelClass?: ModelClassType;
|
|
60
64
|
};
|