@dbx-tools/model 0.9.21 → 0.9.28

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.
Files changed (86) hide show
  1. package/README.md +61 -10
  2. package/index.ts +12 -2
  3. package/lib/exports.d.ts +1 -0
  4. package/lib/exports.js +2 -0
  5. package/lib/index.d.ts +12 -2
  6. package/lib/index.js +9 -2
  7. package/lib/src/_metadata-contract.d.ts +42 -0
  8. package/lib/src/_metadata-contract.js +11 -0
  9. package/lib/src/_metadata-generator.d.ts +7 -0
  10. package/lib/src/_metadata-generator.js +182 -0
  11. package/lib/src/_ranking.d.ts +20 -0
  12. package/lib/src/_ranking.js +226 -0
  13. package/lib/src/_selection.d.ts +23 -0
  14. package/lib/src/_selection.js +95 -0
  15. package/lib/src/classes.d.ts +2 -2
  16. package/lib/src/classes.js +10 -8
  17. package/lib/src/classify.d.ts +130 -0
  18. package/lib/src/classify.js +283 -0
  19. package/lib/src/fallback.d.ts +4 -4
  20. package/lib/src/fallback.js +7 -7
  21. package/lib/src/generated/model-capabilities.json +90 -0
  22. package/lib/src/generated/model-rate-limits.json +342 -0
  23. package/lib/src/generated/retired-models.json +32 -0
  24. package/lib/src/invoke.js +3 -3
  25. package/lib/src/metadata.d.ts +33 -0
  26. package/lib/src/metadata.js +120 -0
  27. package/lib/src/model-catalog.d.ts +4 -4
  28. package/lib/src/model-catalog.js +19 -24
  29. package/lib/src/model-client.d.ts +67 -0
  30. package/lib/src/model-client.js +181 -0
  31. package/lib/src/policy.d.ts +14 -8
  32. package/lib/src/policy.js +173 -14
  33. package/lib/src/python.d.ts +2 -0
  34. package/lib/src/python.js +3 -0
  35. package/lib/src/resolve.d.ts +10 -143
  36. package/lib/src/resolve.js +11 -196
  37. package/lib/tsconfig.tsbuildinfo +1 -1
  38. package/package.json +15 -5
  39. package/src/_metadata-contract.ts +56 -0
  40. package/src/_metadata-generator.ts +199 -0
  41. package/src/_ranking.ts +260 -0
  42. package/src/_selection.ts +141 -0
  43. package/src/classes.ts +11 -7
  44. package/src/classify.ts +324 -0
  45. package/src/fallback.ts +11 -7
  46. package/src/generated/model-capabilities.json +90 -0
  47. package/src/generated/model-rate-limits.json +342 -0
  48. package/src/generated/retired-models.json +32 -0
  49. package/src/invoke.ts +2 -2
  50. package/src/metadata.ts +189 -0
  51. package/src/model-catalog.ts +26 -28
  52. package/src/model-client.ts +311 -0
  53. package/src/policy.ts +176 -19
  54. package/src/python.ts +2 -0
  55. package/src/resolve.ts +24 -270
  56. package/._LICENSE +0 -0
  57. package/._README.md +0 -0
  58. package/._index.ts +0 -0
  59. package/._package.json +0 -0
  60. package/lib/._index.d.ts +0 -0
  61. package/lib/._index.js +0 -0
  62. package/lib/._tsconfig.tsbuildinfo +0 -0
  63. package/lib/src/.__native.d.ts +0 -0
  64. package/lib/src/.__native.js +0 -0
  65. package/lib/src/._classes.d.ts +0 -0
  66. package/lib/src/._classes.js +0 -0
  67. package/lib/src/._fallback.d.ts +0 -0
  68. package/lib/src/._fallback.js +0 -0
  69. package/lib/src/._invoke.d.ts +0 -0
  70. package/lib/src/._invoke.js +0 -0
  71. package/lib/src/._model-catalog.d.ts +0 -0
  72. package/lib/src/._model-catalog.js +0 -0
  73. package/lib/src/._policy.d.ts +0 -0
  74. package/lib/src/._policy.js +0 -0
  75. package/lib/src/._resolve.d.ts +0 -0
  76. package/lib/src/._resolve.js +0 -0
  77. package/lib/src/_native.d.ts +0 -14
  78. package/lib/src/_native.js +0 -124
  79. package/src/.__native.ts +0 -0
  80. package/src/._classes.ts +0 -0
  81. package/src/._fallback.ts +0 -0
  82. package/src/._invoke.ts +0 -0
  83. package/src/._model-catalog.ts +0 -0
  84. package/src/._policy.ts +0 -0
  85. package/src/._resolve.ts +0 -0
  86. package/src/_native.ts +0 -174
@@ -0,0 +1,226 @@
1
+ import { ModelClass as ModelClassValues, } from "@dbx-tools/shared-model/contracts";
2
+ import { toModelDisplayName } from "@dbx-tools/shared-model/display";
3
+ import Fuse from "fuse.js";
4
+ import { classesAtOrBelow, CHAT_CLASS_ORDER, MODEL_CLASS_ORDER } from "./classes.js";
5
+ import { classifyEndpoints, endpointCapabilities, supportsToolsByFamily, versionTuple, } from "./classify.js";
6
+ import { modelStatusFor } from "./metadata.js";
7
+ import { modelFamily, modelReasoningEfforts, modelServiceNames } from "./policy.js";
8
+ const ModelClass = ModelClassValues;
9
+ const DEFAULT_FUZZY_THRESHOLD = 0.4;
10
+ /** Rank endpoint records through the TypeScript-owned model policy. */
11
+ export function rankEndpoints(endpoints, query = {}, options = {}) {
12
+ const originalByName = new Map(endpoints.map((endpoint) => [endpoint.name, endpoint]));
13
+ const normalized = endpoints.map((endpoint) => ({
14
+ ...endpoint,
15
+ ...(options.modelClass ? { class: options.modelClass } : {}),
16
+ ...(options.task ? { task: options.task } : {}),
17
+ }));
18
+ const classified = options.modelClass
19
+ ? {
20
+ [ModelClass.ChatThinking]: [],
21
+ [ModelClass.ChatBalanced]: [],
22
+ [ModelClass.ChatFast]: [],
23
+ [ModelClass.Embedding]: [],
24
+ [options.modelClass]: normalized,
25
+ }
26
+ : classifyEndpoints(normalized);
27
+ const requestedClass = options.modelClass ?? query.modelClass;
28
+ const eligible = requestedClass ? classesAtOrBelow(requestedClass) : CHAT_CLASS_ORDER;
29
+ const candidates = [];
30
+ for (const modelClass of eligible) {
31
+ for (const endpoint of classified[modelClass]) {
32
+ if (!options.includeDeprecated && endpoint.status?.deprecated)
33
+ continue;
34
+ if (query.requiresTools && !endpointCapabilities(endpoint).tools)
35
+ continue;
36
+ candidates.push({ endpoint, modelClass });
37
+ }
38
+ }
39
+ const search = query.search?.trim();
40
+ let ranked = candidates;
41
+ if (search) {
42
+ const exact = candidates.find((candidate) => candidate.endpoint.name === search);
43
+ if (exact) {
44
+ ranked = [{ ...exact, score: 0 }];
45
+ }
46
+ else {
47
+ const threshold = query.threshold ?? DEFAULT_FUZZY_THRESHOLD;
48
+ const searchTokens = tokenize(search);
49
+ const tokenMatches = candidates
50
+ .filter((candidate) => {
51
+ const candidateTokens = new Set(searchableValues(candidate.endpoint).flatMap(tokenize));
52
+ return (searchTokens.length > 0 && searchTokens.every((token) => candidateTokens.has(token)));
53
+ })
54
+ .map((candidate) => ({ ...candidate, score: 0 }));
55
+ if (tokenMatches.length > 0) {
56
+ ranked = tokenMatches.sort(compareRanked);
57
+ }
58
+ else {
59
+ const fuse = new Fuse(candidates, {
60
+ keys: [
61
+ "endpoint.name",
62
+ "endpoint.displayName",
63
+ "endpoint.family",
64
+ "endpoint.modelServiceName",
65
+ "endpoint.serviceNames",
66
+ ],
67
+ threshold,
68
+ ignoreLocation: true,
69
+ includeScore: true,
70
+ useExtendedSearch: true,
71
+ isCaseSensitive: false,
72
+ });
73
+ const normalizedSearch = tokenize(search).join(" ");
74
+ ranked = normalizedSearch
75
+ ? fuse
76
+ .search(normalizedSearch)
77
+ .filter((result) => (result.score ?? 0) <= threshold)
78
+ .map((result) => ({ ...result.item, score: result.score ?? 0 }))
79
+ .sort(compareRanked)
80
+ : [];
81
+ }
82
+ }
83
+ }
84
+ const restored = ranked.map((result) => ({
85
+ ...result,
86
+ endpoint: originalByName.get(result.endpoint.name) ?? result.endpoint,
87
+ }));
88
+ return query.limit === undefined ? restored : restored.slice(0, Math.max(0, query.limit));
89
+ }
90
+ /** Classify chat and embedding endpoints through the TypeScript-owned policy. */
91
+ export function classifyEndpointClasses(endpoints) {
92
+ const classified = classifyEndpoints(endpoints);
93
+ const result = new Map();
94
+ for (const modelClass of MODEL_CLASS_ORDER) {
95
+ for (const endpoint of classified[modelClass])
96
+ result.set(endpoint.name, modelClass);
97
+ }
98
+ return result;
99
+ }
100
+ /** Normalize serialized SDK endpoint records without native bindings. */
101
+ export function normalizeEndpoints(endpoints) {
102
+ const summaries = endpoints.flatMap((value) => {
103
+ const endpoint = record(value);
104
+ const name = stringValue(endpoint.name);
105
+ if (!name)
106
+ return [];
107
+ const entities = arrayValue(record(endpoint.config).served_entities).map(record);
108
+ const identities = [
109
+ name,
110
+ ...entities.flatMap((entity) => [
111
+ stringValue(entity.entity_name),
112
+ stringValue(record(entity.foundation_model).name),
113
+ stringValue(record(entity.external_model).name),
114
+ ].filter((identity) => Boolean(identity))),
115
+ ];
116
+ const modelServiceName = entities
117
+ .map((entity) => stringValue(record(entity.foundation_model).name) ?? stringValue(entity.entity_name))
118
+ .find(Boolean);
119
+ const family = identities.map(modelFamily).find(Boolean);
120
+ const reasoningEfforts = identities.map(modelReasoningEfforts).sort((left, right) => right.length - left.length)[0] ??
121
+ [];
122
+ const profile = entities.map(modelProfile).find(Boolean);
123
+ const summary = {
124
+ name,
125
+ displayName: toModelDisplayName(name, providedDisplayName(endpoint, entities)),
126
+ ...(family ? { family } : {}),
127
+ ...(stringValue(endpoint.task) ? { task: stringValue(endpoint.task) } : {}),
128
+ ...(stringValue(record(endpoint.state).ready)
129
+ ? { state: stringValue(record(endpoint.state).ready) }
130
+ : {}),
131
+ ...(stringValue(endpoint.description)
132
+ ? { description: stringValue(endpoint.description) }
133
+ : {}),
134
+ supportsTools: identities.some(supportsToolsByFamily),
135
+ ...(profile ? { profile } : {}),
136
+ serviceNames: Object.assign({}, ...identities.map(modelServiceNames)),
137
+ ...(modelServiceName ? { modelServiceName } : {}),
138
+ ...(reasoningEfforts.length ? { reasoningEfforts } : {}),
139
+ status: modelStatusFor(...identities),
140
+ };
141
+ return [summary];
142
+ });
143
+ const classes = classifyEndpointClasses(summaries);
144
+ return summaries.map((summary) => {
145
+ const modelClass = classes.get(summary.name);
146
+ return modelClass ? { ...summary, class: modelClass } : summary;
147
+ });
148
+ }
149
+ function compareRanked(left, right) {
150
+ const score = Math.round((left.score ?? 0) * 1000) - Math.round((right.score ?? 0) * 1000);
151
+ if (score !== 0)
152
+ return score;
153
+ const leftVersion = versionTuple(left.endpoint.name);
154
+ const rightVersion = versionTuple(right.endpoint.name);
155
+ for (let index = 0; index < 3; index += 1) {
156
+ const version = rightVersion[index] - leftVersion[index];
157
+ if (version !== 0)
158
+ return version;
159
+ }
160
+ const variant = modelVariantRank(left.endpoint.name) - modelVariantRank(right.endpoint.name);
161
+ if (variant !== 0)
162
+ return variant;
163
+ return MODEL_CLASS_ORDER.indexOf(left.modelClass) - MODEL_CLASS_ORDER.indexOf(right.modelClass);
164
+ }
165
+ function modelVariantRank(name) {
166
+ if (!/(?:^|[-_.])gpt(?:[-_.]|$)/i.test(name))
167
+ return 2;
168
+ if (/(?:^|[-_.])sol(?:[-_.]|$)/i.test(name))
169
+ return 0;
170
+ if (/(?:^|[-_.])luna(?:[-_.]|$)/i.test(name))
171
+ return 1;
172
+ return 2;
173
+ }
174
+ function tokenize(value) {
175
+ return value.toLowerCase().match(/[a-z0-9]+/g) ?? [];
176
+ }
177
+ function searchableValues(endpoint) {
178
+ return [
179
+ endpoint.name,
180
+ endpoint.displayName,
181
+ endpoint.family,
182
+ endpoint.modelServiceName,
183
+ ...Object.values(endpoint.serviceNames ?? {}),
184
+ ].filter((value) => Boolean(value));
185
+ }
186
+ function modelProfile(entity) {
187
+ const source = record(record(entity.foundation_model).ai_gateway_model_profile);
188
+ const quality = finiteNumber(source.quality);
189
+ const speed = finiteNumber(source.speed);
190
+ const cost = finiteNumber(source.cost);
191
+ if (quality === undefined && speed === undefined && cost === undefined)
192
+ return undefined;
193
+ return {
194
+ ...(quality !== undefined ? { quality } : {}),
195
+ ...(speed !== undefined ? { speed } : {}),
196
+ ...(cost !== undefined ? { cost } : {}),
197
+ };
198
+ }
199
+ function providedDisplayName(endpoint, entities) {
200
+ for (const tag of arrayValue(endpoint.tags).map(record)) {
201
+ if (!["display_name", "displayName", "name"].includes(String(tag.key)))
202
+ continue;
203
+ const value = stringValue(tag.value);
204
+ if (value)
205
+ return value;
206
+ }
207
+ return entities.map((entity) => stringValue(record(entity.external_model).name)).find(Boolean);
208
+ }
209
+ function record(value) {
210
+ return value && typeof value === "object" && !Array.isArray(value)
211
+ ? value
212
+ : {};
213
+ }
214
+ function arrayValue(value) {
215
+ return Array.isArray(value) ? value : [];
216
+ }
217
+ function stringValue(value) {
218
+ if (typeof value !== "string")
219
+ return undefined;
220
+ const trimmed = value.trim();
221
+ return trimmed || undefined;
222
+ }
223
+ function finiteNumber(value) {
224
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
225
+ }
226
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX3JhbmtpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvX3JhbmtpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFVBQVUsSUFBSSxnQkFBZ0IsR0FLL0IsTUFBTSxtQ0FBbUMsQ0FBQztBQUMzQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNyRSxPQUFPLElBQUksTUFBTSxTQUFTLENBQUM7QUFFM0IsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLGlCQUFpQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3JGLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsb0JBQW9CLEVBQ3BCLHFCQUFxQixFQUNyQixZQUFZLEdBQ2IsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLHFCQUFxQixFQUFFLGlCQUFpQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBR3BGLE1BQU0sVUFBVSxHQUFHLGdCQUFnQixDQUFDO0FBRXBDLE1BQU0sdUJBQXVCLEdBQUcsR0FBRyxDQUFDO0FBT3BDLHVFQUF1RTtBQUN2RSxNQUFNLFVBQVUsYUFBYSxDQUMzQixTQUE0QyxFQUM1QyxRQUFvQixFQUFFLEVBQ3RCLFVBQWdDLEVBQUU7SUFFbEMsTUFBTSxjQUFjLEdBQUcsSUFBSSxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2RixNQUFNLFVBQVUsR0FBRyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzlDLEdBQUcsUUFBUTtRQUNYLEdBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FB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Q2pDLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUTtRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQ2hELE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUM3QixPQUFPLE9BQU8sSUFBSSxTQUFTLENBQUM7QUFDOUIsQ0FBQztBQUVELFNBQVMsWUFBWSxDQUFDLEtBQWM7SUFDbEMsT0FBTyxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDakYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIE1vZGVsQ2xhc3MgYXMgTW9kZWxDbGFzc1ZhbHVlcyxcbiAgdHlwZSBNb2RlbENsYXNzIGFzIE1vZGVsQ2xhc3NUeXBlLFxuICB0eXBlIE1vZGVsUXVlcnksXG4gIHR5cGUgUmFua2VkTW9kZWwsXG4gIHR5cGUgU2VydmluZ0VuZHBvaW50U3VtbWFyeSxcbn0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLW1vZGVsL2NvbnRyYWN0c1wiO1xuaW1wb3J0IHsgdG9Nb2RlbERpc3BsYXlOYW1lIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLW1vZGVsL2Rpc3BsYXlcIjtcbmltcG9ydCBGdXNlIGZyb20gXCJmdXNlLmpzXCI7XG5cbmltcG9ydCB7IGNsYXNzZXNBdE9yQmVsb3csIENIQVRfQ0xBU1NfT1JERVIsIE1PREVMX0NMQVNTX09SREVSIH0gZnJvbSBcIi4vY2xhc3Nlcy50c1wiO1xuaW1wb3J0IHtcbiAgY2xhc3NpZnlFbmRwb2ludHMsXG4gIGVuZHBvaW50Q2FwYWJpbGl0aWVzLFxuICBzdXBwb3J0c1Rvb2xzQnlGYW1pbHksXG4gIHZlcnNpb25UdXBsZSxcbn0gZnJvbSBcIi4vY2xhc3NpZnkudHNcIjtcbmltcG9ydCB7IG1vZGVsU3RhdHVzRm9yIH0gZnJvbSBcIi4vbWV0YWRhdGEudHNcIjtcbmltcG9ydCB7IG1vZGVsRmFtaWx5LCBtb2RlbFJlYXNvbmluZ0VmZm9ydHMsIG1vZGVsU2VydmljZU5hbWVzIH0gZnJvbSBcIi4vcG9saWN5LnRzXCI7XG5cbnR5cGUgTW9kZWxDbGFzcyA9IE1vZGVsQ2xhc3NUeXBlO1xuY29uc3QgTW9kZWxDbGFzcyA9IE1vZGVsQ2xhc3NWYWx1ZXM7XG5cbmNvbnN0IERFRkFVTFRfRlVaWllfVEhSRVNIT0xEID0gMC40O1xuaW50ZXJmYWNlIE5hdGl2ZVJhbmtpbmdPcHRpb25zIHtcbiAgcmVhZG9ubHkgaW5jbHVkZURlcHJlY2F0ZWQ/OiBib29sZWFuO1xuICByZWFkb25seSBtb2RlbENsYXNzPzogTW9kZWxDbGFzcztcbiAgcmVhZG9ubHkgdGFzaz86IHN0cmluZztcbn1cblxuLyoqIFJhbmsgZW5kcG9pbnQgcmVjb3JkcyB0aHJvdWdoIHRoZSBUeXBlU2NyaXB0LW93bmVkIG1vZGVsIHBvbGljeS4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5rRW5kcG9pbnRzKFxuICBlbmRwb2ludHM6IHJlYWRvbmx5IFNlcnZpbmdFbmRwb2ludFN1bW1hcnlbXSxcbiAgcXVlcnk6IE1vZGVsUXVlcnkgPSB7fSxcbiAgb3B0aW9uczogTmF0aXZlUmFua2luZ09wdGlvbnMgPSB7fSxcbik6IFJhbmtlZE1vZGVsW10ge1xuICBjb25zdCBvcmlnaW5hbEJ5TmFtZSA9IG5ldyBNYXAoZW5kcG9pbnRzLm1hcCgoZW5kcG9pbnQpID0+IFtlbmRwb2ludC5uYW1lLCBlbmRwb2ludF0pKTtcbiAgY29uc3Qgbm9ybWFsaXplZCA9IGVuZHBvaW50cy5tYXAoKGVuZHBvaW50KSA9PiAoe1xuICAgIC4uLmVuZHBvaW50LFxuICAgIC4uLihvcHRpb25zLm1vZGVsQ2xhc3MgPyB7IGNsYXNzOiBvcHRpb25zLm1vZGVsQ2xhc3MgfSA6IHt9KSxcbiAgICAuLi4ob3B0aW9ucy50YXNrID8geyB0YXNrOiBvcHRpb25zLnRhc2sgfSA6IHt9KSxcbiAgfSkpO1xuICBjb25zdCBjbGFzc2lmaWVkID0gb3B0aW9ucy5tb2RlbENsYXNzXG4gICAgPyB7XG4gICAgICAgIFtNb2RlbENsYXNzLkNoYXRUaGlua2luZ106IFtdLFxuICAgICAgICBbTW9kZWxDbGFzcy5DaGF0QmFsYW5jZWRdOiBbXSxcbiAgICAgICAgW01vZGVsQ2xhc3MuQ2hhdEZhc3RdOiBbXSxcbiAgICAgICAgW01vZGVsQ2xhc3MuRW1iZWRkaW5nXTogW10sXG4gICAgICAgIFtvcHRpb25zLm1vZGVsQ2xhc3NdOiBub3JtYWxpemVkLFxuICAgICAgfVxuICAgIDogY2xhc3NpZnlFbmRwb2ludHMobm9ybWFsaXplZCk7XG4gIGNvbnN0IHJlcXVlc3RlZENsYXNzID0gb3B0aW9ucy5tb2RlbENsYXNzID8/IHF1ZXJ5Lm1vZGVsQ2xhc3M7XG4gIGNvbnN0IGVsaWdpYmxlID0gcmVxdWVzdGVkQ2xhc3MgPyBjbGFzc2VzQXRPckJlbG93KHJlcXVlc3RlZENsYXNzKSA6IENIQVRfQ0xBU1NfT1JERVI7XG4gIGNvbnN0IGNhbmRpZGF0ZXM6IFJhbmtlZE1vZGVsW10gPSBbXTtcbiAgZm9yIChjb25zdCBtb2RlbENsYXNzIG9mIGVsaWdpYmxlKSB7XG4gICAgZm9yIChjb25zdCBlbmRwb2ludCBvZiBjbGFzc2lmaWVkW21vZGVsQ2xhc3NdKSB7XG4gICAgICBpZiAoIW9wdGlvbnMuaW5jbHVkZURlcHJlY2F0ZWQgJiYgZW5kcG9pbnQuc3RhdHVzPy5kZXByZWNhdGVkKSBjb250aW51ZTtcbiAgICAgIGlmIChxdWVyeS5yZXF1aXJlc1Rvb2xzICYmICFlbmRwb2ludENhcGFiaWxpdGllcyhlbmRwb2ludCkudG9vbHMpIGNvbnRpbnVlO1xuICAgICAgY2FuZGlkYXRlcy5wdXNoKHsgZW5kcG9pbnQsIG1vZGVsQ2xhc3MgfSk7XG4gICAgfVxuICB9XG5cbiAgY29uc3Qgc2VhcmNoID0gcXVlcnkuc2VhcmNoPy50cmltKCk7XG4gIGxldCByYW5rZWQgPSBjYW5kaWRhdGVzO1xuICBpZiAoc2VhcmNoKSB7XG4gICAgY29uc3QgZXhhY3QgPSBjYW5kaWRhdGVzLmZpbmQoKGNhbmRpZGF0ZSkgPT4gY2FuZGlkYXRlLmVuZHBvaW50Lm5hbWUgPT09IHNlYXJjaCk7XG4gICAgaWYgKGV4YWN0KSB7XG4gICAgICByYW5rZWQgPSBbeyAuLi5leGFjdCwgc2NvcmU6IDAgfV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHRocmVzaG9sZCA9IHF1ZXJ5LnRocmVzaG9sZCA/PyBERUZBVUxUX0ZVWlpZX1RIUkVTSE9MRDtcbiAgICAgIGNvbnN0IHNlYXJjaFRva2VucyA9IHRva2VuaXplKHNlYXJjaCk7XG4gICAgICBjb25zdCB0b2tlbk1hdGNoZXMgPSBjYW5kaWRhdGVzXG4gICAgICAgIC5maWx0ZXIoKGNhbmRpZGF0ZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGNhbmRpZGF0ZVRva2VucyA9IG5ldyBTZXQoc2VhcmNoYWJsZVZhbHVlcyhjYW5kaWRhdGUuZW5kcG9pbnQpLmZsYXRNYXAodG9rZW5pemUpKTtcbiAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgc2VhcmNoVG9rZW5zLmxlbmd0aCA+IDAgJiYgc2VhcmNoVG9rZW5zLmV2ZXJ5KCh0b2tlbikgPT4gY2FuZGlkYXRlVG9rZW5zLmhhcyh0b2tlbikpXG4gICAgICAgICAgKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm1hcCgoY2FuZGlkYXRlKSA9PiAoeyAuLi5jYW5kaWRhdGUsIHNjb3JlOiAwIH0pKTtcbiAgICAgIGlmICh0b2tlbk1hdGNoZXMubGVuZ3RoID4gMCkge1xuICAgICAgICByYW5rZWQgPSB0b2tlbk1hdGNoZXMuc29ydChjb21wYXJlUmFua2VkKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGZ1c2UgPSBuZXcgRnVzZShjYW5kaWRhdGVzLCB7XG4gICAgICAgICAga2V5czogW1xuICAgICAgICAgICAgXCJlbmRwb2ludC5uYW1lXCIsXG4gICAgICAgICAgICBcImVuZHBvaW50LmRpc3BsYXlOYW1lXCIsXG4gICAgICAgICAgICBcImVuZHBvaW50LmZhbWlseVwiLFxuICAgICAgICAgICAgXCJlbmRwb2ludC5tb2RlbFNlcnZpY2VOYW1lXCIsXG4gICAgICAgICAgICBcImVuZHBvaW50LnNlcnZpY2VOYW1lc1wiLFxuICAgICAgICAgIF0sXG4gICAgICAgICAgdGhyZXNob2xkLFxuICAgICAgICAgIGlnbm9yZUxvY2F0aW9uOiB0cnVlLFxuICAgICAgICAgIGluY2x1ZGVTY29yZTogdHJ1ZSxcbiAgICAgICAgICB1c2VFeHRlbmRlZFNlYXJjaDogdHJ1ZSxcbiAgICAgICAgICBpc0Nhc2VTZW5zaXRpdmU6IGZhbHNlLFxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZFNlYXJjaCA9IHRva2VuaXplKHNlYXJjaCkuam9pbihcIiBcIik7XG4gICAgICAgIHJhbmtlZCA9IG5vcm1hbGl6ZWRTZWFyY2hcbiAgICAgICAgICA/IGZ1c2VcbiAgICAgICAgICAgICAgLnNlYXJjaChub3JtYWxpemVkU2VhcmNoKVxuICAgICAgICAgICAgICAuZmlsdGVyKChyZXN1bHQpID0+IChyZXN1bHQuc2NvcmUgPz8gMCkgPD0gdGhyZXNob2xkKVxuICAgICAgICAgICAgICAubWFwKChyZXN1bHQpID0+ICh7IC4uLnJlc3VsdC5pdGVtLCBzY29yZTogcmVzdWx0LnNjb3JlID8/IDAgfSkpXG4gICAgICAgICAgICAgIC5zb3J0KGNvbXBhcmVSYW5rZWQpXG4gICAgICAgICAgOiBbXTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgY29uc3QgcmVzdG9yZWQgPSByYW5rZWQubWFwKChyZXN1bHQpID0+ICh7XG4gICAgLi4ucmVzdWx0LFxuICAgIGVuZHBvaW50OiBvcmlnaW5hbEJ5TmFtZS5nZXQocmVzdWx0LmVuZHBvaW50Lm5hbWUpID8/IHJlc3VsdC5lbmRwb2ludCxcbiAgfSkpO1xuICByZXR1cm4gcXVlcnkubGltaXQgPT09IHVuZGVmaW5lZCA/IHJlc3RvcmVkIDogcmVzdG9yZWQuc2xpY2UoMCwgTWF0aC5tYXgoMCwgcXVlcnkubGltaXQpKTtcbn1cblxuLyoqIENsYXNzaWZ5IGNoYXQgYW5kIGVtYmVkZGluZyBlbmRwb2ludHMgdGhyb3VnaCB0aGUgVHlwZVNjcmlwdC1vd25lZCBwb2xpY3kuICovXG5leHBvcnQgZnVuY3Rpb24gY2xhc3NpZnlFbmRwb2ludENsYXNzZXMoXG4gIGVuZHBvaW50czogcmVhZG9ubHkgU2VydmluZ0VuZHBvaW50U3VtbWFyeVtdLFxuKTogUmVhZG9ubHlNYXA8c3RyaW5nLCBNb2RlbENsYXNzPiB7XG4gIGNvbnN0IGNsYXNzaWZpZWQgPSBjbGFzc2lmeUVuZHBvaW50cyhlbmRwb2ludHMpO1xuICBjb25zdCByZXN1bHQgPSBuZXcgTWFwPHN0cmluZywgTW9kZWxDbGFzcz4oKTtcbiAgZm9yIChjb25zdCBtb2RlbENsYXNzIG9mIE1PREVMX0NMQVNTX09SREVSKSB7XG4gICAgZm9yIChjb25zdCBlbmRwb2ludCBvZiBjbGFzc2lmaWVkW21vZGVsQ2xhc3NdKSByZXN1bHQuc2V0KGVuZHBvaW50Lm5hbWUsIG1vZGVsQ2xhc3MpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKiBOb3JtYWxpemUgc2VyaWFsaXplZCBTREsgZW5kcG9pbnQgcmVjb3JkcyB3aXRob3V0IG5hdGl2ZSBiaW5kaW5ncy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVFbmRwb2ludHMoZW5kcG9pbnRzOiByZWFkb25seSB1bmtub3duW10pOiBTZXJ2aW5nRW5kcG9pbnRTdW1tYXJ5W10ge1xuICBjb25zdCBzdW1tYXJpZXMgPSBlbmRwb2ludHMuZmxhdE1hcCgodmFsdWUpID0+IHtcbiAgICBjb25zdCBlbmRwb2ludCA9IHJlY29yZCh2YWx1ZSk7XG4gICAgY29uc3QgbmFtZSA9IHN0cmluZ1ZhbHVlKGVuZHBvaW50Lm5hbWUpO1xuICAgIGlmICghbmFtZSkgcmV0dXJuIFtdO1xuICAgIGNvbnN0IGVudGl0aWVzID0gYXJyYXlWYWx1ZShyZWNvcmQoZW5kcG9pbnQuY29uZmlnKS5zZXJ2ZWRfZW50aXRpZXMpLm1hcChyZWNvcmQpO1xuICAgIGNvbnN0IGlkZW50aXRpZXMgPSBbXG4gICAgICBuYW1lLFxuICAgICAgLi4uZW50aXRpZXMuZmxhdE1hcCgoZW50aXR5KSA9PlxuICAgICAgICBbXG4gICAgICAgICAgc3RyaW5nVmFsdWUoZW50aXR5LmVudGl0eV9uYW1lKSxcbiAgICAgICAgICBzdHJpbmdWYWx1ZShyZWNvcmQoZW50aXR5LmZvdW5kYXRpb25fbW9kZWwpLm5hbWUpLFxuICAgICAgICAgIHN0cmluZ1ZhbHVlKHJlY29yZChlbnRpdHkuZXh0ZXJuYWxfbW9kZWwpLm5hbWUpLFxuICAgICAgICBdLmZpbHRlcigoaWRlbnRpdHkpOiBpZGVudGl0eSBpcyBzdHJpbmcgPT4gQm9vbGVhbihpZGVudGl0eSkpLFxuICAgICAgKSxcbiAgICBdO1xuICAgIGNvbnN0IG1vZGVsU2VydmljZU5hbWUgPSBlbnRpdGllc1xuICAgICAgLm1hcChcbiAgICAgICAgKGVudGl0eSkgPT5cbiAgICAgICAgICBzdHJpbmdWYWx1ZShyZWNvcmQoZW50aXR5LmZvdW5kYXRpb25fbW9kZWwpLm5hbWUpID8/IHN0cmluZ1ZhbHVlKGVudGl0eS5lbnRpdHlfbmFtZSksXG4gICAgICApXG4gICAgICAuZmluZChCb29sZWFuKTtcbiAgICBjb25zdCBmYW1pbHkgPSBpZGVudGl0aWVzLm1hcChtb2RlbEZhbWlseSkuZmluZChCb29sZWFuKTtcbiAgICBjb25zdCByZWFzb25pbmdFZmZvcnRzID1cbiAgICAgIGlkZW50aXRpZXMubWFwKG1vZGVsUmVhc29uaW5nRWZmb3J0cykuc29ydCgobGVmdCwgcmlnaHQpID0+IHJpZ2h0Lmxlbmd0aCAtIGxlZnQubGVuZ3RoKVswXSA/P1xuICAgICAgW107XG4gICAgY29uc3QgcHJvZmlsZSA9IGVudGl0aWVzLm1hcChtb2RlbFByb2ZpbGUpLmZpbmQoQm9vbGVhbik7XG4gICAgY29uc3Qgc3VtbWFyeTogU2VydmluZ0VuZHBvaW50U3VtbWFyeSA9IHtcbiAgICAgIG5hbWUsXG4gICAgICBkaXNwbGF5TmFtZTogdG9Nb2RlbERpc3BsYXlOYW1lKG5hbWUsIHByb3ZpZGVkRGlzcGxheU5hbWUoZW5kcG9pbnQsIGVudGl0aWVzKSksXG4gICAgICAuLi4oZmFtaWx5ID8geyBmYW1pbHkgfSA6IHt9KSxcbiAgICAgIC4uLihzdHJpbmdWYWx1ZShlbmRwb2ludC50YXNrKSA/IHsgdGFzazogc3RyaW5nVmFsdWUoZW5kcG9pbnQudGFzaykgfSA6IHt9KSxcbiAgICAgIC4uLihzdHJpbmdWYWx1ZShyZWNvcmQoZW5kcG9pbnQuc3RhdGUpLnJlYWR5KVxuICAgICAgICA/IHsgc3RhdGU6IHN0cmluZ1ZhbHVlKHJlY29yZChlbmRwb2ludC5zdGF0ZSkucmVhZHkpIH1cbiAgICAgICAgOiB7fSksXG4gICAgICAuLi4oc3RyaW5nVmFsdWUoZW5kcG9pbnQuZGVzY3JpcHRpb24pXG4gICAgICAgID8geyBkZXNjcmlwdGlvbjogc3RyaW5nVmFsdWUoZW5kcG9pbnQuZGVzY3JpcHRpb24pIH1cbiAgICAgICAgOiB7fSksXG4gICAgICBzdXBwb3J0c1Rvb2xzOiBpZGVudGl0aWVzLnNvbWUoc3VwcG9ydHNUb29sc0J5RmFtaWx5KSxcbiAgICAgIC4uLihwcm9maWxlID8geyBwcm9maWxlIH0gOiB7fSksXG4gICAgICBzZXJ2aWNlTmFtZXM6IE9iamVjdC5hc3NpZ24oe30sIC4uLmlkZW50aXRpZXMubWFwKG1vZGVsU2VydmljZU5hbWVzKSksXG4gICAgICAuLi4obW9kZWxTZXJ2aWNlTmFtZSA/IHsgbW9kZWxTZXJ2aWNlTmFtZSB9IDoge30pLFxuICAgICAgLi4uKHJlYXNvbmluZ0VmZm9ydHMubGVuZ3RoID8geyByZWFzb25pbmdFZmZvcnRzIH0gOiB7fSksXG4gICAgICBzdGF0dXM6IG1vZGVsU3RhdHVzRm9yKC4uLmlkZW50aXRpZXMpLFxuICAgIH07XG4gICAgcmV0dXJuIFtzdW1tYXJ5XTtcbiAgfSk7XG4gIGNvbnN0IGNsYXNzZXMgPSBjbGFzc2lmeUVuZHBvaW50Q2xhc3NlcyhzdW1tYXJpZXMpO1xuICByZXR1cm4gc3VtbWFyaWVzLm1hcCgoc3VtbWFyeSkgPT4ge1xuICAgIGNvbnN0IG1vZGVsQ2xhc3MgPSBjbGFzc2VzLmdldChzdW1tYXJ5Lm5hbWUpO1xuICAgIHJldHVybiBtb2RlbENsYXNzID8geyAuLi5zdW1tYXJ5LCBjbGFzczogbW9kZWxDbGFzcyB9IDogc3VtbWFyeTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNvbXBhcmVSYW5rZWQobGVmdDogUmFua2VkTW9kZWwsIHJpZ2h0OiBSYW5rZWRNb2RlbCk6IG51bWJlciB7XG4gIGNvbnN0IHNjb3JlID0gTWF0aC5yb3VuZCgobGVmdC5zY29yZSA/PyAwKSAqIDEwMDApIC0gTWF0aC5yb3VuZCgocmlnaHQuc2NvcmUgPz8gMCkgKiAxMDAwKTtcbiAgaWYgKHNjb3JlICE9PSAwKSByZXR1cm4gc2NvcmU7XG4gIGNvbnN0IGxlZnRWZXJzaW9uID0gdmVyc2lvblR1cGxlKGxlZnQuZW5kcG9pbnQubmFtZSk7XG4gIGNvbnN0IHJpZ2h0VmVyc2lvbiA9IHZlcnNpb25UdXBsZShyaWdodC5lbmRwb2ludC5uYW1lKTtcbiAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IDM7IGluZGV4ICs9IDEpIHtcbiAgICBjb25zdCB2ZXJzaW9uID0gcmlnaHRWZXJzaW9uW2luZGV4XSEgLSBsZWZ0VmVyc2lvbltpbmRleF0hO1xuICAgIGlmICh2ZXJzaW9uICE9PSAwKSByZXR1cm4gdmVyc2lvbjtcbiAgfVxuICBjb25zdCB2YXJpYW50ID0gbW9kZWxWYXJpYW50UmFuayhsZWZ0LmVuZHBvaW50Lm5hbWUpIC0gbW9kZWxWYXJpYW50UmFuayhyaWdodC5lbmRwb2ludC5uYW1lKTtcbiAgaWYgKHZhcmlhbnQgIT09IDApIHJldHVybiB2YXJpYW50O1xuICByZXR1cm4gTU9ERUxfQ0xBU1NfT1JERVIuaW5kZXhPZihsZWZ0Lm1vZGVsQ2xhc3MpIC0gTU9ERUxfQ0xBU1NfT1JERVIuaW5kZXhPZihyaWdodC5tb2RlbENsYXNzKTtcbn1cblxuZnVuY3Rpb24gbW9kZWxWYXJpYW50UmFuayhuYW1lOiBzdHJpbmcpOiBudW1iZXIge1xuICBpZiAoIS8oPzpefFstXy5dKWdwdCg/OlstXy5dfCQpL2kudGVzdChuYW1lKSkgcmV0dXJuIDI7XG4gIGlmICgvKD86XnxbLV8uXSlzb2woPzpbLV8uXXwkKS9pLnRlc3QobmFtZSkpIHJldHVybiAwO1xuICBpZiAoLyg/Ol58Wy1fLl0pbHVuYSg/OlstXy5dfCQpL2kudGVzdChuYW1lKSkgcmV0dXJuIDE7XG4gIHJldHVybiAyO1xufVxuXG5mdW5jdGlvbiB0b2tlbml6ZSh2YWx1ZTogc3RyaW5nKTogc3RyaW5nW10ge1xuICByZXR1cm4gdmFsdWUudG9Mb3dlckNhc2UoKS5tYXRjaCgvW2EtejAtOV0rL2cpID8/IFtdO1xufVxuXG5mdW5jdGlvbiBzZWFyY2hhYmxlVmFsdWVzKGVuZHBvaW50OiBTZXJ2aW5nRW5kcG9pbnRTdW1tYXJ5KTogc3RyaW5nW10ge1xuICByZXR1cm4gW1xuICAgIGVuZHBvaW50Lm5hbWUsXG4gICAgZW5kcG9pbnQuZGlzcGxheU5hbWUsXG4gICAgZW5kcG9pbnQuZmFtaWx5LFxuICAgIGVuZHBvaW50Lm1vZGVsU2VydmljZU5hbWUsXG4gICAgLi4uT2JqZWN0LnZhbHVlcyhlbmRwb2ludC5zZXJ2aWNlTmFtZXMgPz8ge30pLFxuICBdLmZpbHRlcigodmFsdWUpOiB2YWx1ZSBpcyBzdHJpbmcgPT4gQm9vbGVhbih2YWx1ZSkpO1xufVxuXG5mdW5jdGlvbiBtb2RlbFByb2ZpbGUoZW50aXR5OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikge1xuICBjb25zdCBzb3VyY2UgPSByZWNvcmQocmVjb3JkKGVudGl0eS5mb3VuZGF0aW9uX21vZGVsKS5haV9nYXRld2F5X21vZGVsX3Byb2ZpbGUpO1xuICBjb25zdCBxdWFsaXR5ID0gZmluaXRlTnVtYmVyKHNvdXJjZS5xdWFsaXR5KTtcbiAgY29uc3Qgc3BlZWQgPSBmaW5pdGVOdW1iZXIoc291cmNlLnNwZWVkKTtcbiAgY29uc3QgY29zdCA9IGZpbml0ZU51bWJlcihzb3VyY2UuY29zdCk7XG4gIGlmIChxdWFsaXR5ID09PSB1bmRlZmluZWQgJiYgc3BlZWQgPT09IHVuZGVmaW5lZCAmJiBjb3N0ID09PSB1bmRlZmluZWQpIHJldHVybiB1bmRlZmluZWQ7XG4gIHJldHVybiB7XG4gICAgLi4uKHF1YWxpdHkgIT09IHVuZGVmaW5lZCA/IHsgcXVhbGl0eSB9IDoge30pLFxuICAgIC4uLihzcGVlZCAhPT0gdW5kZWZpbmVkID8geyBzcGVlZCB9IDoge30pLFxuICAgIC4uLihjb3N0ICE9PSB1bmRlZmluZWQgPyB7IGNvc3QgfSA6IHt9KSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gcHJvdmlkZWREaXNwbGF5TmFtZShcbiAgZW5kcG9pbnQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBlbnRpdGllczogcmVhZG9ubHkgUmVjb3JkPHN0cmluZywgdW5rbm93bj5bXSxcbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGZvciAoY29uc3QgdGFnIG9mIGFycmF5VmFsdWUoZW5kcG9pbnQudGFncykubWFwKHJlY29yZCkpIHtcbiAgICBpZiAoIVtcImRpc3BsYXlfbmFtZVwiLCBcImRpc3BsYXlOYW1lXCIsIFwibmFtZVwiXS5pbmNsdWRlcyhTdHJpbmcodGFnLmtleSkpKSBjb250aW51ZTtcbiAgICBjb25zdCB2YWx1ZSA9IHN0cmluZ1ZhbHVlKHRhZy52YWx1ZSk7XG4gICAgaWYgKHZhbHVlKSByZXR1cm4gdmFsdWU7XG4gIH1cbiAgcmV0dXJuIGVudGl0aWVzLm1hcCgoZW50aXR5KSA9PiBzdHJpbmdWYWx1ZShyZWNvcmQoZW50aXR5LmV4dGVybmFsX21vZGVsKS5uYW1lKSkuZmluZChCb29sZWFuKTtcbn1cblxuZnVuY3Rpb24gcmVjb3JkKHZhbHVlOiB1bmtub3duKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICByZXR1cm4gdmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiICYmICFBcnJheS5pc0FycmF5KHZhbHVlKVxuICAgID8gKHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVxuICAgIDoge307XG59XG5cbmZ1bmN0aW9uIGFycmF5VmFsdWUodmFsdWU6IHVua25vd24pOiB1bmtub3duW10ge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyB2YWx1ZSA6IFtdO1xufVxuXG5mdW5jdGlvbiBzdHJpbmdWYWx1ZSh2YWx1ZTogdW5rbm93bik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICh0eXBlb2YgdmFsdWUgIT09IFwic3RyaW5nXCIpIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IHRyaW1tZWQgPSB2YWx1ZS50cmltKCk7XG4gIHJldHVybiB0cmltbWVkIHx8IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gZmluaXRlTnVtYmVyKHZhbHVlOiB1bmtub3duKTogbnVtYmVyIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIiAmJiBOdW1iZXIuaXNGaW5pdGUodmFsdWUpID8gdmFsdWUgOiB1bmRlZmluZWQ7XG59XG4iXX0=
@@ -0,0 +1,23 @@
1
+ import type { ModelClass, ModelQuery, RankedModel, ServingEndpointSummary } from "@dbx-tools/shared-model/contracts";
2
+ import type { ResolvedModel, ResolveModelOptions } from "./model-catalog.ts";
3
+ /** Caller intent passed to {@link resolveModel}. */
4
+ export interface ResolveModelInput {
5
+ explicit?: string;
6
+ fuzzy?: boolean;
7
+ threshold?: number;
8
+ requiresTools?: boolean;
9
+ modelClass?: ModelClass;
10
+ fallbacks?: readonly string[];
11
+ liveOnly?: boolean;
12
+ }
13
+ /** Outcome of {@link resolveModel}: the chosen id plus how it was reached. */
14
+ export interface ResolvedModelSelection {
15
+ modelId: string;
16
+ source: "explicit" | "fuzzy-match" | "class" | "fallback";
17
+ }
18
+ /** Rank a catalogue against a model query, best-first. */
19
+ export declare function lookupModels(endpoints: readonly ServingEndpointSummary[], query?: ModelQuery): RankedModel[];
20
+ /** Resolve the closest model id in one catalogue snapshot. */
21
+ export declare function rankModelId(endpoints: readonly ServingEndpointSummary[], search: string, options?: ResolveModelOptions): ResolvedModel;
22
+ /** Resolve a single model id from a catalogue and caller intent. */
23
+ export declare function resolveModel(endpoints: readonly ServingEndpointSummary[], input?: ResolveModelInput): ResolvedModelSelection;
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Runtime-independent model ranking and selection.
3
+ *
4
+ * @module
5
+ */
6
+ import * as object from "@dbx-tools/shared-core/object";
7
+ import { rankEndpoints } from "./_ranking.js";
8
+ import { FALLBACK_MODEL_IDS, modelsForClass } from "./fallback.js";
9
+ import { endpointSupportsTools } from "./policy.js";
10
+ const DEFAULT_MODEL_FAMILY_SEARCH = "gpt";
11
+ /** Rank a catalogue against a model query, best-first. */
12
+ export function lookupModels(endpoints, query = {}) {
13
+ return rankEndpoints(endpoints, query);
14
+ }
15
+ /** Resolve the closest model id in one catalogue snapshot. */
16
+ export function rankModelId(endpoints, search, options = {}) {
17
+ const [top] = lookupModels(endpoints, {
18
+ search,
19
+ limit: 1,
20
+ ...(options.threshold !== undefined ? { threshold: options.threshold } : {}),
21
+ ...(options.requiresTools !== undefined ? { requiresTools: options.requiresTools } : {}),
22
+ });
23
+ if (!top)
24
+ return { modelId: search, matched: false };
25
+ return { modelId: top.endpoint.name, matched: true, score: top.score };
26
+ }
27
+ /** Resolve a single model id from a catalogue and caller intent. */
28
+ export function resolveModel(endpoints, input = {}) {
29
+ if (input.explicit !== undefined) {
30
+ if (input.fuzzy === false) {
31
+ if (input.requiresTools)
32
+ assertToolSupport(endpoints, input.explicit);
33
+ return { modelId: input.explicit, source: "explicit" };
34
+ }
35
+ const [top] = lookupModels(endpoints, buildQuery(input, input.explicit));
36
+ if (input.requiresTools && !top) {
37
+ throw new Error(`No tool-capable model matches "${input.explicit}"`);
38
+ }
39
+ return { modelId: top?.endpoint.name ?? input.explicit, source: "fuzzy-match" };
40
+ }
41
+ if (input.modelClass === undefined && input.fallbacks && input.fallbacks.length > 0) {
42
+ const present = new Set(endpoints
43
+ .filter((endpoint) => !input.requiresTools || endpointSupportsTools(endpoint))
44
+ .map((endpoint) => endpoint.name));
45
+ const pinned = input.fallbacks.find((id) => present.has(id));
46
+ if (pinned)
47
+ return { modelId: pinned, source: "fallback" };
48
+ }
49
+ const source = input.modelClass !== undefined ? "class" : "fallback";
50
+ if (input.modelClass === undefined) {
51
+ const [preferred] = lookupModels(endpoints, buildQuery(input, DEFAULT_MODEL_FAMILY_SEARCH));
52
+ if (preferred)
53
+ return { modelId: preferred.endpoint.name, source };
54
+ }
55
+ const [top] = lookupModels(endpoints, buildQuery(input, undefined));
56
+ if (top)
57
+ return { modelId: top.endpoint.name, source };
58
+ if (input.liveOnly) {
59
+ throw new Error("No matching live Model Serving endpoint is available");
60
+ }
61
+ const floorSource = input.modelClass !== undefined ? modelsForClass(input.modelClass) : (input.fallbacks ?? []);
62
+ const floor = object.sequence(floorSource).concat(FALLBACK_MODEL_IDS).distinct().toArray();
63
+ if (input.requiresTools) {
64
+ const available = new Set(endpoints.filter(endpointSupportsTools).map((endpoint) => endpoint.name));
65
+ const selected = floor.find((id) => available.has(id));
66
+ if (!selected)
67
+ throw new Error("No tool-capable model is available");
68
+ return { modelId: selected, source };
69
+ }
70
+ return { modelId: pickFirstAvailable(floor, endpoints), source };
71
+ }
72
+ function buildQuery(input, search) {
73
+ return {
74
+ ...(search !== undefined ? { search } : {}),
75
+ ...(input.modelClass !== undefined ? { modelClass: input.modelClass } : {}),
76
+ ...(input.requiresTools !== undefined ? { requiresTools: input.requiresTools } : {}),
77
+ ...(input.threshold !== undefined ? { threshold: input.threshold } : {}),
78
+ limit: 1,
79
+ };
80
+ }
81
+ function assertToolSupport(endpoints, modelId) {
82
+ const endpoint = endpoints.find((candidate) => candidate.name === modelId);
83
+ if (!endpoint || !endpointSupportsTools(endpoint)) {
84
+ throw new Error(`Model "${modelId}" does not support function tools`);
85
+ }
86
+ }
87
+ function pickFirstAvailable(candidates, endpoints) {
88
+ const present = new Set(endpoints.map((endpoint) => endpoint.name));
89
+ for (const candidate of candidates) {
90
+ if (present.has(candidate))
91
+ return candidate;
92
+ }
93
+ return candidates[0] ?? FALLBACK_MODEL_IDS[0];
94
+ }
95
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX3NlbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9fc2VsZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFDSCxPQUFPLEtBQUssTUFBTSxNQUFNLCtCQUErQixDQUFDO0FBUXhELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDOUMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLGNBQWMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUVuRSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFcEQsTUFBTSwyQkFBMkIsR0FBRyxLQUFLLENBQUM7QUFtQjFDLDBEQUEwRDtBQUMxRCxNQUFNLFVBQVUsWUFBWSxDQUMxQixTQUE0QyxFQUM1QyxRQUFvQixFQUFFO0lBRXRCLE9BQU8sYUFBYSxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUN6QyxDQUFDO0FBRUQsOERBQThEO0FBQzlELE1BQU0sVUFBVSxXQUFXLENBQ3pCLFNBQTRDLEVBQzVDLE1BQWMsRUFDZCxVQUErQixFQUFFO0lBRWpDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxZQUFZLENBQUMsU0FBUyxFQUFFO1FBQ3BDLE1BQU07UUFDTixLQUFLLEVBQUUsQ0FBQztRQUNSLEdBQUcsQ0FBQyxPQUFPLENBQUMsU0FBUyxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDNUUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxhQUFhLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLGFBQWEsRUFBRSxPQUFPLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztLQUN6RixDQUFDLENBQUM7SUFDSCxJQUFJLENBQUMsR0FBRztRQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUs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Q0FBQyxDQUFDLENBQUM7SUFDcEUsS0FBSyxNQUFNLFNBQVMsSUFBSSxVQUFVLEVBQUUsQ0FBQztRQUNuQyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDO1lBQUUsT0FBTyxTQUFTLENBQUM7SUFDL0MsQ0FBQztJQUNELE9BQU8sVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLGtCQUFrQixDQUFDLENBQUMsQ0FBRSxDQUFDO0FBQ2pELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFJ1bnRpbWUtaW5kZXBlbmRlbnQgbW9kZWwgcmFua2luZyBhbmQgc2VsZWN0aW9uLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuaW1wb3J0ICogYXMgb2JqZWN0IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlL29iamVjdFwiO1xuaW1wb3J0IHR5cGUge1xuICBNb2RlbENsYXNzLFxuICBNb2RlbFF1ZXJ5LFxuICBSYW5rZWRNb2RlbCxcbiAgU2VydmluZ0VuZHBvaW50U3VtbWFyeSxcbn0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLW1vZGVsL2NvbnRyYWN0c1wiO1xuXG5pbXBvcnQgeyByYW5rRW5kcG9pbnRzIH0gZnJvbSBcIi4vX3JhbmtpbmcudHNcIjtcbmltcG9ydCB7IEZBTExCQUNLX01PREVMX0lEUywgbW9kZWxzRm9yQ2xhc3MgfSBmcm9tIFwiLi9mYWxsYmFjay50c1wiO1xuaW1wb3J0IHR5cGUgeyBSZXNvbHZlZE1vZGVsLCBSZXNvbHZlTW9kZWxPcHRpb25zIH0gZnJvbSBcIi4vbW9kZWwtY2F0YWxvZy50c1wiO1xuaW1wb3J0IHsgZW5kcG9pbnRTdXBwb3J0c1Rvb2xzIH0gZnJvbSBcIi4vcG9saWN5LnRzXCI7XG5cbmNvbnN0IERFRkFVTFRfTU9ERUxfRkFNSUxZX1NFQVJDSCA9IFwiZ3B0XCI7XG5cbi8qKiBDYWxsZXIgaW50ZW50IHBhc3NlZCB0byB7QGxpbmsgcmVzb2x2ZU1vZGVsfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb2x2ZU1vZGVsSW5wdXQge1xuICBleHBsaWNpdD86IHN0cmluZztcbiAgZnV6enk/OiBib29sZWFuO1xuICB0aHJlc2hvbGQ/OiBudW1iZXI7XG4gIHJlcXVpcmVzVG9vbHM/OiBib29sZWFuO1xuICBtb2RlbENsYXNzPzogTW9kZWxDbGFzcztcbiAgZmFsbGJhY2tzPzogcmVhZG9ubHkgc3RyaW5nW107XG4gIGxpdmVPbmx5PzogYm9vbGVhbjtcbn1cblxuLyoqIE91dGNvbWUgb2Yge0BsaW5rIHJlc29sdmVNb2RlbH06IHRoZSBjaG9zZW4gaWQgcGx1cyBob3cgaXQgd2FzIHJlYWNoZWQuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlc29sdmVkTW9kZWxTZWxlY3Rpb24ge1xuICBtb2RlbElkOiBzdHJpbmc7XG4gIHNvdXJjZTogXCJleHBsaWNpdFwiIHwgXCJmdXp6eS1tYXRjaFwiIHwgXCJjbGFzc1wiIHwgXCJmYWxsYmFja1wiO1xufVxuXG4vKiogUmFuayBhIGNhdGFsb2d1ZSBhZ2FpbnN0IGEgbW9kZWwgcXVlcnksIGJlc3QtZmlyc3QuICovXG5leHBvcnQgZnVuY3Rpb24gbG9va3VwTW9kZWxzKFxuICBlbmRwb2ludHM6IHJlYWRvbmx5IFNlcnZpbmdFbmRwb2ludFN1bW1hcnlbXSxcbiAgcXVlcnk6IE1vZGVsUXVlcnkgPSB7fSxcbik6IFJhbmtlZE1vZGVsW10ge1xuICByZXR1cm4gcmFua0VuZHBvaW50cyhlbmRwb2ludHMsIHF1ZXJ5KTtcbn1cblxuLyoqIFJlc29sdmUgdGhlIGNsb3Nlc3QgbW9kZWwgaWQgaW4gb25lIGNhdGFsb2d1ZSBzbmFwc2hvdC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5rTW9kZWxJZChcbiAgZW5kcG9pbnRzOiByZWFkb25seSBTZXJ2aW5nRW5kcG9pbnRTdW1tYXJ5W10sXG4gIHNlYXJjaDogc3RyaW5nLFxuICBvcHRpb25zOiBSZXNvbHZlTW9kZWxPcHRpb25zID0ge30sXG4pOiBSZXNvbHZlZE1vZGVsIHtcbiAgY29uc3QgW3RvcF0gPSBsb29rdXBNb2RlbHMoZW5kcG9pbnRzLCB7XG4gICAgc2VhcmNoLFxuICAgIGxpbWl0OiAxLFxuICAgIC4uLihvcHRpb25zLnRocmVzaG9sZCAhPT0gdW5kZWZpbmVkID8geyB0aHJlc2hvbGQ6IG9wdGlvbnMudGhyZXNob2xkIH0gOiB7fSksXG4gICAgLi4uKG9wdGlvbnMucmVxdWlyZXNUb29scyAhPT0gdW5kZWZpbmVkID8geyByZXF1aXJlc1Rvb2xzOiBvcHRpb25zLnJlcXVpcmVzVG9vbHMgfSA6IHt9KSxcbiAgfSk7XG4gIGlmICghdG9wKSByZXR1cm4geyBtb2RlbElkOiBzZWFyY2gsIG1hdGNoZWQ6IGZhbHNlIH07XG4gIHJldHVybiB7IG1vZGVsSWQ6IHRvcC5lbmRwb2ludC5uYW1lLCBtYXRjaGVkOiB0cnVlLCBzY29yZTogdG9wLnNjb3JlIH07XG59XG5cbi8qKiBSZXNvbHZlIGEgc2luZ2xlIG1vZGVsIGlkIGZyb20gYSBjYXRhbG9ndWUgYW5kIGNhbGxlciBpbnRlbnQuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZU1vZGVsKFxuICBlbmRwb2ludHM6IHJlYWRvbmx5IFNlcnZpbmdFbmRwb2ludFN1bW1hcnlbXSxcbiAgaW5wdXQ6IFJlc29sdmVNb2RlbElucHV0ID0ge30sXG4pOiBSZXNvbHZlZE1vZGVsU2VsZWN0aW9uIHtcbiAgaWYgKGlucHV0LmV4cGxpY2l0ICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoaW5wdXQuZnV6enkgPT09IGZhbHNlKSB7XG4gICAgICBpZiAoaW5wdXQucmVxdWlyZXNUb29scykgYXNzZXJ0VG9vbFN1cHBvcnQoZW5kcG9pbnRzLCBpbnB1dC5leHBsaWNpdCk7XG4gICAgICByZXR1cm4geyBtb2RlbElkOiBpbnB1dC5leHBsaWNpdCwgc291cmNlOiBcImV4cGxpY2l0XCIgfTtcbiAgICB9XG4gICAgY29uc3QgW3RvcF0gPSBsb29rdXBNb2RlbHMoZW5kcG9pbnRzLCBidWlsZFF1ZXJ5KGlucHV0LCBpbnB1dC5leHBsaWNpdCkpO1xuICAgIGlmIChpbnB1dC5yZXF1aXJlc1Rvb2xzICYmICF0b3ApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gdG9vbC1jYXBhYmxlIG1vZGVsIG1hdGNoZXMgXCIke2lucHV0LmV4cGxpY2l0fVwiYCk7XG4gICAgfVxuICAgIHJldHVybiB7IG1vZGVsSWQ6IHRvcD8uZW5kcG9pbnQubmFtZSA/PyBpbnB1dC5leHBsaWNpdCwgc291cmNlOiBcImZ1enp5LW1hdGNoXCIgfTtcbiAgfVxuXG4gIGlmIChpbnB1dC5tb2RlbENsYXNzID09PSB1bmRlZmluZWQgJiYgaW5wdXQuZmFsbGJhY2tzICYmIGlucHV0LmZhbGxiYWNrcy5sZW5ndGggPiAwKSB7XG4gICAgY29uc3QgcHJlc2VudCA9IG5ldyBTZXQoXG4gICAgICBlbmRwb2ludHNcbiAgICAgICAgLmZpbHRlcigoZW5kcG9pbnQpID0+ICFpbnB1dC5yZXF1aXJlc1Rvb2xzIHx8IGVuZHBvaW50U3VwcG9ydHNUb29scyhlbmRwb2ludCkpXG4gICAgICAgIC5tYXAoKGVuZHBvaW50KSA9PiBlbmRwb2ludC5uYW1lKSxcbiAgICApO1xuICAgIGNvbnN0IHBpbm5lZCA9IGlucHV0LmZhbGxiYWNrcy5maW5kKChpZCkgPT4gcHJlc2VudC5oYXMoaWQpKTtcbiAgICBpZiAocGlubmVkKSByZXR1cm4geyBtb2RlbElkOiBwaW5uZWQsIHNvdXJjZTogXCJmYWxsYmFja1wiIH07XG4gIH1cblxuICBjb25zdCBzb3VyY2UgPSBpbnB1dC5tb2RlbENsYXNzICE9PSB1bmRlZmluZWQgPyBcImNsYXNzXCIgOiBcImZhbGxiYWNrXCI7XG4gIGlmIChpbnB1dC5tb2RlbENsYXNzID09PSB1bmRlZmluZWQpIHtcbiAgICBjb25zdCBbcHJlZmVycmVkXSA9IGxvb2t1cE1vZGVscyhlbmRwb2ludHMsIGJ1aWxkUXVlcnkoaW5wdXQsIERFRkFVTFRfTU9ERUxfRkFNSUxZX1NFQVJDSCkpO1xuICAgIGlmIChwcmVmZXJyZWQpIHJldHVybiB7IG1vZGVsSWQ6IHByZWZlcnJlZC5lbmRwb2ludC5uYW1lLCBzb3VyY2UgfTtcbiAgfVxuICBjb25zdCBbdG9wXSA9IGxvb2t1cE1vZGVscyhlbmRwb2ludHMsIGJ1aWxkUXVlcnkoaW5wdXQsIHVuZGVmaW5lZCkpO1xuICBpZiAodG9wKSByZXR1cm4geyBtb2RlbElkOiB0b3AuZW5kcG9pbnQubmFtZSwgc291cmNlIH07XG5cbiAgaWYgKGlucHV0LmxpdmVPbmx5KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gbWF0Y2hpbmcgbGl2ZSBNb2RlbCBTZXJ2aW5nIGVuZHBvaW50IGlzIGF2YWlsYWJsZVwiKTtcbiAgfVxuXG4gIGNvbnN0IGZsb29yU291cmNlID1cbiAgICBpbnB1dC5tb2RlbENsYXNzICE9PSB1bmRlZmluZWQgPyBtb2RlbHNGb3JDbGFzcyhpbnB1dC5tb2RlbENsYXNzKSA6IChpbnB1dC5mYWxsYmFja3MgPz8gW10pO1xuICBjb25zdCBmbG9vciA9IG9iamVjdC5zZXF1ZW5jZShmbG9vclNvdXJjZSkuY29uY2F0KEZBTExCQUNLX01PREVMX0lEUykuZGlzdGluY3QoKS50b0FycmF5KCk7XG4gIGlmIChpbnB1dC5yZXF1aXJlc1Rvb2xzKSB7XG4gICAgY29uc3QgYXZhaWxhYmxlID0gbmV3IFNldChcbiAgICAgIGVuZHBvaW50cy5maWx0ZXIoZW5kcG9pbnRTdXBwb3J0c1Rvb2xzKS5tYXAoKGVuZHBvaW50KSA9PiBlbmRwb2ludC5uYW1lKSxcbiAgICApO1xuICAgIGNvbnN0IHNlbGVjdGVkID0gZmxvb3IuZmluZCgoaWQpID0+IGF2YWlsYWJsZS5oYXMoaWQpKTtcbiAgICBpZiAoIXNlbGVjdGVkKSB0aHJvdyBuZXcgRXJyb3IoXCJObyB0b29sLWNhcGFibGUgbW9kZWwgaXMgYXZhaWxhYmxlXCIpO1xuICAgIHJldHVybiB7IG1vZGVsSWQ6IHNlbGVjdGVkLCBzb3VyY2UgfTtcbiAgfVxuICByZXR1cm4geyBtb2RlbElkOiBwaWNrRmlyc3RBdmFpbGFibGUoZmxvb3IsIGVuZHBvaW50cyksIHNvdXJjZSB9O1xufVxuXG5mdW5jdGlvbiBidWlsZFF1ZXJ5KGlucHV0OiBSZXNvbHZlTW9kZWxJbnB1dCwgc2VhcmNoOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBNb2RlbFF1ZXJ5IHtcbiAgcmV0dXJuIHtcbiAgICAuLi4oc2VhcmNoICE9PSB1bmRlZmluZWQgPyB7IHNlYXJjaCB9IDoge30pLFxuICAgIC4uLihpbnB1dC5tb2RlbENsYXNzICE9PSB1bmRlZmluZWQgPyB7IG1vZGVsQ2xhc3M6IGlucHV0Lm1vZGVsQ2xhc3MgfSA6IHt9KSxcbiAgICAuLi4oaW5wdXQucmVxdWlyZXNUb29scyAhPT0gdW5kZWZpbmVkID8geyByZXF1aXJlc1Rvb2xzOiBpbnB1dC5yZXF1aXJlc1Rvb2xzIH0gOiB7fSksXG4gICAgLi4uKGlucHV0LnRocmVzaG9sZCAhPT0gdW5kZWZpbmVkID8geyB0aHJlc2hvbGQ6IGlucHV0LnRocmVzaG9sZCB9IDoge30pLFxuICAgIGxpbWl0OiAxLFxuICB9O1xufVxuXG5mdW5jdGlvbiBhc3NlcnRUb29sU3VwcG9ydChlbmRwb2ludHM6IHJlYWRvbmx5IFNlcnZpbmdFbmRwb2ludFN1bW1hcnlbXSwgbW9kZWxJZDogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IGVuZHBvaW50ID0gZW5kcG9pbnRzLmZpbmQoKGNhbmRpZGF0ZSkgPT4gY2FuZGlkYXRlLm5hbWUgPT09IG1vZGVsSWQpO1xuICBpZiAoIWVuZHBvaW50IHx8ICFlbmRwb2ludFN1cHBvcnRzVG9vbHMoZW5kcG9pbnQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBNb2RlbCBcIiR7bW9kZWxJZH1cIiBkb2VzIG5vdCBzdXBwb3J0IGZ1bmN0aW9uIHRvb2xzYCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcGlja0ZpcnN0QXZhaWxhYmxlKFxuICBjYW5kaWRhdGVzOiByZWFkb25seSBzdHJpbmdbXSxcbiAgZW5kcG9pbnRzOiByZWFkb25seSBTZXJ2aW5nRW5kcG9pbnRTdW1tYXJ5W10sXG4pOiBzdHJpbmcge1xuICBjb25zdCBwcmVzZW50ID0gbmV3IFNldChlbmRwb2ludHMubWFwKChlbmRwb2ludCkgPT4gZW5kcG9pbnQubmFtZSkpO1xuICBmb3IgKGNvbnN0IGNhbmRpZGF0ZSBvZiBjYW5kaWRhdGVzKSB7XG4gICAgaWYgKHByZXNlbnQuaGFzKGNhbmRpZGF0ZSkpIHJldHVybiBjYW5kaWRhdGU7XG4gIH1cbiAgcmV0dXJuIGNhbmRpZGF0ZXNbMF0gPz8gRkFMTEJBQ0tfTU9ERUxfSURTWzBdITtcbn1cbiJdfQ==
@@ -9,8 +9,8 @@
9
9
  *
10
10
  * @module
11
11
  */
12
- import { model } from "@dbx-tools/shared-model";
13
- type ModelClass = model.ModelClass;
12
+ import { type ModelClass as ModelClassType } from "@dbx-tools/shared-model/contracts";
13
+ type ModelClass = ModelClassType;
14
14
  declare const ModelClass: {
15
15
  readonly ChatThinking: "chat-thinking";
16
16
  readonly ChatBalanced: "chat-balanced";
@@ -9,8 +9,9 @@
9
9
  *
10
10
  * @module
11
11
  */
12
- import { model } from "@dbx-tools/shared-model";
13
- const { ModelClass, ModelClassSchema } = model;
12
+ import { ModelClass as ModelClassValues, } from "@dbx-tools/shared-model/contracts";
13
+ const ModelClass = ModelClassValues;
14
+ const MODEL_CLASSES = new Set(Object.values(ModelClassValues));
14
15
  /**
15
16
  * Chat capability ladder in descending order - most capable
16
17
  * ({@link ModelClass.ChatThinking}) first, least ({@link ModelClass.ChatFast})
@@ -43,11 +44,12 @@ export function isChatClass(cls) {
43
44
  * `"balanced"` / `"fast"` resolves to the corresponding `chat-*` class.
44
45
  */
45
46
  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;
47
+ if (typeof value !== "string")
48
+ return null;
49
+ if (MODEL_CLASSES.has(value))
50
+ return value;
51
+ const prefixed = `chat-${value}`;
52
+ return MODEL_CLASSES.has(prefixed) ? prefixed : null;
51
53
  }
52
54
  /**
53
55
  * Classes at or below `cls` in chat capability: the class itself plus every
@@ -67,4 +69,4 @@ export function classesAtOrBelow(cls) {
67
69
  const index = CHAT_CLASS_ORDER.indexOf(cls);
68
70
  return index < 0 ? [...CHAT_CLASS_ORDER] : [...CHAT_CLASS_ORDER.slice(index)];
69
71
  }
70
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbGFzc2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7O0dBVUc7QUFFSCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHaEQsTUFBTSxFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsRUFBRSxHQUFHLEtBQUssQ0FBQztBQUUvQzs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBMEI7SUFDckQsVUFBVSxDQUFDLFlBQVk7SUFDdkIsVUFBVSxDQUFDLFlBQVk7SUFDdkIsVUFBVSxDQUFDLFFBQVE7Q0FDcEIsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBMEIsQ0FBQyxHQUFHLGdCQUFnQixFQUFFLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUVwRyx5RUFBeUU7QUFDekUsTUFBTSxVQUFVLFdBQVcsQ0FBQyxHQUFlO0lBQ3pDLE9BQU8sZ0JBQWdCLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ3hDLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQUMsS0FBYztJQUM1QyxNQUFNLEtBQUssR0FBRyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDaEQsSUFBSSxLQUFLLENBQUMsT0FBTztRQUFFLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQztJQUNyQyxNQUFNLFFBQVEsR0FBRyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsUUFBUSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQzdELE9BQU8sUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0FBQ2pELENBQUM7QUFFRDs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxHQUFlO0lBQzlDLElBQUksR0FBRyxLQUFLLFVBQVUsQ0FBQyxTQUFTO1FBQUUsT0FBTyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNoRSxNQUFNLEtBQUssR0FBRyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDNUMsT0FBTyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQ2hGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE1vZGVsLWNsYXNzIG9yZGVyaW5nIGZvciB0aGUgbW9kZWwgc2VydmljZS5cbiAqXG4gKiBgQGRieC10b29scy9zaGFyZWQtbW9kZWxgIGRlY2xhcmVzIHRoZSB7QGxpbmsgTW9kZWxDbGFzc30gdmFsdWVzIGFuZCB0aGVpclxuICogc2NoZW1hOyB0aGUgKmJlaGF2aW9yKiBvdmVyIHRob3NlIHZhbHVlcyAtIHRoZSBjaGF0IGNhcGFiaWxpdHkgb3JkZXIsIHRoZVxuICogXCJ0aGlzIGNsYXNzIGFuZCBiZWxvd1wiIGNlaWxpbmcsIGFuZCBjb2VyY2luZyBsb29zZSByZXF1ZXN0IGlucHV0IHRvIGEgY2xhc3MgLVxuICogbGl2ZXMgaGVyZSBpbiB0aGUgc2VydmljZSBzbyB0aGUgc2hhcmVkIHdpcmUtZm9ybWF0IHN1cmZhY2Ugc3RheXMgcHVyZWx5XG4gKiBkZWNsYXJhdGl2ZS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgbW9kZWwgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtbW9kZWxcIjtcblxudHlwZSBNb2RlbENsYXNzID0gbW9kZWwuTW9kZWxDbGFzcztcbmNvbnN0IHsgTW9kZWxDbGFzcywgTW9kZWxDbGFzc1NjaGVtYSB9ID0gbW9kZWw7XG5cbi8qKlxuICogQ2hhdCBjYXBhYmlsaXR5IGxhZGRlciBpbiBkZXNjZW5kaW5nIG9yZGVyIC0gbW9zdCBjYXBhYmxlXG4gKiAoe0BsaW5rIE1vZGVsQ2xhc3MuQ2hhdFRoaW5raW5nfSkgZmlyc3QsIGxlYXN0ICh7QGxpbmsgTW9kZWxDbGFzcy5DaGF0RmFzdH0pXG4gKiBsYXN0LiB7QGxpbmsgTW9kZWxDbGFzcy5FbWJlZGRpbmd9IGlzIGEgc2VwYXJhdGUgbW9kYWxpdHkgYW5kIGlzIGRlbGliZXJhdGVseVxuICogYWJzZW50OiB0aGUgY2VpbGluZyBuZXZlciBzcGFucyBpdC4gVGhpcyBpcyB0aGUgb3JkZXIgdXNlZCB0byBmaWx0ZXIgXCJ0aGlzXG4gKiBjbGFzcyBhbmQgYmVsb3dcIiBhbmQgdG8gYnJlYWsgcmFua2luZyB0aWVzIHRvd2FyZCB0aGUgbW9yZSBjYXBhYmxlIG1vZGVsLlxuICovXG5leHBvcnQgY29uc3QgQ0hBVF9DTEFTU19PUkRFUjogcmVhZG9ubHkgTW9kZWxDbGFzc1tdID0gW1xuICBNb2RlbENsYXNzLkNoYXRUaGlua2luZyxcbiAgTW9kZWxDbGFzcy5DaGF0QmFsYW5jZWQsXG4gIE1vZGVsQ2xhc3MuQ2hhdEZhc3QsXG5dO1xuXG4vKipcbiAqIEV2ZXJ5IGNsYXNzIGluIGRpc3BsYXkgb3JkZXI6IHRoZSBjaGF0IGxhZGRlciBmb2xsb3dlZCBieVxuICoge0BsaW5rIE1vZGVsQ2xhc3MuRW1iZWRkaW5nfS4gVXNlZCB3aGVuIGZsYXR0ZW5pbmcgYSBmdWxsIGNsYXNzaWZpY2F0aW9uXG4gKiAoZS5nLiBzdGFtcGluZyB0aGUgY2xhc3Mgb250byBlYWNoIGNhY2hlZCBlbmRwb2ludCkuXG4gKi9cbmV4cG9ydCBjb25zdCBNT0RFTF9DTEFTU19PUkRFUjogcmVhZG9ubHkgTW9kZWxDbGFzc1tdID0gWy4uLkNIQVRfQ0xBU1NfT1JERVIsIE1vZGVsQ2xhc3MuRW1iZWRkaW5nXTtcblxuLyoqIFdoZXRoZXIgYGNsc2AgaXMgb25lIG9mIHRoZSBjaGF0IGNhcGFiaWxpdHkgYmFuZHMgKHZzLiBlbWJlZGRpbmcpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQ2hhdENsYXNzKGNsczogTW9kZWxDbGFzcyk6IGJvb2xlYW4ge1xuICByZXR1cm4gQ0hBVF9DTEFTU19PUkRFUi5pbmNsdWRlcyhjbHMpO1xufVxuXG4vKipcbiAqIENvZXJjZSBhbiBhcmJpdHJhcnkgdmFsdWUgKHF1ZXJ5IHN0cmluZywgaGVhZGVyLCBib2R5IGZpZWxkKSB0byBhXG4gKiB7QGxpbmsgTW9kZWxDbGFzc30sIHJldHVybmluZyBgbnVsbGAgd2hlbiBpdCBpc24ndCBhIGtub3duIGNsYXNzLiBMZXRzIGFcbiAqIHJvdXRlIGFjY2VwdCBhIGNsYXNzIHJlcXVlc3Qgd2l0aG91dCB0aHJvd2luZyBvbiBqdW5rIGlucHV0LlxuICpcbiAqIE1hdGNoZXMgdGhlIGZ1bGwgc2x1ZyBmaXJzdCAoYFwiY2hhdC1mYXN0XCJgLCBgXCJlbWJlZGRpbmdcImApLCB0aGVuIC0gZm9yIGEgYmFyZVxuICogY2hhdCBiYW5kIC0gcmV0cmllcyB3aXRoIGEgYGNoYXQtYCBwcmVmaXgsIHNvIHRoZSBzaG9ydGhhbmQgYFwidGhpbmtpbmdcImAgL1xuICogYFwiYmFsYW5jZWRcImAgLyBgXCJmYXN0XCJgIHJlc29sdmVzIHRvIHRoZSBjb3JyZXNwb25kaW5nIGBjaGF0LSpgIGNsYXNzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VNb2RlbENsYXNzKHZhbHVlOiB1bmtub3duKTogTW9kZWxDbGFzcyB8IG51bGwge1xuICBjb25zdCBleGFjdCA9IE1vZGVsQ2xhc3NTY2hlbWEuc2FmZVBhcnNlKHZhbHVlKTtcbiAgaWYgKGV4YWN0LnN1Y2Nlc3MpIHJldHVybiBleGFjdC5kYXRhO1xuICBjb25zdCBwcmVmaXhlZCA9IE1vZGVsQ2xhc3NTY2hlbWEuc2FmZVBhcnNlKGBjaGF0LSR7dmFsdWV9YCk7XG4gIHJldHVybiBwcmVmaXhlZC5zdWNjZXNzID8gcHJlZml4ZWQuZGF0YSA6IG51bGw7XG59XG5cbi8qKlxuICogQ2xhc3NlcyBhdCBvciBiZWxvdyBgY2xzYCBpbiBjaGF0IGNhcGFiaWxpdHk6IHRoZSBjbGFzcyBpdHNlbGYgcGx1cyBldmVyeVxuICogbGVzcy1jYXBhYmxlIGNoYXQgYmFuZCwgaW4ge0BsaW5rIENIQVRfQ0xBU1NfT1JERVJ9LiBUcmVhdHMgYSBjaGF0IGBjbHNgIGFzIGFcbiAqIGNlaWxpbmcgLSByZXF1ZXN0aW5nIHtAbGluayBNb2RlbENsYXNzLkNoYXRCYWxhbmNlZH0geWllbGRzXG4gKiBgW0NoYXRCYWxhbmNlZCwgQ2hhdEZhc3RdYCwgbmV2ZXIge0BsaW5rIE1vZGVsQ2xhc3MuQ2hhdFRoaW5raW5nfSAtIHNvIGFcbiAqIGNsYXNzIGFzayBjYW4gZGVncmFkZSBkb3dud2FyZCB0byBhIHNtYWxsZXIgY2hhdCBtb2RlbCBidXQgbmV2ZXIgZXNjYWxhdGUgdG9cbiAqIGEgbGFyZ2VyIG9uZS5cbiAqXG4gKiB7QGxpbmsgTW9kZWxDbGFzcy5FbWJlZGRpbmd9IGlzIGl0cyBvd24gbW9kYWxpdHksIG5vdCBhIHJ1bmcgb24gdGhlIGNoYXRcbiAqIGxhZGRlciwgc28gaXQgeWllbGRzIGp1c3QgYFtFbWJlZGRpbmddYC4gQW4gdW5yZWNvZ25pemVkIGNsYXNzIHlpZWxkcyB0aGVcbiAqIGZ1bGwgY2hhdCBsYWRkZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGFzc2VzQXRPckJlbG93KGNsczogTW9kZWxDbGFzcyk6IE1vZGVsQ2xhc3NbXSB7XG4gIGlmIChjbHMgPT09IE1vZGVsQ2xhc3MuRW1iZWRkaW5nKSByZXR1cm4gW01vZGVsQ2xhc3MuRW1iZWRkaW5nXTtcbiAgY29uc3QgaW5kZXggPSBDSEFUX0NMQVNTX09SREVSLmluZGV4T2YoY2xzKTtcbiAgcmV0dXJuIGluZGV4IDwgMCA/IFsuLi5DSEFUX0NMQVNTX09SREVSXSA6IFsuLi5DSEFUX0NMQVNTX09SREVSLnNsaWNlKGluZGV4KV07XG59XG4iXX0=
72
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbGFzc2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7O0dBVUc7QUFFSCxPQUFPLEVBQ0wsVUFBVSxJQUFJLGdCQUFnQixHQUUvQixNQUFNLG1DQUFtQyxDQUFDO0FBRzNDLE1BQU0sVUFBVSxHQUFHLGdCQUFnQixDQUFDO0FBQ3BDLE1BQU0sYUFBYSxHQUFHLElBQUksR0FBRyxDQUFhLE1BQU0sQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO0FBRTNFOzs7Ozs7R0FNRztBQUNILE1BQU0sQ0FBQyxNQUFNLGdCQUFnQixHQUEwQjtJQUNyRCxVQUFVLENBQUMsWUFBWTtJQUN2QixVQUFVLENBQUMsWUFBWTtJQUN2QixVQUFVLENBQUMsUUFBUTtDQUNwQixDQUFDO0FBRUY7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUEwQixDQUFDLEdBQUcsZ0JBQWdCLEVBQUUsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBRXBHLHlFQUF5RTtBQUN6RSxNQUFNLFVBQVUsV0FBVyxDQUFDLEdBQWU7SUFDekMsT0FBTyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDeEMsQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FBQyxLQUFjO0lBQzVDLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUTtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQzNDLElBQUksYUFBYSxDQUFDLEdBQUcsQ0FBQyxLQUFtQixDQUFDO1FBQUUsT0FBTyxLQUFtQixDQUFDO0lBQ3ZFLE1BQU0sUUFBUSxHQUFHLFFBQVEsS0FBSyxFQUFnQixDQUFDO0lBQy9DLE9BQU8sYUFBYSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDdkQsQ0FBQztBQUVEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLEdBQWU7SUFDOUMsSUFBSSxHQUFHLEtBQUssVUFBVSxDQUFDLFNBQVM7UUFBRSxPQUFPLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ2hFLE1BQU0sS0FBSyxHQUFHLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM1QyxPQUFPLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDaEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTW9kZWwtY2xhc3Mgb3JkZXJpbmcgZm9yIHRoZSBtb2RlbCBzZXJ2aWNlLlxuICpcbiAqIGBAZGJ4LXRvb2xzL3NoYXJlZC1tb2RlbGAgZGVjbGFyZXMgdGhlIHtAbGluayBNb2RlbENsYXNzfSB2YWx1ZXMgYW5kIHRoZWlyXG4gKiBzY2hlbWE7IHRoZSAqYmVoYXZpb3IqIG92ZXIgdGhvc2UgdmFsdWVzIC0gdGhlIGNoYXQgY2FwYWJpbGl0eSBvcmRlciwgdGhlXG4gKiBcInRoaXMgY2xhc3MgYW5kIGJlbG93XCIgY2VpbGluZywgYW5kIGNvZXJjaW5nIGxvb3NlIHJlcXVlc3QgaW5wdXQgdG8gYSBjbGFzcyAtXG4gKiBsaXZlcyBoZXJlIGluIHRoZSBzZXJ2aWNlIHNvIHRoZSBzaGFyZWQgd2lyZS1mb3JtYXQgc3VyZmFjZSBzdGF5cyBwdXJlbHlcbiAqIGRlY2xhcmF0aXZlLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQge1xuICBNb2RlbENsYXNzIGFzIE1vZGVsQ2xhc3NWYWx1ZXMsXG4gIHR5cGUgTW9kZWxDbGFzcyBhcyBNb2RlbENsYXNzVHlwZSxcbn0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLW1vZGVsL2NvbnRyYWN0c1wiO1xuXG50eXBlIE1vZGVsQ2xhc3MgPSBNb2RlbENsYXNzVHlwZTtcbmNvbnN0IE1vZGVsQ2xhc3MgPSBNb2RlbENsYXNzVmFsdWVzO1xuY29uc3QgTU9ERUxfQ0xBU1NFUyA9IG5ldyBTZXQ8TW9kZWxDbGFzcz4oT2JqZWN0LnZhbHVlcyhNb2RlbENsYXNzVmFsdWVzKSk7XG5cbi8qKlxuICogQ2hhdCBjYXBhYmlsaXR5IGxhZGRlciBpbiBkZXNjZW5kaW5nIG9yZGVyIC0gbW9zdCBjYXBhYmxlXG4gKiAoe0BsaW5rIE1vZGVsQ2xhc3MuQ2hhdFRoaW5raW5nfSkgZmlyc3QsIGxlYXN0ICh7QGxpbmsgTW9kZWxDbGFzcy5DaGF0RmFzdH0pXG4gKiBsYXN0LiB7QGxpbmsgTW9kZWxDbGFzcy5FbWJlZGRpbmd9IGlzIGEgc2VwYXJhdGUgbW9kYWxpdHkgYW5kIGlzIGRlbGliZXJhdGVseVxuICogYWJzZW50OiB0aGUgY2VpbGluZyBuZXZlciBzcGFucyBpdC4gVGhpcyBpcyB0aGUgb3JkZXIgdXNlZCB0byBmaWx0ZXIgXCJ0aGlzXG4gKiBjbGFzcyBhbmQgYmVsb3dcIiBhbmQgdG8gYnJlYWsgcmFua2luZyB0aWVzIHRvd2FyZCB0aGUgbW9yZSBjYXBhYmxlIG1vZGVsLlxuICovXG5leHBvcnQgY29uc3QgQ0hBVF9DTEFTU19PUkRFUjogcmVhZG9ubHkgTW9kZWxDbGFzc1tdID0gW1xuICBNb2RlbENsYXNzLkNoYXRUaGlua2luZyxcbiAgTW9kZWxDbGFzcy5DaGF0QmFsYW5jZWQsXG4gIE1vZGVsQ2xhc3MuQ2hhdEZhc3QsXG5dO1xuXG4vKipcbiAqIEV2ZXJ5IGNsYXNzIGluIGRpc3BsYXkgb3JkZXI6IHRoZSBjaGF0IGxhZGRlciBmb2xsb3dlZCBieVxuICoge0BsaW5rIE1vZGVsQ2xhc3MuRW1iZWRkaW5nfS4gVXNlZCB3aGVuIGZsYXR0ZW5pbmcgYSBmdWxsIGNsYXNzaWZpY2F0aW9uXG4gKiAoZS5nLiBzdGFtcGluZyB0aGUgY2xhc3Mgb250byBlYWNoIGNhY2hlZCBlbmRwb2ludCkuXG4gKi9cbmV4cG9ydCBjb25zdCBNT0RFTF9DTEFTU19PUkRFUjogcmVhZG9ubHkgTW9kZWxDbGFzc1tdID0gWy4uLkNIQVRfQ0xBU1NfT1JERVIsIE1vZGVsQ2xhc3MuRW1iZWRkaW5nXTtcblxuLyoqIFdoZXRoZXIgYGNsc2AgaXMgb25lIG9mIHRoZSBjaGF0IGNhcGFiaWxpdHkgYmFuZHMgKHZzLiBlbWJlZGRpbmcpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQ2hhdENsYXNzKGNsczogTW9kZWxDbGFzcyk6IGJvb2xlYW4ge1xuICByZXR1cm4gQ0hBVF9DTEFTU19PUkRFUi5pbmNsdWRlcyhjbHMpO1xufVxuXG4vKipcbiAqIENvZXJjZSBhbiBhcmJpdHJhcnkgdmFsdWUgKHF1ZXJ5IHN0cmluZywgaGVhZGVyLCBib2R5IGZpZWxkKSB0byBhXG4gKiB7QGxpbmsgTW9kZWxDbGFzc30sIHJldHVybmluZyBgbnVsbGAgd2hlbiBpdCBpc24ndCBhIGtub3duIGNsYXNzLiBMZXRzIGFcbiAqIHJvdXRlIGFjY2VwdCBhIGNsYXNzIHJlcXVlc3Qgd2l0aG91dCB0aHJvd2luZyBvbiBqdW5rIGlucHV0LlxuICpcbiAqIE1hdGNoZXMgdGhlIGZ1bGwgc2x1ZyBmaXJzdCAoYFwiY2hhdC1mYXN0XCJgLCBgXCJlbWJlZGRpbmdcImApLCB0aGVuIC0gZm9yIGEgYmFyZVxuICogY2hhdCBiYW5kIC0gcmV0cmllcyB3aXRoIGEgYGNoYXQtYCBwcmVmaXgsIHNvIHRoZSBzaG9ydGhhbmQgYFwidGhpbmtpbmdcImAgL1xuICogYFwiYmFsYW5jZWRcImAgLyBgXCJmYXN0XCJgIHJlc29sdmVzIHRvIHRoZSBjb3JyZXNwb25kaW5nIGBjaGF0LSpgIGNsYXNzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VNb2RlbENsYXNzKHZhbHVlOiB1bmtub3duKTogTW9kZWxDbGFzcyB8IG51bGwge1xuICBpZiAodHlwZW9mIHZhbHVlICE9PSBcInN0cmluZ1wiKSByZXR1cm4gbnVsbDtcbiAgaWYgKE1PREVMX0NMQVNTRVMuaGFzKHZhbHVlIGFzIE1vZGVsQ2xhc3MpKSByZXR1cm4gdmFsdWUgYXMgTW9kZWxDbGFzcztcbiAgY29uc3QgcHJlZml4ZWQgPSBgY2hhdC0ke3ZhbHVlfWAgYXMgTW9kZWxDbGFzcztcbiAgcmV0dXJuIE1PREVMX0NMQVNTRVMuaGFzKHByZWZpeGVkKSA/IHByZWZpeGVkIDogbnVsbDtcbn1cblxuLyoqXG4gKiBDbGFzc2VzIGF0IG9yIGJlbG93IGBjbHNgIGluIGNoYXQgY2FwYWJpbGl0eTogdGhlIGNsYXNzIGl0c2VsZiBwbHVzIGV2ZXJ5XG4gKiBsZXNzLWNhcGFibGUgY2hhdCBiYW5kLCBpbiB7QGxpbmsgQ0hBVF9DTEFTU19PUkRFUn0uIFRyZWF0cyBhIGNoYXQgYGNsc2AgYXMgYVxuICogY2VpbGluZyAtIHJlcXVlc3Rpbmcge0BsaW5rIE1vZGVsQ2xhc3MuQ2hhdEJhbGFuY2VkfSB5aWVsZHNcbiAqIGBbQ2hhdEJhbGFuY2VkLCBDaGF0RmFzdF1gLCBuZXZlciB7QGxpbmsgTW9kZWxDbGFzcy5DaGF0VGhpbmtpbmd9IC0gc28gYVxuICogY2xhc3MgYXNrIGNhbiBkZWdyYWRlIGRvd253YXJkIHRvIGEgc21hbGxlciBjaGF0IG1vZGVsIGJ1dCBuZXZlciBlc2NhbGF0ZSB0b1xuICogYSBsYXJnZXIgb25lLlxuICpcbiAqIHtAbGluayBNb2RlbENsYXNzLkVtYmVkZGluZ30gaXMgaXRzIG93biBtb2RhbGl0eSwgbm90IGEgcnVuZyBvbiB0aGUgY2hhdFxuICogbGFkZGVyLCBzbyBpdCB5aWVsZHMganVzdCBgW0VtYmVkZGluZ11gLiBBbiB1bnJlY29nbml6ZWQgY2xhc3MgeWllbGRzIHRoZVxuICogZnVsbCBjaGF0IGxhZGRlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsYXNzZXNBdE9yQmVsb3coY2xzOiBNb2RlbENsYXNzKTogTW9kZWxDbGFzc1tdIHtcbiAgaWYgKGNscyA9PT0gTW9kZWxDbGFzcy5FbWJlZGRpbmcpIHJldHVybiBbTW9kZWxDbGFzcy5FbWJlZGRpbmddO1xuICBjb25zdCBpbmRleCA9IENIQVRfQ0xBU1NfT1JERVIuaW5kZXhPZihjbHMpO1xuICByZXR1cm4gaW5kZXggPCAwID8gWy4uLkNIQVRfQ0xBU1NfT1JERVJdIDogWy4uLkNIQVRfQ0xBU1NfT1JERVIuc2xpY2UoaW5kZXgpXTtcbn1cbiJdfQ==
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Model-class classification for Databricks Model Serving endpoints.
3
+ *
4
+ * Chat capability bands are derived from the live workspace catalogue
5
+ * rather than a hand-maintained table. Databricks publishes
6
+ * per-endpoint `quality` / `speed` / `cost` scores (the AI Playground
7
+ * bars) on the serving list; {@link classifyEndpoints} buckets scored
8
+ * chat models into the chat {@link ModelClass} bands by the *relative*
9
+ * distribution of those scores (quantiles, not fixed cut-offs) so a
10
+ * brand-new model that lands outside today's score range still slots in
11
+ * next to its peers. Embedding endpoints (`task === "llm/v1/embeddings"`)
12
+ * are bucketed into {@link ModelClass.Embedding} by task, independent of
13
+ * any score.
14
+ *
15
+ * Unscored-but-recognizable chat endpoints are still placed by a small
16
+ * family heuristic ({@link classifyByFamily}) so a workspace whose
17
+ * models predate Foundation Model API scoring keeps working. The
18
+ * offline fallback floor - the hard-coded model list reached for when
19
+ * the live catalogue can't be read at all - is a server concern and
20
+ * lives in `@dbx-tools/model`, not here: a browser client never talks
21
+ * to Databricks directly, so it has nothing to fall back to.
22
+ *
23
+ * Pure (no Node-only imports), so a client can classify a `/models`
24
+ * response without server dependencies.
25
+ *
26
+ * @module
27
+ */
28
+ import { type ModelClass as ModelClassType, type ServingEndpointSummary } from "@dbx-tools/shared-model/contracts";
29
+ type ModelClass = ModelClassType;
30
+ declare const ModelClass: {
31
+ readonly ChatThinking: "chat-thinking";
32
+ readonly ChatBalanced: "chat-balanced";
33
+ readonly ChatFast: "chat-fast";
34
+ readonly Embedding: "embedding";
35
+ };
36
+ /** What an endpoint can be asked to do, as derived by {@link endpointCapabilities}. */
37
+ export interface EndpointCapabilities {
38
+ /** OpenAI chat/completions + Responses: the surface a chat agent needs. */
39
+ chat: boolean;
40
+ /** Embedding (vector) endpoint. */
41
+ embedding: boolean;
42
+ /** Complete function-tool round-trip (call plus function_call_output replay). */
43
+ tools: boolean;
44
+ }
45
+ /**
46
+ * Provider families verified against Databricks Responses/Open Responses with
47
+ * both a forced function call and a stateless `function_call_output` replay.
48
+ *
49
+ * Databricks' endpoint list/OpenAPI currently exposes no tools capability bit.
50
+ * Keep this conservative: an unknown chat family is not agent-safe until it is
51
+ * verified. Gemini is excluded because it emits a call but Open Responses
52
+ * cannot replay the required thought signature; GPT-OSS rejects Responses
53
+ * passthrough entirely.
54
+ */
55
+ export declare function supportsToolsByFamily(name: string): boolean;
56
+ /**
57
+ * Derive an endpoint's capabilities from its Databricks task hint and its
58
+ * classified {@link ModelClass}, so consumers filter on capability instead of
59
+ * re-deriving it from raw `task` / `class` strings.
60
+ *
61
+ * Either signal alone is enough: the task hint is authoritative when present,
62
+ * and the class covers endpoints Databricks left untasked but the classifier
63
+ * recognized. Embedding wins over chat when both point at it, since the two are
64
+ * not interchangeable.
65
+ */
66
+ export declare function endpointCapabilities(endpoint: ServingEndpointSummary): EndpointCapabilities;
67
+ /** Family-heuristic classification of a single endpoint name. */
68
+ export interface FamilyClass {
69
+ /** Chat capability band the family maps to (never embedding). */
70
+ class: ModelClass;
71
+ /** Intra-family ordering hint (higher is newer / more capable). */
72
+ rank: number;
73
+ }
74
+ /**
75
+ * Numeric `[major, minor, patch]` version parsed from an endpoint
76
+ * name, used to order siblings within a family/tier. Starts at the
77
+ * first digit in the name, then reads successive separator-delimited,
78
+ * digit-prefixed chunks as the three components (missing ones default
79
+ * to `0`):
80
+ *
81
+ * - `databricks-claude-opus-4-8` -> `[4, 8, 0]`
82
+ * - `databricks-claude-opus-4-10` -> `[4, 10, 0]` (sorts above 4-8)
83
+ * - `databricks-meta-llama-3-3-70b`-> `[3, 3, 70]`
84
+ * - `databricks-bge-large-en` -> `[0, 0, 0]` (no digits)
85
+ *
86
+ * Component-wise comparison (not a decimal collapse) so `4.10` beats
87
+ * `4.8` - the bug a `major + minor/10` score would hit.
88
+ */
89
+ export declare function versionTuple(name: string): [number, number, number];
90
+ /**
91
+ * Best-effort chat capability band for an endpoint we have no live
92
+ * score for, keyed off provider family and the well-known variant words
93
+ * in the name (`opus`/`sonnet`/`haiku`, `pro`/`mini`/`nano`,
94
+ * `flash`/`flash-lite`, Llama parameter sizes, etc). Returns `null` for
95
+ * names we don't recognize so unknown custom endpoints are never
96
+ * auto-selected as a default. The accompanying `rank` orders siblings
97
+ * within a class. Only ever returns a chat band - embedding endpoints
98
+ * are classified by task, not name.
99
+ */
100
+ export declare function classifyByFamily(name: string): FamilyClass | null;
101
+ /**
102
+ * Bucket live endpoints into {@link ModelClass}es, ranked best-first
103
+ * within each chat band.
104
+ *
105
+ * Embedding endpoints (`task === "llm/v1/embeddings"`) go into
106
+ * {@link ModelClass.Embedding} by task, in listing order (they carry no
107
+ * capability score to rank on).
108
+ *
109
+ * Chat endpoints (`task === "llm/v1/chat"`) split into the three chat
110
+ * bands. Scored endpoints (those carrying a `profile.quality`) drive
111
+ * the banding: the observed quality distribution is split at its 1/3
112
+ * and 2/3 quantiles, so the top third is {@link ModelClass.ChatThinking},
113
+ * the bottom third {@link ModelClass.ChatFast}, and the middle
114
+ * {@link ModelClass.ChatBalanced}. Because the thresholds come from the
115
+ * data, the split adapts as Databricks adds or rescores models -
116
+ * nothing is pinned to a fixed score band.
117
+ *
118
+ * Unscored chat endpoints are placed by {@link classifyByFamily} and
119
+ * ranked after the scored ones in their band; unrecognized, unscored
120
+ * endpoints (e.g. custom external models) are omitted entirely so they
121
+ * are never picked as an automatic default.
122
+ *
123
+ * Within a chat band, scored models sort by `quality` desc, then `cost`
124
+ * asc, then `speed` desc, then parsed name version desc; family-only
125
+ * models sort by version rank then parsed version. The version
126
+ * tie-break ({@link versionTuple}) is what separates point releases
127
+ * that share a score profile (e.g. `opus-4-8` ahead of `opus-4-7`).
128
+ */
129
+ export declare function classifyEndpoints(endpoints: readonly ServingEndpointSummary[]): Record<ModelClass, ServingEndpointSummary[]>;
130
+ export {};