@dbx-tools/model 0.3.43 → 0.4.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/lib/index.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ export * as classes from "./src/classes.js";
2
+ export * as fallback from "./src/fallback.js";
3
+ export * as invoke from "./src/invoke.js";
4
+ export * as resolve from "./src/resolve.js";
5
+ export * as serving from "./src/serving.js";
6
+ export { CHAT_CLASS_ORDER, MODEL_CLASS_ORDER, isChatClass, parseModelClass, classesAtOrBelow } from "./src/classes.js";
7
+ export { modelsForClass, modelForClass, FALLBACK_MODEL_IDS } from "./src/fallback.js";
8
+ export { INVOCATIONS_SUFFIX, RESPONSES_PATH, OPEN_RESPONSES_PATH, CHAT_COMPLETIONS_PATH, invocationsUrl, responsesUrl, openResponsesUrl, chatCompletionsUrl, isResponsesOnly, responsesUpstreamUrl, authHeaders } from "./src/invoke.js";
9
+ export type { AuthenticatingClientLike } from "./src/invoke.js";
10
+ export { rankModels, rankModelId, rankModelIdLive, searchModels, selectModel, resolveModel } from "./src/resolve.js";
11
+ export type { ResolveModelInput, ResolvedModelSelection, SelectModelInput, SearchModelsInput } from "./src/resolve.js";
12
+ export { DEFAULT_MODEL_CACHE_TTL_MS, DEFAULT_FUZZY_THRESHOLD, listServingEndpoints, listServingEndpointsUncached, clearServingEndpointsCache, searchServingEndpoints, resolveModelId } from "./src/serving.js";
13
+ export type { WorkspaceClientLike, ListServingEndpointsOptions, ResolvedModel, ResolveModelOptions, ScoredEndpoint } from "./src/serving.js";
package/lib/index.js ADDED
@@ -0,0 +1,14 @@
1
+ // GENERATED by projen watch - DO NOT EDIT.
2
+ // Regenerated from the exporting modules in ./src.
3
+ // Hand edits are overwritten on the next watch; this file is read-only.
4
+ export * as classes from "./src/classes.js";
5
+ export * as fallback from "./src/fallback.js";
6
+ export * as invoke from "./src/invoke.js";
7
+ export * as resolve from "./src/resolve.js";
8
+ export * as serving from "./src/serving.js";
9
+ export { CHAT_CLASS_ORDER, MODEL_CLASS_ORDER, isChatClass, parseModelClass, classesAtOrBelow } from "./src/classes.js";
10
+ export { modelsForClass, modelForClass, FALLBACK_MODEL_IDS } from "./src/fallback.js";
11
+ export { INVOCATIONS_SUFFIX, RESPONSES_PATH, OPEN_RESPONSES_PATH, CHAT_COMPLETIONS_PATH, invocationsUrl, responsesUrl, openResponsesUrl, chatCompletionsUrl, isResponsesOnly, responsesUpstreamUrl, authHeaders } from "./src/invoke.js";
12
+ export { rankModels, rankModelId, rankModelIdLive, searchModels, selectModel, resolveModel } from "./src/resolve.js";
13
+ export { DEFAULT_MODEL_CACHE_TTL_MS, DEFAULT_FUZZY_THRESHOLD, listServingEndpoints, listServingEndpointsUncached, clearServingEndpointsCache, searchServingEndpoints, resolveModelId } from "./src/serving.js";
14
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEtBQUssUUFBUSxNQUFNLGdCQUFnQixDQUFDO0FBQzNDLE9BQU8sS0FBSyxNQUFNLE1BQU0sY0FBYyxDQUFDO0FBQ3ZDLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxpQkFBaUIsRUFBRSxXQUFXLEVBQUUsZUFBZSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3BILE9BQU8sRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLGtCQUFrQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbkYsT0FBTyxFQUFFLGtCQUFrQixFQUFFLGNBQWMsRUFBRSxtQkFBbUIsRUFBRSxxQkFBcUIsRUFBRSxjQUFjLEVBQUUsWUFBWSxFQUFFLGdCQUFnQixFQUFFLGtCQUFrQixFQUFFLGVBQWUsRUFBRSxvQkFBb0IsRUFBRSxXQUFXLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFdE8sT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRWxILE9BQU8sRUFBRSwwQkFBMEIsRUFBRSx1QkFBdUIsRUFBRSxvQkFBb0IsRUFBRSw0QkFBNEIsRUFBRSwwQkFBMEIsRUFBRSxzQkFBc0IsRUFBRSxjQUFjLEVBQUUsTUFBTSxlQUFlLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBHRU5FUkFURUQgYnkgcHJvamVuIHdhdGNoIC0gRE8gTk9UIEVESVQuXG4vLyBSZWdlbmVyYXRlZCBmcm9tIHRoZSBleHBvcnRpbmcgbW9kdWxlcyBpbiAuL3NyYy5cbi8vIEhhbmQgZWRpdHMgYXJlIG92ZXJ3cml0dGVuIG9uIHRoZSBuZXh0IHdhdGNoOyB0aGlzIGZpbGUgaXMgcmVhZC1vbmx5LlxuXG5leHBvcnQgKiBhcyBjbGFzc2VzIGZyb20gXCIuL3NyYy9jbGFzc2VzXCI7XG5leHBvcnQgKiBhcyBmYWxsYmFjayBmcm9tIFwiLi9zcmMvZmFsbGJhY2tcIjtcbmV4cG9ydCAqIGFzIGludm9rZSBmcm9tIFwiLi9zcmMvaW52b2tlXCI7XG5leHBvcnQgKiBhcyByZXNvbHZlIGZyb20gXCIuL3NyYy9yZXNvbHZlXCI7XG5leHBvcnQgKiBhcyBzZXJ2aW5nIGZyb20gXCIuL3NyYy9zZXJ2aW5nXCI7XG5leHBvcnQgeyBDSEFUX0NMQVNTX09SREVSLCBNT0RFTF9DTEFTU19PUkRFUiwgaXNDaGF0Q2xhc3MsIHBhcnNlTW9kZWxDbGFzcywgY2xhc3Nlc0F0T3JCZWxvdyB9IGZyb20gXCIuL3NyYy9jbGFzc2VzXCI7XG5leHBvcnQgeyBtb2RlbHNGb3JDbGFzcywgbW9kZWxGb3JDbGFzcywgRkFMTEJBQ0tfTU9ERUxfSURTIH0gZnJvbSBcIi4vc3JjL2ZhbGxiYWNrXCI7XG5leHBvcnQgeyBJTlZPQ0FUSU9OU19TVUZGSVgsIFJFU1BPTlNFU19QQVRILCBPUEVOX1JFU1BPTlNFU19QQVRILCBDSEFUX0NPTVBMRVRJT05TX1BBVEgsIGludm9jYXRpb25zVXJsLCByZXNwb25zZXNVcmwsIG9wZW5SZXNwb25zZXNVcmwsIGNoYXRDb21wbGV0aW9uc1VybCwgaXNSZXNwb25zZXNPbmx5LCByZXNwb25zZXNVcHN0cmVhbVVybCwgYXV0aEhlYWRlcnMgfSBmcm9tIFwiLi9zcmMvaW52b2tlXCI7XG5leHBvcnQgdHlwZSB7IEF1dGhlbnRpY2F0aW5nQ2xpZW50TGlrZSB9IGZyb20gXCIuL3NyYy9pbnZva2VcIjtcbmV4cG9ydCB7IHJhbmtNb2RlbHMsIHJhbmtNb2RlbElkLCByYW5rTW9kZWxJZExpdmUsIHNlYXJjaE1vZGVscywgc2VsZWN0TW9kZWwsIHJlc29sdmVNb2RlbCB9IGZyb20gXCIuL3NyYy9yZXNvbHZlXCI7XG5leHBvcnQgdHlwZSB7IFJlc29sdmVNb2RlbElucHV0LCBSZXNvbHZlZE1vZGVsU2VsZWN0aW9uLCBTZWxlY3RNb2RlbElucHV0LCBTZWFyY2hNb2RlbHNJbnB1dCB9IGZyb20gXCIuL3NyYy9yZXNvbHZlXCI7XG5leHBvcnQgeyBERUZBVUxUX01PREVMX0NBQ0hFX1RUTF9NUywgREVGQVVMVF9GVVpaWV9USFJFU0hPTEQsIGxpc3RTZXJ2aW5nRW5kcG9pbnRzLCBsaXN0U2VydmluZ0VuZHBvaW50c1VuY2FjaGVkLCBjbGVhclNlcnZpbmdFbmRwb2ludHNDYWNoZSwgc2VhcmNoU2VydmluZ0VuZHBvaW50cywgcmVzb2x2ZU1vZGVsSWQgfSBmcm9tIFwiLi9zcmMvc2VydmluZ1wiO1xuZXhwb3J0IHR5cGUgeyBXb3Jrc3BhY2VDbGllbnRMaWtlLCBMaXN0U2VydmluZ0VuZHBvaW50c09wdGlvbnMsIFJlc29sdmVkTW9kZWwsIFJlc29sdmVNb2RlbE9wdGlvbnMsIFNjb3JlZEVuZHBvaW50IH0gZnJvbSBcIi4vc3JjL3NlcnZpbmdcIjtcbiJdfQ==
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Model-class ordering for the model service.
3
+ *
4
+ * `@dbx-tools/shared-model` declares the {@link ModelClass} values and their
5
+ * schema; the *behavior* over those values - the chat capability order, the
6
+ * "this class and below" ceiling, and coercing loose request input to a class -
7
+ * lives here in the service so the shared wire-format surface stays purely
8
+ * declarative.
9
+ *
10
+ * @module
11
+ */
12
+ import { model } from "@dbx-tools/shared-model";
13
+ type ModelClass = model.ModelClass;
14
+ declare const ModelClass: typeof model.ModelClass;
15
+ /**
16
+ * Chat capability ladder in descending order - most capable
17
+ * ({@link ModelClass.ChatThinking}) first, least ({@link ModelClass.ChatFast})
18
+ * last. {@link ModelClass.Embedding} is a separate modality and is deliberately
19
+ * absent: the ceiling never spans it. This is the order used to filter "this
20
+ * class and below" and to break ranking ties toward the more capable model.
21
+ */
22
+ export declare const CHAT_CLASS_ORDER: readonly ModelClass[];
23
+ /**
24
+ * Every class in display order: the chat ladder followed by
25
+ * {@link ModelClass.Embedding}. Used when flattening a full classification
26
+ * (e.g. stamping the class onto each cached endpoint).
27
+ */
28
+ export declare const MODEL_CLASS_ORDER: readonly ModelClass[];
29
+ /** Whether `cls` is one of the chat capability bands (vs. embedding). */
30
+ export declare function isChatClass(cls: ModelClass): boolean;
31
+ /**
32
+ * Coerce an arbitrary value (query string, header, body field) to a
33
+ * {@link ModelClass}, returning `null` when it isn't a known class. Lets a
34
+ * route accept a class request without throwing on junk input.
35
+ *
36
+ * Matches the full slug first (`"chat-fast"`, `"embedding"`), then - for a bare
37
+ * chat band - retries with a `chat-` prefix, so the shorthand `"thinking"` /
38
+ * `"balanced"` / `"fast"` resolves to the corresponding `chat-*` class.
39
+ */
40
+ export declare function parseModelClass(value: unknown): ModelClass | null;
41
+ /**
42
+ * Classes at or below `cls` in chat capability: the class itself plus every
43
+ * less-capable chat band, in {@link CHAT_CLASS_ORDER}. Treats a chat `cls` as a
44
+ * ceiling - requesting {@link ModelClass.ChatBalanced} yields
45
+ * `[ChatBalanced, ChatFast]`, never {@link ModelClass.ChatThinking} - so a
46
+ * class ask can degrade downward to a smaller chat model but never escalate to
47
+ * a larger one.
48
+ *
49
+ * {@link ModelClass.Embedding} is its own modality, not a rung on the chat
50
+ * ladder, so it yields just `[Embedding]`. An unrecognized class yields the
51
+ * full chat ladder.
52
+ */
53
+ export declare function classesAtOrBelow(cls: ModelClass): ModelClass[];
54
+ export {};
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Model-class ordering for the model service.
3
+ *
4
+ * `@dbx-tools/shared-model` declares the {@link ModelClass} values and their
5
+ * schema; the *behavior* over those values - the chat capability order, the
6
+ * "this class and below" ceiling, and coercing loose request input to a class -
7
+ * lives here in the service so the shared wire-format surface stays purely
8
+ * declarative.
9
+ *
10
+ * @module
11
+ */
12
+ import { model } from "@dbx-tools/shared-model";
13
+ const { ModelClass, ModelClassSchema } = model;
14
+ /**
15
+ * Chat capability ladder in descending order - most capable
16
+ * ({@link ModelClass.ChatThinking}) first, least ({@link ModelClass.ChatFast})
17
+ * last. {@link ModelClass.Embedding} is a separate modality and is deliberately
18
+ * absent: the ceiling never spans it. This is the order used to filter "this
19
+ * class and below" and to break ranking ties toward the more capable model.
20
+ */
21
+ export const CHAT_CLASS_ORDER = [
22
+ ModelClass.ChatThinking,
23
+ ModelClass.ChatBalanced,
24
+ ModelClass.ChatFast,
25
+ ];
26
+ /**
27
+ * Every class in display order: the chat ladder followed by
28
+ * {@link ModelClass.Embedding}. Used when flattening a full classification
29
+ * (e.g. stamping the class onto each cached endpoint).
30
+ */
31
+ export const MODEL_CLASS_ORDER = [...CHAT_CLASS_ORDER, ModelClass.Embedding];
32
+ /** Whether `cls` is one of the chat capability bands (vs. embedding). */
33
+ export function isChatClass(cls) {
34
+ return CHAT_CLASS_ORDER.includes(cls);
35
+ }
36
+ /**
37
+ * Coerce an arbitrary value (query string, header, body field) to a
38
+ * {@link ModelClass}, returning `null` when it isn't a known class. Lets a
39
+ * route accept a class request without throwing on junk input.
40
+ *
41
+ * Matches the full slug first (`"chat-fast"`, `"embedding"`), then - for a bare
42
+ * chat band - retries with a `chat-` prefix, so the shorthand `"thinking"` /
43
+ * `"balanced"` / `"fast"` resolves to the corresponding `chat-*` class.
44
+ */
45
+ export function parseModelClass(value) {
46
+ const exact = ModelClassSchema.safeParse(value);
47
+ if (exact.success)
48
+ return exact.data;
49
+ const prefixed = ModelClassSchema.safeParse(`chat-${value}`);
50
+ return prefixed.success ? prefixed.data : null;
51
+ }
52
+ /**
53
+ * Classes at or below `cls` in chat capability: the class itself plus every
54
+ * less-capable chat band, in {@link CHAT_CLASS_ORDER}. Treats a chat `cls` as a
55
+ * ceiling - requesting {@link ModelClass.ChatBalanced} yields
56
+ * `[ChatBalanced, ChatFast]`, never {@link ModelClass.ChatThinking} - so a
57
+ * class ask can degrade downward to a smaller chat model but never escalate to
58
+ * a larger one.
59
+ *
60
+ * {@link ModelClass.Embedding} is its own modality, not a rung on the chat
61
+ * ladder, so it yields just `[Embedding]`. An unrecognized class yields the
62
+ * full chat ladder.
63
+ */
64
+ export function classesAtOrBelow(cls) {
65
+ if (cls === ModelClass.Embedding)
66
+ return [ModelClass.Embedding];
67
+ const index = CHAT_CLASS_ORDER.indexOf(cls);
68
+ return index < 0 ? [...CHAT_CLASS_ORDER] : [...CHAT_CLASS_ORDER.slice(index)];
69
+ }
70
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbGFzc2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7O0dBVUc7QUFFSCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHaEQsTUFBTSxFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsRUFBRSxHQUFHLEtBQUssQ0FBQztBQUUvQzs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBMEI7SUFDckQsVUFBVSxDQUFDLFlBQVk7SUFDdkIsVUFBVSxDQUFDLFlBQVk7SUFDdkIsVUFBVSxDQUFDLFFBQVE7Q0FDcEIsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBMEIsQ0FBQyxHQUFHLGdCQUFnQixFQUFFLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUVwRyx5RUFBeUU7QUFDekUsTUFBTSxVQUFVLFdBQVcsQ0FBQyxHQUFlO0lBQ3pDLE9BQU8sZ0JBQWdCLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ3hDLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQUMsS0FBYztJQUM1QyxNQUFNLEtBQUssR0FBRyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDaEQsSUFBSSxLQUFLLENBQUMsT0FBTztRQUFFLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQztJQUNyQyxNQUFNLFFBQVEsR0FBRyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsUUFBUSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQzdELE9BQU8sUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0FBQ2pELENBQUM7QUFFRDs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxHQUFlO0lBQzlDLElBQUksR0FBRyxLQUFLLFVBQVUsQ0FBQyxTQUFTO1FBQUUsT0FBTyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNoRSxNQUFNLEtBQUssR0FBRyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDNUMsT0FBTyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQ2hGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE1vZGVsLWNsYXNzIG9yZGVyaW5nIGZvciB0aGUgbW9kZWwgc2VydmljZS5cbiAqXG4gKiBgQGRieC10b29scy9zaGFyZWQtbW9kZWxgIGRlY2xhcmVzIHRoZSB7QGxpbmsgTW9kZWxDbGFzc30gdmFsdWVzIGFuZCB0aGVpclxuICogc2NoZW1hOyB0aGUgKmJlaGF2aW9yKiBvdmVyIHRob3NlIHZhbHVlcyAtIHRoZSBjaGF0IGNhcGFiaWxpdHkgb3JkZXIsIHRoZVxuICogXCJ0aGlzIGNsYXNzIGFuZCBiZWxvd1wiIGNlaWxpbmcsIGFuZCBjb2VyY2luZyBsb29zZSByZXF1ZXN0IGlucHV0IHRvIGEgY2xhc3MgLVxuICogbGl2ZXMgaGVyZSBpbiB0aGUgc2VydmljZSBzbyB0aGUgc2hhcmVkIHdpcmUtZm9ybWF0IHN1cmZhY2Ugc3RheXMgcHVyZWx5XG4gKiBkZWNsYXJhdGl2ZS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgbW9kZWwgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtbW9kZWxcIjtcblxudHlwZSBNb2RlbENsYXNzID0gbW9kZWwuTW9kZWxDbGFzcztcbmNvbnN0IHsgTW9kZWxDbGFzcywgTW9kZWxDbGFzc1NjaGVtYSB9ID0gbW9kZWw7XG5cbi8qKlxuICogQ2hhdCBjYXBhYmlsaXR5IGxhZGRlciBpbiBkZXNjZW5kaW5nIG9yZGVyIC0gbW9zdCBjYXBhYmxlXG4gKiAoe0BsaW5rIE1vZGVsQ2xhc3MuQ2hhdFRoaW5raW5nfSkgZmlyc3QsIGxlYXN0ICh7QGxpbmsgTW9kZWxDbGFzcy5DaGF0RmFzdH0pXG4gKiBsYXN0LiB7QGxpbmsgTW9kZWxDbGFzcy5FbWJlZGRpbmd9IGlzIGEgc2VwYXJhdGUgbW9kYWxpdHkgYW5kIGlzIGRlbGliZXJhdGVseVxuICogYWJzZW50OiB0aGUgY2VpbGluZyBuZXZlciBzcGFucyBpdC4gVGhpcyBpcyB0aGUgb3JkZXIgdXNlZCB0byBmaWx0ZXIgXCJ0aGlzXG4gKiBjbGFzcyBhbmQgYmVsb3dcIiBhbmQgdG8gYnJlYWsgcmFua2luZyB0aWVzIHRvd2FyZCB0aGUgbW9yZSBjYXBhYmxlIG1vZGVsLlxuICovXG5leHBvcnQgY29uc3QgQ0hBVF9DTEFTU19PUkRFUjogcmVhZG9ubHkgTW9kZWxDbGFzc1tdID0gW1xuICBNb2RlbENsYXNzLkNoYXRUaGlua2luZyxcbiAgTW9kZWxDbGFzcy5DaGF0QmFsYW5jZWQsXG4gIE1vZGVsQ2xhc3MuQ2hhdEZhc3QsXG5dO1xuXG4vKipcbiAqIEV2ZXJ5IGNsYXNzIGluIGRpc3BsYXkgb3JkZXI6IHRoZSBjaGF0IGxhZGRlciBmb2xsb3dlZCBieVxuICoge0BsaW5rIE1vZGVsQ2xhc3MuRW1iZWRkaW5nfS4gVXNlZCB3aGVuIGZsYXR0ZW5pbmcgYSBmdWxsIGNsYXNzaWZpY2F0aW9uXG4gKiAoZS5nLiBzdGFtcGluZyB0aGUgY2xhc3Mgb250byBlYWNoIGNhY2hlZCBlbmRwb2ludCkuXG4gKi9cbmV4cG9ydCBjb25zdCBNT0RFTF9DTEFTU19PUkRFUjogcmVhZG9ubHkgTW9kZWxDbGFzc1tdID0gWy4uLkNIQVRfQ0xBU1NfT1JERVIsIE1vZGVsQ2xhc3MuRW1iZWRkaW5nXTtcblxuLyoqIFdoZXRoZXIgYGNsc2AgaXMgb25lIG9mIHRoZSBjaGF0IGNhcGFiaWxpdHkgYmFuZHMgKHZzLiBlbWJlZGRpbmcpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQ2hhdENsYXNzKGNsczogTW9kZWxDbGFzcyk6IGJvb2xlYW4ge1xuICByZXR1cm4gQ0hBVF9DTEFTU19PUkRFUi5pbmNsdWRlcyhjbHMpO1xufVxuXG4vKipcbiAqIENvZXJjZSBhbiBhcmJpdHJhcnkgdmFsdWUgKHF1ZXJ5IHN0cmluZywgaGVhZGVyLCBib2R5IGZpZWxkKSB0byBhXG4gKiB7QGxpbmsgTW9kZWxDbGFzc30sIHJldHVybmluZyBgbnVsbGAgd2hlbiBpdCBpc24ndCBhIGtub3duIGNsYXNzLiBMZXRzIGFcbiAqIHJvdXRlIGFjY2VwdCBhIGNsYXNzIHJlcXVlc3Qgd2l0aG91dCB0aHJvd2luZyBvbiBqdW5rIGlucHV0LlxuICpcbiAqIE1hdGNoZXMgdGhlIGZ1bGwgc2x1ZyBmaXJzdCAoYFwiY2hhdC1mYXN0XCJgLCBgXCJlbWJlZGRpbmdcImApLCB0aGVuIC0gZm9yIGEgYmFyZVxuICogY2hhdCBiYW5kIC0gcmV0cmllcyB3aXRoIGEgYGNoYXQtYCBwcmVmaXgsIHNvIHRoZSBzaG9ydGhhbmQgYFwidGhpbmtpbmdcImAgL1xuICogYFwiYmFsYW5jZWRcImAgLyBgXCJmYXN0XCJgIHJlc29sdmVzIHRvIHRoZSBjb3JyZXNwb25kaW5nIGBjaGF0LSpgIGNsYXNzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VNb2RlbENsYXNzKHZhbHVlOiB1bmtub3duKTogTW9kZWxDbGFzcyB8IG51bGwge1xuICBjb25zdCBleGFjdCA9IE1vZGVsQ2xhc3NTY2hlbWEuc2FmZVBhcnNlKHZhbHVlKTtcbiAgaWYgKGV4YWN0LnN1Y2Nlc3MpIHJldHVybiBleGFjdC5kYXRhO1xuICBjb25zdCBwcmVmaXhlZCA9IE1vZGVsQ2xhc3NTY2hlbWEuc2FmZVBhcnNlKGBjaGF0LSR7dmFsdWV9YCk7XG4gIHJldHVybiBwcmVmaXhlZC5zdWNjZXNzID8gcHJlZml4ZWQuZGF0YSA6IG51bGw7XG59XG5cbi8qKlxuICogQ2xhc3NlcyBhdCBvciBiZWxvdyBgY2xzYCBpbiBjaGF0IGNhcGFiaWxpdHk6IHRoZSBjbGFzcyBpdHNlbGYgcGx1cyBldmVyeVxuICogbGVzcy1jYXBhYmxlIGNoYXQgYmFuZCwgaW4ge0BsaW5rIENIQVRfQ0xBU1NfT1JERVJ9LiBUcmVhdHMgYSBjaGF0IGBjbHNgIGFzIGFcbiAqIGNlaWxpbmcgLSByZXF1ZXN0aW5nIHtAbGluayBNb2RlbENsYXNzLkNoYXRCYWxhbmNlZH0geWllbGRzXG4gKiBgW0NoYXRCYWxhbmNlZCwgQ2hhdEZhc3RdYCwgbmV2ZXIge0BsaW5rIE1vZGVsQ2xhc3MuQ2hhdFRoaW5raW5nfSAtIHNvIGFcbiAqIGNsYXNzIGFzayBjYW4gZGVncmFkZSBkb3dud2FyZCB0byBhIHNtYWxsZXIgY2hhdCBtb2RlbCBidXQgbmV2ZXIgZXNjYWxhdGUgdG9cbiAqIGEgbGFyZ2VyIG9uZS5cbiAqXG4gKiB7QGxpbmsgTW9kZWxDbGFzcy5FbWJlZGRpbmd9IGlzIGl0cyBvd24gbW9kYWxpdHksIG5vdCBhIHJ1bmcgb24gdGhlIGNoYXRcbiAqIGxhZGRlciwgc28gaXQgeWllbGRzIGp1c3QgYFtFbWJlZGRpbmddYC4gQW4gdW5yZWNvZ25pemVkIGNsYXNzIHlpZWxkcyB0aGVcbiAqIGZ1bGwgY2hhdCBsYWRkZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGFzc2VzQXRPckJlbG93KGNsczogTW9kZWxDbGFzcyk6IE1vZGVsQ2xhc3NbXSB7XG4gIGlmIChjbHMgPT09IE1vZGVsQ2xhc3MuRW1iZWRkaW5nKSByZXR1cm4gW01vZGVsQ2xhc3MuRW1iZWRkaW5nXTtcbiAgY29uc3QgaW5kZXggPSBDSEFUX0NMQVNTX09SREVSLmluZGV4T2YoY2xzKTtcbiAgcmV0dXJuIGluZGV4IDwgMCA/IFsuLi5DSEFUX0NMQVNTX09SREVSXSA6IFsuLi5DSEFUX0NMQVNTX09SREVSLnNsaWNlKGluZGV4KV07XG59XG4iXX0=
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Server-side offline fallback opinion for model selection.
3
+ *
4
+ * When the live `/serving-endpoints` catalogue can't be read at all - no user
5
+ * token, the service principal can't list, or the workspace is unreachable -
6
+ * the resolver still has to name *some* endpoint. This module holds that floor:
7
+ * a small, hard-coded set of well-known Foundation Model API endpoint names,
8
+ * each bucketed into a chat {@link ModelClass} by the shared
9
+ * {@link classify.classifyByFamily} heuristic (no classes are hard-coded here)
10
+ * and ordered best-first.
11
+ *
12
+ * This is deliberately *server-only*. A browser client never talks to
13
+ * Databricks directly - it always goes through this server - so it has nothing
14
+ * to fall back to and must not assume a stale, baked-in model list; it consumes
15
+ * the live `/models` response instead. The pure classifier
16
+ * ({@link classify.classifyEndpoints}) is what the client shares.
17
+ *
18
+ * @module
19
+ */
20
+ import { model } from "@dbx-tools/shared-model";
21
+ type ModelClass = model.ModelClass;
22
+ declare const ModelClass: typeof model.ModelClass;
23
+ /**
24
+ * Static fallback model ids for a chat class, drawn from the small built-in
25
+ * {@link FALLBACK_MODEL_NAMES} list and ordered best-first by family rank. Sync
26
+ * and workspace-independent: this is the *fallback opinion* used to seed default
27
+ * lists or when the live catalogue is unreachable - live resolution prefers
28
+ * {@link classify.classifyEndpoints}. Returns `[]` for
29
+ * {@link ModelClass.Embedding} (the floor is chat-only).
30
+ */
31
+ export declare function modelsForClass(cls: ModelClass): readonly string[];
32
+ /** Top static fallback model id for a chat class. */
33
+ export declare function modelForClass(cls: ModelClass): string;
34
+ /**
35
+ * Priority-ordered fallback chain (ChatThinking -> ChatBalanced -> ChatFast)
36
+ * over the small built-in list. The floor walked at resolve time when no agent
37
+ * / plugin / env / request model is set *and* the live catalogue yields nothing.
38
+ */
39
+ export declare const FALLBACK_MODEL_IDS: readonly string[];
40
+ export {};
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Server-side offline fallback opinion for model selection.
3
+ *
4
+ * When the live `/serving-endpoints` catalogue can't be read at all - no user
5
+ * token, the service principal can't list, or the workspace is unreachable -
6
+ * the resolver still has to name *some* endpoint. This module holds that floor:
7
+ * a small, hard-coded set of well-known Foundation Model API endpoint names,
8
+ * each bucketed into a chat {@link ModelClass} by the shared
9
+ * {@link classify.classifyByFamily} heuristic (no classes are hard-coded here)
10
+ * and ordered best-first.
11
+ *
12
+ * This is deliberately *server-only*. A browser client never talks to
13
+ * Databricks directly - it always goes through this server - so it has nothing
14
+ * to fall back to and must not assume a stale, baked-in model list; it consumes
15
+ * the live `/models` response instead. The pure classifier
16
+ * ({@link classify.classifyEndpoints}) is what the client shares.
17
+ *
18
+ * @module
19
+ */
20
+ import { classify, model } from "@dbx-tools/shared-model";
21
+ const { ModelClass } = model;
22
+ /**
23
+ * Small, last-resort set of well-known Foundation Model API endpoint names,
24
+ * ordered best-first within each class by {@link classify.classifyByFamily}.
25
+ * Used only as the floor when the live `/serving-endpoints` catalogue can't be
26
+ * read at resolve time; the live, score-driven classification supersedes it
27
+ * whenever the workspace listing is available. Classes are not hard-coded here
28
+ * - each name is classified by family heuristic.
29
+ */
30
+ const FALLBACK_MODEL_NAMES = [
31
+ "databricks-claude-opus-4-8",
32
+ "databricks-gpt-5-5-pro",
33
+ "databricks-gemini-3-1-pro",
34
+ "databricks-claude-sonnet-4-6",
35
+ "databricks-gpt-5-5",
36
+ "databricks-meta-llama-3-3-70b-instruct",
37
+ "databricks-claude-haiku-4-5",
38
+ "databricks-gpt-5-nano",
39
+ "databricks-meta-llama-3-1-8b-instruct",
40
+ ];
41
+ /**
42
+ * Static fallback model ids for a chat class, drawn from the small built-in
43
+ * {@link FALLBACK_MODEL_NAMES} list and ordered best-first by family rank. Sync
44
+ * and workspace-independent: this is the *fallback opinion* used to seed default
45
+ * lists or when the live catalogue is unreachable - live resolution prefers
46
+ * {@link classify.classifyEndpoints}. Returns `[]` for
47
+ * {@link ModelClass.Embedding} (the floor is chat-only).
48
+ */
49
+ export function modelsForClass(cls) {
50
+ return FALLBACK_MODEL_NAMES.map((name) => ({ name, c: classify.classifyByFamily(name) }))
51
+ .filter((x) => x.c !== null && x.c.class === cls)
52
+ .sort((a, b) => b.c.rank - a.c.rank)
53
+ .map((x) => x.name);
54
+ }
55
+ /** Top static fallback model id for a chat class. */
56
+ export function modelForClass(cls) {
57
+ return modelsForClass(cls)[0];
58
+ }
59
+ /**
60
+ * Priority-ordered fallback chain (ChatThinking -> ChatBalanced -> ChatFast)
61
+ * over the small built-in list. The floor walked at resolve time when no agent
62
+ * / plugin / env / request model is set *and* the live catalogue yields nothing.
63
+ */
64
+ export const FALLBACK_MODEL_IDS = [
65
+ ...modelsForClass(ModelClass.ChatThinking),
66
+ ...modelsForClass(ModelClass.ChatBalanced),
67
+ ...modelsForClass(ModelClass.ChatFast),
68
+ ];
69
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFsbGJhY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZmFsbGJhY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtCRztBQUVILE9BQU8sRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFvQixNQUFNLHlCQUF5QixDQUFDO0FBRzVFLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRyxLQUFLLENBQUM7QUFFN0I7Ozs7Ozs7R0FPRztBQUNILE1BQU0sb0JBQW9CLEdBQXNCO0lBQzlDLDRCQUE0QjtJQUM1Qix3QkFBd0I7SUFDeEIsMkJBQTJCO0lBQzNCLDhCQUE4QjtJQUM5QixvQkFBb0I7SUFDcEIsd0NBQXdDO0lBQ3hDLDZCQUE2QjtJQUM3Qix1QkFBdUI7SUFDdkIsdUNBQXVDO0NBQ3hDLENBQUM7QUFFRjs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FBQyxHQUFlO0lBQzVDLE9BQU8sb0JBQW9CLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxRQUFRLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQ3RGLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBeUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLEdBQUcsQ0FBQztTQUN2RixJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztTQUNuQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUN4QixDQUFDO0FBRUQscURBQXFEO0FBQ3JELE1BQU0sVUFBVSxhQUFhLENBQUMsR0FBZTtJQUMzQyxPQUFPLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUUsQ0FBQztBQUNqQyxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFzQjtJQUNuRCxHQUFHLGNBQWMsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDO0lBQzFDLEdBQUcsY0FBYyxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUM7SUFDMUMsR0FBRyxjQUFjLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQztDQUN2QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBTZXJ2ZXItc2lkZSBvZmZsaW5lIGZhbGxiYWNrIG9waW5pb24gZm9yIG1vZGVsIHNlbGVjdGlvbi5cbiAqXG4gKiBXaGVuIHRoZSBsaXZlIGAvc2VydmluZy1lbmRwb2ludHNgIGNhdGFsb2d1ZSBjYW4ndCBiZSByZWFkIGF0IGFsbCAtIG5vIHVzZXJcbiAqIHRva2VuLCB0aGUgc2VydmljZSBwcmluY2lwYWwgY2FuJ3QgbGlzdCwgb3IgdGhlIHdvcmtzcGFjZSBpcyB1bnJlYWNoYWJsZSAtXG4gKiB0aGUgcmVzb2x2ZXIgc3RpbGwgaGFzIHRvIG5hbWUgKnNvbWUqIGVuZHBvaW50LiBUaGlzIG1vZHVsZSBob2xkcyB0aGF0IGZsb29yOlxuICogYSBzbWFsbCwgaGFyZC1jb2RlZCBzZXQgb2Ygd2VsbC1rbm93biBGb3VuZGF0aW9uIE1vZGVsIEFQSSBlbmRwb2ludCBuYW1lcyxcbiAqIGVhY2ggYnVja2V0ZWQgaW50byBhIGNoYXQge0BsaW5rIE1vZGVsQ2xhc3N9IGJ5IHRoZSBzaGFyZWRcbiAqIHtAbGluayBjbGFzc2lmeS5jbGFzc2lmeUJ5RmFtaWx5fSBoZXVyaXN0aWMgKG5vIGNsYXNzZXMgYXJlIGhhcmQtY29kZWQgaGVyZSlcbiAqIGFuZCBvcmRlcmVkIGJlc3QtZmlyc3QuXG4gKlxuICogVGhpcyBpcyBkZWxpYmVyYXRlbHkgKnNlcnZlci1vbmx5Ki4gQSBicm93c2VyIGNsaWVudCBuZXZlciB0YWxrcyB0b1xuICogRGF0YWJyaWNrcyBkaXJlY3RseSAtIGl0IGFsd2F5cyBnb2VzIHRocm91Z2ggdGhpcyBzZXJ2ZXIgLSBzbyBpdCBoYXMgbm90aGluZ1xuICogdG8gZmFsbCBiYWNrIHRvIGFuZCBtdXN0IG5vdCBhc3N1bWUgYSBzdGFsZSwgYmFrZWQtaW4gbW9kZWwgbGlzdDsgaXQgY29uc3VtZXNcbiAqIHRoZSBsaXZlIGAvbW9kZWxzYCByZXNwb25zZSBpbnN0ZWFkLiBUaGUgcHVyZSBjbGFzc2lmaWVyXG4gKiAoe0BsaW5rIGNsYXNzaWZ5LmNsYXNzaWZ5RW5kcG9pbnRzfSkgaXMgd2hhdCB0aGUgY2xpZW50IHNoYXJlcy5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgY2xhc3NpZnksIG1vZGVsLCB0eXBlIEZhbWlseUNsYXNzIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLW1vZGVsXCI7XG5cbnR5cGUgTW9kZWxDbGFzcyA9IG1vZGVsLk1vZGVsQ2xhc3M7XG5jb25zdCB7IE1vZGVsQ2xhc3MgfSA9IG1vZGVsO1xuXG4vKipcbiAqIFNtYWxsLCBsYXN0LXJlc29ydCBzZXQgb2Ygd2VsbC1rbm93biBGb3VuZGF0aW9uIE1vZGVsIEFQSSBlbmRwb2ludCBuYW1lcyxcbiAqIG9yZGVyZWQgYmVzdC1maXJzdCB3aXRoaW4gZWFjaCBjbGFzcyBieSB7QGxpbmsgY2xhc3NpZnkuY2xhc3NpZnlCeUZhbWlseX0uXG4gKiBVc2VkIG9ubHkgYXMgdGhlIGZsb29yIHdoZW4gdGhlIGxpdmUgYC9zZXJ2aW5nLWVuZHBvaW50c2AgY2F0YWxvZ3VlIGNhbid0IGJlXG4gKiByZWFkIGF0IHJlc29sdmUgdGltZTsgdGhlIGxpdmUsIHNjb3JlLWRyaXZlbiBjbGFzc2lmaWNhdGlvbiBzdXBlcnNlZGVzIGl0XG4gKiB3aGVuZXZlciB0aGUgd29ya3NwYWNlIGxpc3RpbmcgaXMgYXZhaWxhYmxlLiBDbGFzc2VzIGFyZSBub3QgaGFyZC1jb2RlZCBoZXJlXG4gKiAtIGVhY2ggbmFtZSBpcyBjbGFzc2lmaWVkIGJ5IGZhbWlseSBoZXVyaXN0aWMuXG4gKi9cbmNvbnN0IEZBTExCQUNLX01PREVMX05BTUVTOiByZWFkb25seSBzdHJpbmdbXSA9IFtcbiAgXCJkYXRhYnJpY2tzLWNsYXVkZS1vcHVzLTQtOFwiLFxuICBcImRhdGFicmlja3MtZ3B0LTUtNS1wcm9cIixcbiAgXCJkYXRhYnJpY2tzLWdlbWluaS0zLTEtcHJvXCIsXG4gIFwiZGF0YWJyaWNrcy1jbGF1ZGUtc29ubmV0LTQtNlwiLFxuICBcImRhdGFicmlja3MtZ3B0LTUtNVwiLFxuICBcImRhdGFicmlja3MtbWV0YS1sbGFtYS0zLTMtNzBiLWluc3RydWN0XCIsXG4gIFwiZGF0YWJyaWNrcy1jbGF1ZGUtaGFpa3UtNC01XCIsXG4gIFwiZGF0YWJyaWNrcy1ncHQtNS1uYW5vXCIsXG4gIFwiZGF0YWJyaWNrcy1tZXRhLWxsYW1hLTMtMS04Yi1pbnN0cnVjdFwiLFxuXTtcblxuLyoqXG4gKiBTdGF0aWMgZmFsbGJhY2sgbW9kZWwgaWRzIGZvciBhIGNoYXQgY2xhc3MsIGRyYXduIGZyb20gdGhlIHNtYWxsIGJ1aWx0LWluXG4gKiB7QGxpbmsgRkFMTEJBQ0tfTU9ERUxfTkFNRVN9IGxpc3QgYW5kIG9yZGVyZWQgYmVzdC1maXJzdCBieSBmYW1pbHkgcmFuay4gU3luY1xuICogYW5kIHdvcmtzcGFjZS1pbmRlcGVuZGVudDogdGhpcyBpcyB0aGUgKmZhbGxiYWNrIG9waW5pb24qIHVzZWQgdG8gc2VlZCBkZWZhdWx0XG4gKiBsaXN0cyBvciB3aGVuIHRoZSBsaXZlIGNhdGFsb2d1ZSBpcyB1bnJlYWNoYWJsZSAtIGxpdmUgcmVzb2x1dGlvbiBwcmVmZXJzXG4gKiB7QGxpbmsgY2xhc3NpZnkuY2xhc3NpZnlFbmRwb2ludHN9LiBSZXR1cm5zIGBbXWAgZm9yXG4gKiB7QGxpbmsgTW9kZWxDbGFzcy5FbWJlZGRpbmd9ICh0aGUgZmxvb3IgaXMgY2hhdC1vbmx5KS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1vZGVsc0ZvckNsYXNzKGNsczogTW9kZWxDbGFzcyk6IHJlYWRvbmx5IHN0cmluZ1tdIHtcbiAgcmV0dXJuIEZBTExCQUNLX01PREVMX05BTUVTLm1hcCgobmFtZSkgPT4gKHsgbmFtZSwgYzogY2xhc3NpZnkuY2xhc3NpZnlCeUZhbWlseShuYW1lKSB9KSlcbiAgICAuZmlsdGVyKCh4KTogeCBpcyB7IG5hbWU6IHN0cmluZzsgYzogRmFtaWx5Q2xhc3MgfSA9PiB4LmMgIT09IG51bGwgJiYgeC5jLmNsYXNzID09PSBjbHMpXG4gICAgLnNvcnQoKGEsIGIpID0+IGIuYy5yYW5rIC0gYS5jLnJhbmspXG4gICAgLm1hcCgoeCkgPT4geC5uYW1lKTtcbn1cblxuLyoqIFRvcCBzdGF0aWMgZmFsbGJhY2sgbW9kZWwgaWQgZm9yIGEgY2hhdCBjbGFzcy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtb2RlbEZvckNsYXNzKGNsczogTW9kZWxDbGFzcyk6IHN0cmluZyB7XG4gIHJldHVybiBtb2RlbHNGb3JDbGFzcyhjbHMpWzBdITtcbn1cblxuLyoqXG4gKiBQcmlvcml0eS1vcmRlcmVkIGZhbGxiYWNrIGNoYWluIChDaGF0VGhpbmtpbmcgLT4gQ2hhdEJhbGFuY2VkIC0+IENoYXRGYXN0KVxuICogb3ZlciB0aGUgc21hbGwgYnVpbHQtaW4gbGlzdC4gVGhlIGZsb29yIHdhbGtlZCBhdCByZXNvbHZlIHRpbWUgd2hlbiBubyBhZ2VudFxuICogLyBwbHVnaW4gLyBlbnYgLyByZXF1ZXN0IG1vZGVsIGlzIHNldCAqYW5kKiB0aGUgbGl2ZSBjYXRhbG9ndWUgeWllbGRzIG5vdGhpbmcuXG4gKi9cbmV4cG9ydCBjb25zdCBGQUxMQkFDS19NT0RFTF9JRFM6IHJlYWRvbmx5IHN0cmluZ1tdID0gW1xuICAuLi5tb2RlbHNGb3JDbGFzcyhNb2RlbENsYXNzLkNoYXRUaGlua2luZyksXG4gIC4uLm1vZGVsc0ZvckNsYXNzKE1vZGVsQ2xhc3MuQ2hhdEJhbGFuY2VkKSxcbiAgLi4ubW9kZWxzRm9yQ2xhc3MoTW9kZWxDbGFzcy5DaGF0RmFzdCksXG5dO1xuIl19
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Calling a Model Serving endpoint directly over HTTP.
3
+ *
4
+ * The SDK's `servingEndpoints.query` covers the typed request shapes, but an
5
+ * OpenAI-compatible caller (a proxy, a passthrough route, a streaming client)
6
+ * needs to issue its own `fetch` against Databricks' OpenAI-shaped URLs with
7
+ * an OpenAI body. That needs exactly two things the SDK doesn't hand out
8
+ * directly: the URL ({@link invocationsUrl} / {@link responsesUrl} /
9
+ * {@link openResponsesUrl}) and a currently-valid set of auth headers
10
+ * ({@link authHeaders}).
11
+ *
12
+ * Auth is delegated entirely to the Databricks SDK: `config.authenticate`
13
+ * re-runs the configured credential provider on every call and refreshes the
14
+ * underlying OAuth / PAT token when it is close to expiry, so a caller never
15
+ * manages token lifetimes itself - mint headers per request and each one is
16
+ * signed with a valid bearer token.
17
+ *
18
+ * @module
19
+ */
20
+ /**
21
+ * Path segment appended to a serving endpoint for OpenAI-compatible chat
22
+ * requests. Databricks routes `/serving-endpoints/<name>/invocations` to the
23
+ * endpoint's Chat Completions surface (`messages` in, `choices` out). Some
24
+ * models (notably Codex) reject this path and require {@link responsesUrl}.
25
+ */
26
+ export declare const INVOCATIONS_SUFFIX = "invocations";
27
+ /**
28
+ * Workspace-level OpenAI Responses API path. Body carries `model` (endpoint
29
+ * id); used by GPT / Codex models that speak Responses natively.
30
+ */
31
+ export declare const RESPONSES_PATH = "serving-endpoints/responses";
32
+ /**
33
+ * Workspace-level Open Responses API path - the cross-provider Responses
34
+ * surface (Claude, Gemini, …) that OpenAI `/responses` does not cover.
35
+ */
36
+ export declare const OPEN_RESPONSES_PATH = "serving-endpoints/open-responses";
37
+ /**
38
+ * Workspace-level OpenAI Chat Completions path. Body carries `model` (endpoint
39
+ * id), unlike {@link invocationsUrl} which names the endpoint in the URL. Use
40
+ * this when the caller has a model id rather than a per-endpoint route - e.g.
41
+ * attaching a provider tool spec to whichever endpoint was resolved.
42
+ */
43
+ export declare const CHAT_COMPLETIONS_PATH = "serving-endpoints/chat/completions";
44
+ /**
45
+ * The OpenAI-compatible chat-completions invocations URL for an endpoint id.
46
+ *
47
+ * @param host - Workspace host, e.g. `https://my-workspace.cloud.databricks.com/`.
48
+ * Pass the value resolved from `client.config.getHost()`.
49
+ * @param endpoint - Endpoint id (already resolved; not fuzzy-matched here).
50
+ */
51
+ export declare function invocationsUrl(host: string, endpoint: string): string;
52
+ /** Workspace OpenAI Responses API URL (`POST`, model in the body). */
53
+ export declare function responsesUrl(host: string): string;
54
+ /** Workspace Open Responses API URL (`POST`, model in the body). */
55
+ export declare function openResponsesUrl(host: string): string;
56
+ /** Workspace OpenAI Chat Completions URL (`POST`, model in the body). */
57
+ export declare function chatCompletionsUrl(host: string): string;
58
+ /**
59
+ * True when the endpoint is known to reject Chat Completions `/invocations`
60
+ * and require the Responses API (Codex models today). Callers should route
61
+ * those to {@link responsesUrl} instead of {@link invocationsUrl}.
62
+ */
63
+ export declare function isResponsesOnly(endpoint: string): boolean;
64
+ /**
65
+ * Pick the Databricks Responses upstream for an endpoint id: OpenAI-family
66
+ * models use `/serving-endpoints/responses`; everything else uses the
67
+ * cross-provider `/serving-endpoints/open-responses`.
68
+ */
69
+ export declare function responsesUpstreamUrl(host: string, endpoint: string): string;
70
+ /**
71
+ * Minimal structural shape {@link authHeaders} needs. Declared narrowly rather
72
+ * than as a full `WorkspaceClientLike` so a caller holding its own
73
+ * `@databricks/sdk-experimental` `WorkspaceClient` satisfies it regardless of
74
+ * which SDK version resolved in its tree.
75
+ */
76
+ export interface AuthenticatingClientLike {
77
+ config: {
78
+ authenticate(headers: Headers): Promise<void>;
79
+ };
80
+ }
81
+ /**
82
+ * Mint auth headers for one upstream request as a plain object, ready to spread
83
+ * into a `fetch` init. Call it per request: the SDK refreshes the underlying
84
+ * token when needed, so a long-lived process never has to track expiry itself.
85
+ */
86
+ export declare function authHeaders(client: AuthenticatingClientLike): Promise<Record<string, string>>;
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Calling a Model Serving endpoint directly over HTTP.
3
+ *
4
+ * The SDK's `servingEndpoints.query` covers the typed request shapes, but an
5
+ * OpenAI-compatible caller (a proxy, a passthrough route, a streaming client)
6
+ * needs to issue its own `fetch` against Databricks' OpenAI-shaped URLs with
7
+ * an OpenAI body. That needs exactly two things the SDK doesn't hand out
8
+ * directly: the URL ({@link invocationsUrl} / {@link responsesUrl} /
9
+ * {@link openResponsesUrl}) and a currently-valid set of auth headers
10
+ * ({@link authHeaders}).
11
+ *
12
+ * Auth is delegated entirely to the Databricks SDK: `config.authenticate`
13
+ * re-runs the configured credential provider on every call and refreshes the
14
+ * underlying OAuth / PAT token when it is close to expiry, so a caller never
15
+ * manages token lifetimes itself - mint headers per request and each one is
16
+ * signed with a valid bearer token.
17
+ *
18
+ * @module
19
+ */
20
+ /**
21
+ * Path segment appended to a serving endpoint for OpenAI-compatible chat
22
+ * requests. Databricks routes `/serving-endpoints/<name>/invocations` to the
23
+ * endpoint's Chat Completions surface (`messages` in, `choices` out). Some
24
+ * models (notably Codex) reject this path and require {@link responsesUrl}.
25
+ */
26
+ export const INVOCATIONS_SUFFIX = "invocations";
27
+ /**
28
+ * Workspace-level OpenAI Responses API path. Body carries `model` (endpoint
29
+ * id); used by GPT / Codex models that speak Responses natively.
30
+ */
31
+ export const RESPONSES_PATH = "serving-endpoints/responses";
32
+ /**
33
+ * Workspace-level Open Responses API path - the cross-provider Responses
34
+ * surface (Claude, Gemini, …) that OpenAI `/responses` does not cover.
35
+ */
36
+ export const OPEN_RESPONSES_PATH = "serving-endpoints/open-responses";
37
+ /**
38
+ * Workspace-level OpenAI Chat Completions path. Body carries `model` (endpoint
39
+ * id), unlike {@link invocationsUrl} which names the endpoint in the URL. Use
40
+ * this when the caller has a model id rather than a per-endpoint route - e.g.
41
+ * attaching a provider tool spec to whichever endpoint was resolved.
42
+ */
43
+ export const CHAT_COMPLETIONS_PATH = "serving-endpoints/chat/completions";
44
+ /**
45
+ * The OpenAI-compatible chat-completions invocations URL for an endpoint id.
46
+ *
47
+ * @param host - Workspace host, e.g. `https://my-workspace.cloud.databricks.com/`.
48
+ * Pass the value resolved from `client.config.getHost()`.
49
+ * @param endpoint - Endpoint id (already resolved; not fuzzy-matched here).
50
+ */
51
+ export function invocationsUrl(host, endpoint) {
52
+ return new URL(`serving-endpoints/${encodeURIComponent(endpoint)}/${INVOCATIONS_SUFFIX}`, host).toString();
53
+ }
54
+ /** Workspace OpenAI Responses API URL (`POST`, model in the body). */
55
+ export function responsesUrl(host) {
56
+ return new URL(RESPONSES_PATH, host).toString();
57
+ }
58
+ /** Workspace Open Responses API URL (`POST`, model in the body). */
59
+ export function openResponsesUrl(host) {
60
+ return new URL(OPEN_RESPONSES_PATH, host).toString();
61
+ }
62
+ /** Workspace OpenAI Chat Completions URL (`POST`, model in the body). */
63
+ export function chatCompletionsUrl(host) {
64
+ return new URL(CHAT_COMPLETIONS_PATH, host).toString();
65
+ }
66
+ /**
67
+ * True when the endpoint is known to reject Chat Completions `/invocations`
68
+ * and require the Responses API (Codex models today). Callers should route
69
+ * those to {@link responsesUrl} instead of {@link invocationsUrl}.
70
+ */
71
+ export function isResponsesOnly(endpoint) {
72
+ return /codex/i.test(endpoint);
73
+ }
74
+ /**
75
+ * Pick the Databricks Responses upstream for an endpoint id: OpenAI-family
76
+ * models use `/serving-endpoints/responses`; everything else uses the
77
+ * cross-provider `/serving-endpoints/open-responses`.
78
+ */
79
+ export function responsesUpstreamUrl(host, endpoint) {
80
+ return isOpenAiFamily(endpoint) ? responsesUrl(host) : openResponsesUrl(host);
81
+ }
82
+ /** GPT / Codex / o-series style endpoint names that speak OpenAI Responses. */
83
+ function isOpenAiFamily(endpoint) {
84
+ const n = endpoint.toLowerCase();
85
+ return (n.includes("gpt") ||
86
+ n.includes("codex") ||
87
+ /(^|[^a-z])o[1-9]([^a-z]|$)/.test(n) ||
88
+ n.includes("openai"));
89
+ }
90
+ /**
91
+ * Mint auth headers for one upstream request as a plain object, ready to spread
92
+ * into a `fetch` init. Call it per request: the SDK refreshes the underlying
93
+ * token when needed, so a long-lived process never has to track expiry itself.
94
+ */
95
+ export async function authHeaders(client) {
96
+ const headers = new Headers();
97
+ await client.config.authenticate(headers);
98
+ const out = {};
99
+ headers.forEach((value, key) => {
100
+ out[key] = value;
101
+ });
102
+ return out;
103
+ }
104
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW52b2tlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ludm9rZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0JHO0FBRUg7Ozs7O0dBS0c7QUFDSCxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxhQUFhLENBQUM7QUFFaEQ7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLDZCQUE2QixDQUFDO0FBRTVEOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLGtDQUFrQyxDQUFDO0FBRXRFOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsb0NBQW9DLENBQUM7QUFFMUU7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FBQyxJQUFZLEVBQUUsUUFBZ0I7SUFDM0QsT0FBTyxJQUFJLEdBQUcsQ0FDWixxQkFBcUIsa0JBQWtCLENBQUMsUUFBUSxDQUFDLElBQUksa0JBQWtCLEVBQUUsRUFDekUsSUFBSSxDQUNMLENBQUMsUUFBUSxFQUFFLENBQUM7QUFDZixDQUFDO0FBRUQsc0VBQXNFO0FBQ3RFLE1BQU0sVUFBVSxZQUFZLENBQUMsSUFBWTtJQUN2QyxPQUFPLElBQUksR0FBRyxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztBQUNsRCxDQUFDO0FBRUQsb0VBQW9FO0FBQ3BFLE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxJQUFZO0lBQzNDLE9BQU8sSUFBSSxHQUFHLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7QUFDdkQsQ0FBQztBQUVELHlFQUF5RTtBQUN6RSxNQUFNLFVBQVUsa0JBQWtCLENBQUMsSUFBWTtJQUM3QyxPQUFPLElBQUksR0FBRyxDQUFDLHFCQUFxQixFQUFFLElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO0FBQ3pELENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FBQyxRQUFnQjtJQUM5QyxPQUFPLFFBQVEsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDakMsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsb0JBQW9CLENBQUMsSUFBWSxFQUFFLFFBQWdCO0lBQ2pFLE9BQU8sY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ2hGLENBQUM7QUFFRCwrRUFBK0U7QUFDL0UsU0FBUyxjQUFjLENBQUMsUUFBZ0I7SUFDdEMsTUFBTSxDQUFDLEdBQUcsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ2pDLE9BQU8sQ0FDTCxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztRQUNqQixDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQztRQUNuQiw0QkFBNEIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3BDLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQ3JCLENBQUM7QUFDSixDQUFDO0FBY0Q7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsV0FBVyxDQUMvQixNQUFnQztJQUVoQyxNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO0lBQzlCLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDMUMsTUFBTSxHQUFHLEdBQTJCLEVBQUUsQ0FBQztJQUN2QyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxFQUFFO1FBQzdCLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxLQUFLLENBQUM7SUFDbkIsQ0FBQyxDQUFDLENBQUM7SUFDSCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENhbGxpbmcgYSBNb2RlbCBTZXJ2aW5nIGVuZHBvaW50IGRpcmVjdGx5IG92ZXIgSFRUUC5cbiAqXG4gKiBUaGUgU0RLJ3MgYHNlcnZpbmdFbmRwb2ludHMucXVlcnlgIGNvdmVycyB0aGUgdHlwZWQgcmVxdWVzdCBzaGFwZXMsIGJ1dCBhblxuICogT3BlbkFJLWNvbXBhdGlibGUgY2FsbGVyIChhIHByb3h5LCBhIHBhc3N0aHJvdWdoIHJvdXRlLCBhIHN0cmVhbWluZyBjbGllbnQpXG4gKiBuZWVkcyB0byBpc3N1ZSBpdHMgb3duIGBmZXRjaGAgYWdhaW5zdCBEYXRhYnJpY2tzJyBPcGVuQUktc2hhcGVkIFVSTHMgd2l0aFxuICogYW4gT3BlbkFJIGJvZHkuIFRoYXQgbmVlZHMgZXhhY3RseSB0d28gdGhpbmdzIHRoZSBTREsgZG9lc24ndCBoYW5kIG91dFxuICogZGlyZWN0bHk6IHRoZSBVUkwgKHtAbGluayBpbnZvY2F0aW9uc1VybH0gLyB7QGxpbmsgcmVzcG9uc2VzVXJsfSAvXG4gKiB7QGxpbmsgb3BlblJlc3BvbnNlc1VybH0pIGFuZCBhIGN1cnJlbnRseS12YWxpZCBzZXQgb2YgYXV0aCBoZWFkZXJzXG4gKiAoe0BsaW5rIGF1dGhIZWFkZXJzfSkuXG4gKlxuICogQXV0aCBpcyBkZWxlZ2F0ZWQgZW50aXJlbHkgdG8gdGhlIERhdGFicmlja3MgU0RLOiBgY29uZmlnLmF1dGhlbnRpY2F0ZWBcbiAqIHJlLXJ1bnMgdGhlIGNvbmZpZ3VyZWQgY3JlZGVudGlhbCBwcm92aWRlciBvbiBldmVyeSBjYWxsIGFuZCByZWZyZXNoZXMgdGhlXG4gKiB1bmRlcmx5aW5nIE9BdXRoIC8gUEFUIHRva2VuIHdoZW4gaXQgaXMgY2xvc2UgdG8gZXhwaXJ5LCBzbyBhIGNhbGxlciBuZXZlclxuICogbWFuYWdlcyB0b2tlbiBsaWZldGltZXMgaXRzZWxmIC0gbWludCBoZWFkZXJzIHBlciByZXF1ZXN0IGFuZCBlYWNoIG9uZSBpc1xuICogc2lnbmVkIHdpdGggYSB2YWxpZCBiZWFyZXIgdG9rZW4uXG4gKlxuICogQG1vZHVsZVxuICovXG5cbi8qKlxuICogUGF0aCBzZWdtZW50IGFwcGVuZGVkIHRvIGEgc2VydmluZyBlbmRwb2ludCBmb3IgT3BlbkFJLWNvbXBhdGlibGUgY2hhdFxuICogcmVxdWVzdHMuIERhdGFicmlja3Mgcm91dGVzIGAvc2VydmluZy1lbmRwb2ludHMvPG5hbWU+L2ludm9jYXRpb25zYCB0byB0aGVcbiAqIGVuZHBvaW50J3MgQ2hhdCBDb21wbGV0aW9ucyBzdXJmYWNlIChgbWVzc2FnZXNgIGluLCBgY2hvaWNlc2Agb3V0KS4gU29tZVxuICogbW9kZWxzIChub3RhYmx5IENvZGV4KSByZWplY3QgdGhpcyBwYXRoIGFuZCByZXF1aXJlIHtAbGluayByZXNwb25zZXNVcmx9LlxuICovXG5leHBvcnQgY29uc3QgSU5WT0NBVElPTlNfU1VGRklYID0gXCJpbnZvY2F0aW9uc1wiO1xuXG4vKipcbiAqIFdvcmtzcGFjZS1sZXZlbCBPcGVuQUkgUmVzcG9uc2VzIEFQSSBwYXRoLiBCb2R5IGNhcnJpZXMgYG1vZGVsYCAoZW5kcG9pbnRcbiAqIGlkKTsgdXNlZCBieSBHUFQgLyBDb2RleCBtb2RlbHMgdGhhdCBzcGVhayBSZXNwb25zZXMgbmF0aXZlbHkuXG4gKi9cbmV4cG9ydCBjb25zdCBSRVNQT05TRVNfUEFUSCA9IFwic2VydmluZy1lbmRwb2ludHMvcmVzcG9uc2VzXCI7XG5cbi8qKlxuICogV29ya3NwYWNlLWxldmVsIE9wZW4gUmVzcG9uc2VzIEFQSSBwYXRoIC0gdGhlIGNyb3NzLXByb3ZpZGVyIFJlc3BvbnNlc1xuICogc3VyZmFjZSAoQ2xhdWRlLCBHZW1pbmksIOKApikgdGhhdCBPcGVuQUkgYC9yZXNwb25zZXNgIGRvZXMgbm90IGNvdmVyLlxuICovXG5leHBvcnQgY29uc3QgT1BFTl9SRVNQT05TRVNfUEFUSCA9IFwic2VydmluZy1lbmRwb2ludHMvb3Blbi1yZXNwb25zZXNcIjtcblxuLyoqXG4gKiBXb3Jrc3BhY2UtbGV2ZWwgT3BlbkFJIENoYXQgQ29tcGxldGlvbnMgcGF0aC4gQm9keSBjYXJyaWVzIGBtb2RlbGAgKGVuZHBvaW50XG4gKiBpZCksIHVubGlrZSB7QGxpbmsgaW52b2NhdGlvbnNVcmx9IHdoaWNoIG5hbWVzIHRoZSBlbmRwb2ludCBpbiB0aGUgVVJMLiBVc2VcbiAqIHRoaXMgd2hlbiB0aGUgY2FsbGVyIGhhcyBhIG1vZGVsIGlkIHJhdGhlciB0aGFuIGEgcGVyLWVuZHBvaW50IHJvdXRlIC0gZS5nLlxuICogYXR0YWNoaW5nIGEgcHJvdmlkZXIgdG9vbCBzcGVjIHRvIHdoaWNoZXZlciBlbmRwb2ludCB3YXMgcmVzb2x2ZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBDSEFUX0NPTVBMRVRJT05TX1BBVEggPSBcInNlcnZpbmctZW5kcG9pbnRzL2NoYXQvY29tcGxldGlvbnNcIjtcblxuLyoqXG4gKiBUaGUgT3BlbkFJLWNvbXBhdGlibGUgY2hhdC1jb21wbGV0aW9ucyBpbnZvY2F0aW9ucyBVUkwgZm9yIGFuIGVuZHBvaW50IGlkLlxuICpcbiAqIEBwYXJhbSBob3N0IC0gV29ya3NwYWNlIGhvc3QsIGUuZy4gYGh0dHBzOi8vbXktd29ya3NwYWNlLmNsb3VkLmRhdGFicmlja3MuY29tL2AuXG4gKiAgIFBhc3MgdGhlIHZhbHVlIHJlc29sdmVkIGZyb20gYGNsaWVudC5jb25maWcuZ2V0SG9zdCgpYC5cbiAqIEBwYXJhbSBlbmRwb2ludCAtIEVuZHBvaW50IGlkIChhbHJlYWR5IHJlc29sdmVkOyBub3QgZnV6enktbWF0Y2hlZCBoZXJlKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGludm9jYXRpb25zVXJsKGhvc3Q6IHN0cmluZywgZW5kcG9pbnQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBuZXcgVVJMKFxuICAgIGBzZXJ2aW5nLWVuZHBvaW50cy8ke2VuY29kZVVSSUNvbXBvbmVudChlbmRwb2ludCl9LyR7SU5WT0NBVElPTlNfU1VGRklYfWAsXG4gICAgaG9zdCxcbiAgKS50b1N0cmluZygpO1xufVxuXG4vKiogV29ya3NwYWNlIE9wZW5BSSBSZXNwb25zZXMgQVBJIFVSTCAoYFBPU1RgLCBtb2RlbCBpbiB0aGUgYm9keSkuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzcG9uc2VzVXJsKGhvc3Q6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBuZXcgVVJMKFJFU1BPTlNFU19QQVRILCBob3N0KS50b1N0cmluZygpO1xufVxuXG4vKiogV29ya3NwYWNlIE9wZW4gUmVzcG9uc2VzIEFQSSBVUkwgKGBQT1NUYCwgbW9kZWwgaW4gdGhlIGJvZHkpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9wZW5SZXNwb25zZXNVcmwoaG9zdDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIG5ldyBVUkwoT1BFTl9SRVNQT05TRVNfUEFUSCwgaG9zdCkudG9TdHJpbmcoKTtcbn1cblxuLyoqIFdvcmtzcGFjZSBPcGVuQUkgQ2hhdCBDb21wbGV0aW9ucyBVUkwgKGBQT1NUYCwgbW9kZWwgaW4gdGhlIGJvZHkpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoYXRDb21wbGV0aW9uc1VybChob3N0OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gbmV3IFVSTChDSEFUX0NPTVBMRVRJT05TX1BBVEgsIGhvc3QpLnRvU3RyaW5nKCk7XG59XG5cbi8qKlxuICogVHJ1ZSB3aGVuIHRoZSBlbmRwb2ludCBpcyBrbm93biB0byByZWplY3QgQ2hhdCBDb21wbGV0aW9ucyBgL2ludm9jYXRpb25zYFxuICogYW5kIHJlcXVpcmUgdGhlIFJlc3BvbnNlcyBBUEkgKENvZGV4IG1vZGVscyB0b2RheSkuIENhbGxlcnMgc2hvdWxkIHJvdXRlXG4gKiB0aG9zZSB0byB7QGxpbmsgcmVzcG9uc2VzVXJsfSBpbnN0ZWFkIG9mIHtAbGluayBpbnZvY2F0aW9uc1VybH0uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1Jlc3BvbnNlc09ubHkoZW5kcG9pbnQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gL2NvZGV4L2kudGVzdChlbmRwb2ludCk7XG59XG5cbi8qKlxuICogUGljayB0aGUgRGF0YWJyaWNrcyBSZXNwb25zZXMgdXBzdHJlYW0gZm9yIGFuIGVuZHBvaW50IGlkOiBPcGVuQUktZmFtaWx5XG4gKiBtb2RlbHMgdXNlIGAvc2VydmluZy1lbmRwb2ludHMvcmVzcG9uc2VzYDsgZXZlcnl0aGluZyBlbHNlIHVzZXMgdGhlXG4gKiBjcm9zcy1wcm92aWRlciBgL3NlcnZpbmctZW5kcG9pbnRzL29wZW4tcmVzcG9uc2VzYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc3BvbnNlc1Vwc3RyZWFtVXJsKGhvc3Q6IHN0cmluZywgZW5kcG9pbnQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBpc09wZW5BaUZhbWlseShlbmRwb2ludCkgPyByZXNwb25zZXNVcmwoaG9zdCkgOiBvcGVuUmVzcG9uc2VzVXJsKGhvc3QpO1xufVxuXG4vKiogR1BUIC8gQ29kZXggLyBvLXNlcmllcyBzdHlsZSBlbmRwb2ludCBuYW1lcyB0aGF0IHNwZWFrIE9wZW5BSSBSZXNwb25zZXMuICovXG5mdW5jdGlvbiBpc09wZW5BaUZhbWlseShlbmRwb2ludDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IG4gPSBlbmRwb2ludC50b0xvd2VyQ2FzZSgpO1xuICByZXR1cm4gKFxuICAgIG4uaW5jbHVkZXMoXCJncHRcIikgfHxcbiAgICBuLmluY2x1ZGVzKFwiY29kZXhcIikgfHxcbiAgICAvKF58W15hLXpdKW9bMS05XShbXmEtel18JCkvLnRlc3QobikgfHxcbiAgICBuLmluY2x1ZGVzKFwib3BlbmFpXCIpXG4gICk7XG59XG5cbi8qKlxuICogTWluaW1hbCBzdHJ1Y3R1cmFsIHNoYXBlIHtAbGluayBhdXRoSGVhZGVyc30gbmVlZHMuIERlY2xhcmVkIG5hcnJvd2x5IHJhdGhlclxuICogdGhhbiBhcyBhIGZ1bGwgYFdvcmtzcGFjZUNsaWVudExpa2VgIHNvIGEgY2FsbGVyIGhvbGRpbmcgaXRzIG93blxuICogYEBkYXRhYnJpY2tzL3Nkay1leHBlcmltZW50YWxgIGBXb3Jrc3BhY2VDbGllbnRgIHNhdGlzZmllcyBpdCByZWdhcmRsZXNzIG9mXG4gKiB3aGljaCBTREsgdmVyc2lvbiByZXNvbHZlZCBpbiBpdHMgdHJlZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBdXRoZW50aWNhdGluZ0NsaWVudExpa2Uge1xuICBjb25maWc6IHtcbiAgICBhdXRoZW50aWNhdGUoaGVhZGVyczogSGVhZGVycyk6IFByb21pc2U8dm9pZD47XG4gIH07XG59XG5cbi8qKlxuICogTWludCBhdXRoIGhlYWRlcnMgZm9yIG9uZSB1cHN0cmVhbSByZXF1ZXN0IGFzIGEgcGxhaW4gb2JqZWN0LCByZWFkeSB0byBzcHJlYWRcbiAqIGludG8gYSBgZmV0Y2hgIGluaXQuIENhbGwgaXQgcGVyIHJlcXVlc3Q6IHRoZSBTREsgcmVmcmVzaGVzIHRoZSB1bmRlcmx5aW5nXG4gKiB0b2tlbiB3aGVuIG5lZWRlZCwgc28gYSBsb25nLWxpdmVkIHByb2Nlc3MgbmV2ZXIgaGFzIHRvIHRyYWNrIGV4cGlyeSBpdHNlbGYuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhdXRoSGVhZGVycyhcbiAgY2xpZW50OiBBdXRoZW50aWNhdGluZ0NsaWVudExpa2UsXG4pOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHN0cmluZz4+IHtcbiAgY29uc3QgaGVhZGVycyA9IG5ldyBIZWFkZXJzKCk7XG4gIGF3YWl0IGNsaWVudC5jb25maWcuYXV0aGVudGljYXRlKGhlYWRlcnMpO1xuICBjb25zdCBvdXQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgaGVhZGVycy5mb3JFYWNoKCh2YWx1ZSwga2V5KSA9PiB7XG4gICAgb3V0W2tleV0gPSB2YWx1ZTtcbiAgfSk7XG4gIHJldHVybiBvdXQ7XG59XG4iXX0=