@dbx-tools/model 0.9.19 → 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 (58) 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/lib/src/_native.d.ts +0 -14
  57. package/lib/src/_native.js +0 -124
  58. package/src/_native.ts +0 -174
package/README.md CHANGED
@@ -14,7 +14,7 @@ Browser-safe request/result schemas and endpoint classification types live in
14
14
  Key features:
15
15
 
16
16
  - Lists Databricks Model Serving endpoints through the SDK and normalizes them
17
- into a stable summary shape with Rust-derived family and reasoning-effort
17
+ into a stable summary shape with TypeScript-owned family and reasoning-effort
18
18
  metadata.
19
19
  - Classifies endpoints into chat-thinking, chat-balanced, chat-fast, and
20
20
  embedding classes using Foundation Model API scores and family heuristics.
@@ -28,6 +28,8 @@ Key features:
28
28
  and re-lists once on a resolve miss so a newly deployed model still resolves.
29
29
  - Builds the invocations URL and mints per-request auth headers for callers that
30
30
  issue their own OpenAI-shaped HTTP requests.
31
+ - Provides build-generated retirement, Responses, image-input, apply-patch,
32
+ web-search, ITPM, OTPM, and QPH metadata through cached in-process lookups.
31
33
  - Provides a small static fallback floor for local tools and degraded workspace
32
34
  access.
33
35
 
@@ -51,6 +53,37 @@ endpoint:
51
53
  - keep local agents and CLIs working with a static fallback when catalogue
52
54
  access is unavailable.
53
55
 
56
+ ## Use The Portable Model Client
57
+
58
+ ```ts
59
+ import { createModelClient } from "@dbx-tools/model";
60
+
61
+ const models = await createModelClient({
62
+ auth: { profile: "DEFAULT" },
63
+ cacheTtlMs: 60_000,
64
+ });
65
+
66
+ const selected = await models.resolveModel({ explicit: "gpt" });
67
+ const route = await models.route({
68
+ explicit: selected.modelId,
69
+ protocol: "responses",
70
+ });
71
+
72
+ const response = await fetch(route.url, {
73
+ method: "POST",
74
+ headers: { ...route.headers, "content-type": "application/json" },
75
+ body: JSON.stringify({ model: route.modelId, input: "Hello" }),
76
+ });
77
+ ```
78
+
79
+ `createModelClient()` is the portable auth-backed facade embedded by the Python
80
+ model proxy. It lists and normalizes endpoints, caches one
81
+ catalogue per host, workspace ID, and principal, refreshes once after an
82
+ unmatched fuzzy request, resolves routes, returns complete authentication
83
+ headers, exposes profiles, and returns the package's generated metadata. Its
84
+ portable `@dbx-tools/model/python` entrypoint excludes the AppKit catalogue
85
+ wrapper while reusing the same pure ranking and policy implementation.
86
+
54
87
  ## Select One Model
55
88
 
56
89
  ```ts
@@ -95,10 +128,9 @@ const ranked = await resolve.searchModels(client, host, {
95
128
 
96
129
  Use `searchModels()` for UI pickers and debug routes. It returns ranked models
97
130
  with match scores and endpoint summaries, using the same fuzzy threshold and
98
- class ceiling logic as `selectModel()`. Both delegate catalogue ranking to the
99
- generated [`@dbx-tools/model-rs`](../model-rs) binding, so Node and the Rust
100
- model proxy use one fuzzy scorer, family-version order, variant preference, and
101
- class policy.
131
+ class ceiling logic as `selectModel()`. Classification, fuzzy scoring,
132
+ family-version order, and variant preference are implemented directly in this
133
+ package and require no native binding.
102
134
 
103
135
  ## Work With A Held Catalogue
104
136
 
@@ -194,9 +226,24 @@ a property of the model (see `isResponsesOnly()` and `responsesUpstreamUrl()`),
194
226
  so a hard-coded string in one package silently diverges when that routing
195
227
  changes. `isResponsesOnly()` covers Codex and GPT 5.4+ endpoints, which reject
196
228
  tool-bearing Chat Completions, while keeping GPT-OSS on its supported Chat path.
197
- The TypeScript helper delegates this policy to the generated
198
- [`@dbx-tools/model-rs`](../model-rs) binding, so the Rust proxy, Node packages,
199
- and Python callers share one version threshold.
229
+ The TypeScript helper owns this policy, so Node consumers and generated Python
230
+ bindings share one version threshold without loading a native library.
231
+
232
+ ## Read Published Model Metadata
233
+
234
+ ```ts
235
+ import { metadata } from "@dbx-tools/model";
236
+
237
+ const capabilities = metadata.modelCapabilitiesFor("databricks-gpt-5-4");
238
+ const limits = metadata.modelRateLimitsFor("gpt-5.4");
239
+ const status = metadata.modelStatusFor("system.ai.gemini-2-5-pro");
240
+ ```
241
+
242
+ The package ships committed snapshots generated from Databricks documentation
243
+ by `bun run model:metadata`. Runtime calls normalize endpoint, display,
244
+ foundation-model, and provider identities into memoized sets and maps; they do
245
+ not fetch documentation. `modelMetadataFor()` returns status, capabilities, and
246
+ published limits together for a string or `ServingEndpointSummary`.
200
247
 
201
248
  ## Use Static Fallbacks
202
249
 
@@ -214,14 +261,18 @@ policy decisions; fallbacks are a last resort.
214
261
 
215
262
  ## Modules
216
263
 
217
- - `resolve` - high-level `selectModel`, Rust-backed ranked search, and
264
+ - `resolve` - high-level `selectModel`, TypeScript-ranked search, and
218
265
  catalogue-held resolver functions.
219
266
  - `serving` - Databricks serving-endpoint listing, cache management, fuzzy
220
267
  search, and endpoint-id resolution.
221
268
  - `invoke` - serving-path constants, URL construction, and per-request auth
222
269
  headers for calling an endpoint over raw HTTP.
270
+ - `metadata` - build-generated retirement, capability, and rate-limit snapshots
271
+ with cached normalized lookups.
272
+ - `modelClient` - portable authentication-aware discovery, selection, routing,
273
+ profile, and metadata facade.
223
274
  - `classes` - model-class parsing, ordering, and class-ceiling helpers.
224
- - `policy` - Rust-backed family and reasoning-effort metadata projection.
275
+ - `policy` - family, serving-protocol, tool, and reasoning-effort policy.
225
276
  - `fallback` - static fallback model ids per class.
226
277
 
227
278
  The AppKit-Mastra integration uses this package through
package/index.ts CHANGED
@@ -3,17 +3,27 @@
3
3
  // Hand edits are overwritten on the next watch; this file is read-only.
4
4
 
5
5
  export const PACKAGE_IDENTIFIER = "@dbx-tools/model";
6
- export const PACKAGE_VERSION = "0.9.19";
6
+ export const PACKAGE_VERSION = "0.9.28";
7
7
  export * as classes from "./src/classes.ts";
8
+ export * as classify from "./src/classify.ts";
8
9
  export * as fallback from "./src/fallback.ts";
9
10
  export * as invoke from "./src/invoke.ts";
11
+ export * as metadata from "./src/metadata.ts";
10
12
  export * as modelCatalog from "./src/model-catalog.ts";
13
+ export * as modelClient from "./src/model-client.ts";
11
14
  export * as policy from "./src/policy.ts";
15
+ export * as python from "./src/python.ts";
12
16
  export * as resolve from "./src/resolve.ts";
13
17
  export { CHAT_CLASS_ORDER, MODEL_CLASS_ORDER } from "./src/classes.ts";
18
+ export type { EndpointCapabilities, FamilyClass } from "./src/classify.ts";
14
19
  export { FALLBACK_MODEL_IDS } from "./src/fallback.ts";
15
20
  export { INVOCATIONS_SUFFIX, RESPONSES_PATH, OPEN_RESPONSES_PATH, CHAT_COMPLETIONS_PATH } from "./src/invoke.ts";
16
21
  export type { AuthenticatingClientLike } from "./src/invoke.ts";
22
+ export { MODEL_METADATA_TTL_MS, MODEL_RATE_LIMITS_URL, OPENAI_RESPONSES_MODELS_URL, RETIRED_MODELS_URL, WEB_SEARCH_MODELS_URL } from "./src/metadata.ts";
23
+ export type { ModelCapabilities, ModelMetadata } from "./src/metadata.ts";
17
24
  export { DEFAULT_MODEL_CACHE_TTL_MS, DEFAULT_FUZZY_THRESHOLD } from "./src/model-catalog.ts";
18
25
  export type { WorkspaceClientLike, ListServingEndpointsOptions, ResolvedModel, ResolveModelOptions, ScoredEndpoint } from "./src/model-catalog.ts";
19
- export type { ResolveModelInput, ResolvedModelSelection, SelectModelInput, SearchModelsInput } from "./src/resolve.ts";
26
+ export { DEFAULT_MODEL_CLIENT_CACHE_TTL_MS } from "./src/model-client.ts";
27
+ export type { ModelClientOptions, ModelClientStatus, ModelProtocol, ModelRouteInput, ModelRoute, ModelClient } from "./src/model-client.ts";
28
+ export type { SelectModelInput, SearchModelsInput } from "./src/resolve.ts";
29
+ export * from "./exports.ts";
@@ -0,0 +1 @@
1
+ export { createModelClient } from "./src/model-client.ts";
package/lib/exports.js ADDED
@@ -0,0 +1,2 @@
1
+ export { createModelClient } from "./src/model-client.js";
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwb3J0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL2V4cG9ydHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgeyBjcmVhdGVNb2RlbENsaWVudCB9IGZyb20gXCIuL3NyYy9tb2RlbC1jbGllbnQudHNcIjtcbiJdfQ==
package/lib/index.d.ts CHANGED
@@ -1,15 +1,25 @@
1
1
  export declare const PACKAGE_IDENTIFIER = "@dbx-tools/model";
2
- export declare const PACKAGE_VERSION = "0.9.19";
2
+ export declare const PACKAGE_VERSION = "0.9.28";
3
3
  export * as classes from "./src/classes.ts";
4
+ export * as classify from "./src/classify.ts";
4
5
  export * as fallback from "./src/fallback.ts";
5
6
  export * as invoke from "./src/invoke.ts";
7
+ export * as metadata from "./src/metadata.ts";
6
8
  export * as modelCatalog from "./src/model-catalog.ts";
9
+ export * as modelClient from "./src/model-client.ts";
7
10
  export * as policy from "./src/policy.ts";
11
+ export * as python from "./src/python.ts";
8
12
  export * as resolve from "./src/resolve.ts";
9
13
  export { CHAT_CLASS_ORDER, MODEL_CLASS_ORDER } from "./src/classes.ts";
14
+ export type { EndpointCapabilities, FamilyClass } from "./src/classify.ts";
10
15
  export { FALLBACK_MODEL_IDS } from "./src/fallback.ts";
11
16
  export { INVOCATIONS_SUFFIX, RESPONSES_PATH, OPEN_RESPONSES_PATH, CHAT_COMPLETIONS_PATH } from "./src/invoke.ts";
12
17
  export type { AuthenticatingClientLike } from "./src/invoke.ts";
18
+ export { MODEL_METADATA_TTL_MS, MODEL_RATE_LIMITS_URL, OPENAI_RESPONSES_MODELS_URL, RETIRED_MODELS_URL, WEB_SEARCH_MODELS_URL } from "./src/metadata.ts";
19
+ export type { ModelCapabilities, ModelMetadata } from "./src/metadata.ts";
13
20
  export { DEFAULT_MODEL_CACHE_TTL_MS, DEFAULT_FUZZY_THRESHOLD } from "./src/model-catalog.ts";
14
21
  export type { WorkspaceClientLike, ListServingEndpointsOptions, ResolvedModel, ResolveModelOptions, ScoredEndpoint } from "./src/model-catalog.ts";
15
- export type { ResolveModelInput, ResolvedModelSelection, SelectModelInput, SearchModelsInput } from "./src/resolve.ts";
22
+ export { DEFAULT_MODEL_CLIENT_CACHE_TTL_MS } from "./src/model-client.ts";
23
+ export type { ModelClientOptions, ModelClientStatus, ModelProtocol, ModelRouteInput, ModelRoute, ModelClient } from "./src/model-client.ts";
24
+ export type { SelectModelInput, SearchModelsInput } from "./src/resolve.ts";
25
+ export * from "./exports.ts";
package/lib/index.js CHANGED
@@ -2,15 +2,22 @@
2
2
  // Regenerated from the exporting modules in ./src.
3
3
  // Hand edits are overwritten on the next watch; this file is read-only.
4
4
  export const PACKAGE_IDENTIFIER = "@dbx-tools/model";
5
- export const PACKAGE_VERSION = "0.9.19";
5
+ export const PACKAGE_VERSION = "0.9.28";
6
6
  export * as classes from "./src/classes.js";
7
+ export * as classify from "./src/classify.js";
7
8
  export * as fallback from "./src/fallback.js";
8
9
  export * as invoke from "./src/invoke.js";
10
+ export * as metadata from "./src/metadata.js";
9
11
  export * as modelCatalog from "./src/model-catalog.js";
12
+ export * as modelClient from "./src/model-client.js";
10
13
  export * as policy from "./src/policy.js";
14
+ export * as python from "./src/python.js";
11
15
  export * as resolve from "./src/resolve.js";
12
16
  export { CHAT_CLASS_ORDER, MODEL_CLASS_ORDER } from "./src/classes.js";
13
17
  export { FALLBACK_MODEL_IDS } from "./src/fallback.js";
14
18
  export { INVOCATIONS_SUFFIX, RESPONSES_PATH, OPEN_RESPONSES_PATH, CHAT_COMPLETIONS_PATH } from "./src/invoke.js";
19
+ export { MODEL_METADATA_TTL_MS, MODEL_RATE_LIMITS_URL, OPENAI_RESPONSES_MODELS_URL, RETIRED_MODELS_URL, WEB_SEARCH_MODELS_URL } from "./src/metadata.js";
15
20
  export { DEFAULT_MODEL_CACHE_TTL_MS, DEFAULT_FUZZY_THRESHOLD } from "./src/model-catalog.js";
16
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQztBQUNyRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDO0FBQ3hDLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxLQUFLLFFBQVEsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEtBQUssTUFBTSxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxZQUFZLE1BQU0sd0JBQXdCLENBQUM7QUFDdkQsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxjQUFjLEVBQUUsbUJBQW1CLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUVqSCxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCBjb25zdCBQQUNLQUdFX0lERU5USUZJRVIgPSBcIkBkYngtdG9vbHMvbW9kZWxcIjtcbmV4cG9ydCBjb25zdCBQQUNLQUdFX1ZFUlNJT04gPSBcIjAuOS4xOVwiO1xuZXhwb3J0ICogYXMgY2xhc3NlcyBmcm9tIFwiLi9zcmMvY2xhc3Nlcy50c1wiO1xuZXhwb3J0ICogYXMgZmFsbGJhY2sgZnJvbSBcIi4vc3JjL2ZhbGxiYWNrLnRzXCI7XG5leHBvcnQgKiBhcyBpbnZva2UgZnJvbSBcIi4vc3JjL2ludm9rZS50c1wiO1xuZXhwb3J0ICogYXMgbW9kZWxDYXRhbG9nIGZyb20gXCIuL3NyYy9tb2RlbC1jYXRhbG9nLnRzXCI7XG5leHBvcnQgKiBhcyBwb2xpY3kgZnJvbSBcIi4vc3JjL3BvbGljeS50c1wiO1xuZXhwb3J0ICogYXMgcmVzb2x2ZSBmcm9tIFwiLi9zcmMvcmVzb2x2ZS50c1wiO1xuZXhwb3J0IHsgQ0hBVF9DTEFTU19PUkRFUiwgTU9ERUxfQ0xBU1NfT1JERVIgfSBmcm9tIFwiLi9zcmMvY2xhc3Nlcy50c1wiO1xuZXhwb3J0IHsgRkFMTEJBQ0tfTU9ERUxfSURTIH0gZnJvbSBcIi4vc3JjL2ZhbGxiYWNrLnRzXCI7XG5leHBvcnQgeyBJTlZPQ0FUSU9OU19TVUZGSVgsIFJFU1BPTlNFU19QQVRILCBPUEVOX1JFU1BPTlNFU19QQVRILCBDSEFUX0NPTVBMRVRJT05TX1BBVEggfSBmcm9tIFwiLi9zcmMvaW52b2tlLnRzXCI7XG5leHBvcnQgdHlwZSB7IEF1dGhlbnRpY2F0aW5nQ2xpZW50TGlrZSB9IGZyb20gXCIuL3NyYy9pbnZva2UudHNcIjtcbmV4cG9ydCB7IERFRkFVTFRfTU9ERUxfQ0FDSEVfVFRMX01TLCBERUZBVUxUX0ZVWlpZX1RIUkVTSE9MRCB9IGZyb20gXCIuL3NyYy9tb2RlbC1jYXRhbG9nLnRzXCI7XG5leHBvcnQgdHlwZSB7IFdvcmtzcGFjZUNsaWVudExpa2UsIExpc3RTZXJ2aW5nRW5kcG9pbnRzT3B0aW9ucywgUmVzb2x2ZWRNb2RlbCwgUmVzb2x2ZU1vZGVsT3B0aW9ucywgU2NvcmVkRW5kcG9pbnQgfSBmcm9tIFwiLi9zcmMvbW9kZWwtY2F0YWxvZy50c1wiO1xuZXhwb3J0IHR5cGUgeyBSZXNvbHZlTW9kZWxJbnB1dCwgUmVzb2x2ZWRNb2RlbFNlbGVjdGlvbiwgU2VsZWN0TW9kZWxJbnB1dCwgU2VhcmNoTW9kZWxzSW5wdXQgfSBmcm9tIFwiLi9zcmMvcmVzb2x2ZS50c1wiO1xuIl19
21
+ export { DEFAULT_MODEL_CLIENT_CACHE_TTL_MS } from "./src/model-client.js";
22
+ export * from "./exports.js";
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQztBQUNyRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDO0FBQ3hDLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxLQUFLLFFBQVEsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEtBQUssUUFBUSxNQUFNLG1CQUFtQixDQUFDO0FBQzlDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLFFBQVEsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEtBQUssWUFBWSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZELE9BQU8sS0FBSyxXQUFXLE1BQU0sdUJBQXVCLENBQUM7QUFDckQsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEtBQUssTUFBTSxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGlCQUFpQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFdkUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDdkQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLGNBQWMsRUFBRSxtQkFBbUIsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRWpILE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxxQkFBcUIsRUFBRSwyQkFBMkIsRUFBRSxrQkFBa0IsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRXpKLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRTdGLE9BQU8sRUFBRSxpQ0FBaUMsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRzFFLGNBQWMsY0FBYyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gR0VORVJBVEVEIGJ5IHByb2plbiB3YXRjaCAtIERPIE5PVCBFRElULlxuLy8gUmVnZW5lcmF0ZWQgZnJvbSB0aGUgZXhwb3J0aW5nIG1vZHVsZXMgaW4gLi9zcmMuXG4vLyBIYW5kIGVkaXRzIGFyZSBvdmVyd3JpdHRlbiBvbiB0aGUgbmV4dCB3YXRjaDsgdGhpcyBmaWxlIGlzIHJlYWQtb25seS5cblxuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfSURFTlRJRklFUiA9IFwiQGRieC10b29scy9tb2RlbFwiO1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfVkVSU0lPTiA9IFwiMC45LjI4XCI7XG5leHBvcnQgKiBhcyBjbGFzc2VzIGZyb20gXCIuL3NyYy9jbGFzc2VzLnRzXCI7XG5leHBvcnQgKiBhcyBjbGFzc2lmeSBmcm9tIFwiLi9zcmMvY2xhc3NpZnkudHNcIjtcbmV4cG9ydCAqIGFzIGZhbGxiYWNrIGZyb20gXCIuL3NyYy9mYWxsYmFjay50c1wiO1xuZXhwb3J0ICogYXMgaW52b2tlIGZyb20gXCIuL3NyYy9pbnZva2UudHNcIjtcbmV4cG9ydCAqIGFzIG1ldGFkYXRhIGZyb20gXCIuL3NyYy9tZXRhZGF0YS50c1wiO1xuZXhwb3J0ICogYXMgbW9kZWxDYXRhbG9nIGZyb20gXCIuL3NyYy9tb2RlbC1jYXRhbG9nLnRzXCI7XG5leHBvcnQgKiBhcyBtb2RlbENsaWVudCBmcm9tIFwiLi9zcmMvbW9kZWwtY2xpZW50LnRzXCI7XG5leHBvcnQgKiBhcyBwb2xpY3kgZnJvbSBcIi4vc3JjL3BvbGljeS50c1wiO1xuZXhwb3J0ICogYXMgcHl0aG9uIGZyb20gXCIuL3NyYy9weXRob24udHNcIjtcbmV4cG9ydCAqIGFzIHJlc29sdmUgZnJvbSBcIi4vc3JjL3Jlc29sdmUudHNcIjtcbmV4cG9ydCB7IENIQVRfQ0xBU1NfT1JERVIsIE1PREVMX0NMQVNTX09SREVSIH0gZnJvbSBcIi4vc3JjL2NsYXNzZXMudHNcIjtcbmV4cG9ydCB0eXBlIHsgRW5kcG9pbnRDYXBhYmlsaXRpZXMsIEZhbWlseUNsYXNzIH0gZnJvbSBcIi4vc3JjL2NsYXNzaWZ5LnRzXCI7XG5leHBvcnQgeyBGQUxMQkFDS19NT0RFTF9JRFMgfSBmcm9tIFwiLi9zcmMvZmFsbGJhY2sudHNcIjtcbmV4cG9ydCB7IElOVk9DQVRJT05TX1NVRkZJWCwgUkVTUE9OU0VTX1BBVEgsIE9QRU5fUkVTUE9OU0VTX1BBVEgsIENIQVRfQ09NUExFVElPTlNfUEFUSCB9IGZyb20gXCIuL3NyYy9pbnZva2UudHNcIjtcbmV4cG9ydCB0eXBlIHsgQXV0aGVudGljYXRpbmdDbGllbnRMaWtlIH0gZnJvbSBcIi4vc3JjL2ludm9rZS50c1wiO1xuZXhwb3J0IHsgTU9ERUxfTUVUQURBVEFfVFRMX01TLCBNT0RFTF9SQVRFX0xJTUlUU19VUkwsIE9QRU5BSV9SRVNQT05TRVNfTU9ERUxTX1VSTCwgUkVUSVJFRF9NT0RFTFNfVVJMLCBXRUJfU0VBUkNIX01PREVMU19VUkwgfSBmcm9tIFwiLi9zcmMvbWV0YWRhdGEudHNcIjtcbmV4cG9ydCB0eXBlIHsgTW9kZWxDYXBhYmlsaXRpZXMsIE1vZGVsTWV0YWRhdGEgfSBmcm9tIFwiLi9zcmMvbWV0YWRhdGEudHNcIjtcbmV4cG9ydCB7IERFRkFVTFRfTU9ERUxfQ0FDSEVfVFRMX01TLCBERUZBVUxUX0ZVWlpZX1RIUkVTSE9MRCB9IGZyb20gXCIuL3NyYy9tb2RlbC1jYXRhbG9nLnRzXCI7XG5leHBvcnQgdHlwZSB7IFdvcmtzcGFjZUNsaWVudExpa2UsIExpc3RTZXJ2aW5nRW5kcG9pbnRzT3B0aW9ucywgUmVzb2x2ZWRNb2RlbCwgUmVzb2x2ZU1vZGVsT3B0aW9ucywgU2NvcmVkRW5kcG9pbnQgfSBmcm9tIFwiLi9zcmMvbW9kZWwtY2F0YWxvZy50c1wiO1xuZXhwb3J0IHsgREVGQVVMVF9NT0RFTF9DTElFTlRfQ0FDSEVfVFRMX01TIH0gZnJvbSBcIi4vc3JjL21vZGVsLWNsaWVudC50c1wiO1xuZXhwb3J0IHR5cGUgeyBNb2RlbENsaWVudE9wdGlvbnMsIE1vZGVsQ2xpZW50U3RhdHVzLCBNb2RlbFByb3RvY29sLCBNb2RlbFJvdXRlSW5wdXQsIE1vZGVsUm91dGUsIE1vZGVsQ2xpZW50IH0gZnJvbSBcIi4vc3JjL21vZGVsLWNsaWVudC50c1wiO1xuZXhwb3J0IHR5cGUgeyBTZWxlY3RNb2RlbElucHV0LCBTZWFyY2hNb2RlbHNJbnB1dCB9IGZyb20gXCIuL3NyYy9yZXNvbHZlLnRzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9leHBvcnRzLnRzXCI7XG4iXX0=
@@ -0,0 +1,42 @@
1
+ /** One day, matching the refresh cadence of Databricks model documentation. */
2
+ export declare const MODEL_METADATA_TTL_MS: number;
3
+ /** Databricks documentation URL for retired foundation models. */
4
+ export declare const RETIRED_MODELS_URL = "https://docs.databricks.com/aws/en/machine-learning/retired-models-policy";
5
+ /** Databricks documentation URL for OpenAI Responses model support. */
6
+ export declare const OPENAI_RESPONSES_MODELS_URL = "https://docs.databricks.com/aws/en/machine-learning/model-serving/query-openai-responses";
7
+ /** Databricks documentation URL for native web-search model support. */
8
+ export declare const WEB_SEARCH_MODELS_URL = "https://docs.databricks.com/aws/en/machine-learning/model-serving/web-search";
9
+ /** Databricks documentation URL for Foundation Model API limits. */
10
+ export declare const MODEL_RATE_LIMITS_URL = "https://docs.databricks.com/aws/en/machine-learning/foundation-model-apis/limits";
11
+ /** Build-generated retired-model snapshot. */
12
+ export interface RetiredModelsSnapshot {
13
+ readonly generatedAt: number;
14
+ readonly models: readonly string[];
15
+ }
16
+ /** Normalized model identities grouped by documented capability. */
17
+ export interface ModelCapabilityCatalogue {
18
+ readonly responses: readonly string[];
19
+ readonly imageInput: readonly string[];
20
+ readonly applyPatch: readonly string[];
21
+ readonly webSearch: readonly string[];
22
+ }
23
+ /** Build-generated model-capability snapshot. */
24
+ export interface ModelCapabilitiesSnapshot {
25
+ readonly generatedAt: number;
26
+ readonly capabilities: ModelCapabilityCatalogue;
27
+ }
28
+ /** Published pay-per-token limits for one model. */
29
+ export interface ModelRateLimits {
30
+ readonly inputTokensPerMinute: number | null;
31
+ readonly outputTokensPerMinute: number | null;
32
+ readonly queriesPerHour: number | null;
33
+ }
34
+ /** Model limits keyed by normalized Databricks model identity. */
35
+ export interface ModelRateLimitCatalogue {
36
+ readonly models: Readonly<Record<string, ModelRateLimits>>;
37
+ }
38
+ /** Build-generated model-rate-limit snapshot. */
39
+ export interface ModelRateLimitsSnapshot {
40
+ readonly generatedAt: number;
41
+ readonly catalogue: ModelRateLimitCatalogue;
42
+ }
@@ -0,0 +1,11 @@
1
+ /** One day, matching the refresh cadence of Databricks model documentation. */
2
+ export const MODEL_METADATA_TTL_MS = 24 * 60 * 60 * 1000;
3
+ /** Databricks documentation URL for retired foundation models. */
4
+ export const RETIRED_MODELS_URL = "https://docs.databricks.com/aws/en/machine-learning/retired-models-policy";
5
+ /** Databricks documentation URL for OpenAI Responses model support. */
6
+ export const OPENAI_RESPONSES_MODELS_URL = "https://docs.databricks.com/aws/en/machine-learning/model-serving/query-openai-responses";
7
+ /** Databricks documentation URL for native web-search model support. */
8
+ export const WEB_SEARCH_MODELS_URL = "https://docs.databricks.com/aws/en/machine-learning/model-serving/web-search";
9
+ /** Databricks documentation URL for Foundation Model API limits. */
10
+ export const MODEL_RATE_LIMITS_URL = "https://docs.databricks.com/aws/en/machine-learning/foundation-model-apis/limits";
11
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX21ldGFkYXRhLWNvbnRyYWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL19tZXRhZGF0YS1jb250cmFjdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrRUFBK0U7QUFDL0UsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBRXpELGtFQUFrRTtBQUNsRSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FDN0IsMkVBQTJFLENBQUM7QUFFOUUsdUVBQXVFO0FBQ3ZFLE1BQU0sQ0FBQyxNQUFNLDJCQUEyQixHQUN0QywwRkFBMEYsQ0FBQztBQUU3Rix3RUFBd0U7QUFDeEUsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQ2hDLDhFQUE4RSxDQUFDO0FBRWpGLG9FQUFvRTtBQUNwRSxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FDaEMsa0ZBQWtGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiogT25lIGRheSwgbWF0Y2hpbmcgdGhlIHJlZnJlc2ggY2FkZW5jZSBvZiBEYXRhYnJpY2tzIG1vZGVsIGRvY3VtZW50YXRpb24uICovXG5leHBvcnQgY29uc3QgTU9ERUxfTUVUQURBVEFfVFRMX01TID0gMjQgKiA2MCAqIDYwICogMTAwMDtcblxuLyoqIERhdGFicmlja3MgZG9jdW1lbnRhdGlvbiBVUkwgZm9yIHJldGlyZWQgZm91bmRhdGlvbiBtb2RlbHMuICovXG5leHBvcnQgY29uc3QgUkVUSVJFRF9NT0RFTFNfVVJMID1cbiAgXCJodHRwczovL2RvY3MuZGF0YWJyaWNrcy5jb20vYXdzL2VuL21hY2hpbmUtbGVhcm5pbmcvcmV0aXJlZC1tb2RlbHMtcG9saWN5XCI7XG5cbi8qKiBEYXRhYnJpY2tzIGRvY3VtZW50YXRpb24gVVJMIGZvciBPcGVuQUkgUmVzcG9uc2VzIG1vZGVsIHN1cHBvcnQuICovXG5leHBvcnQgY29uc3QgT1BFTkFJX1JFU1BPTlNFU19NT0RFTFNfVVJMID1cbiAgXCJodHRwczovL2RvY3MuZGF0YWJyaWNrcy5jb20vYXdzL2VuL21hY2hpbmUtbGVhcm5pbmcvbW9kZWwtc2VydmluZy9xdWVyeS1vcGVuYWktcmVzcG9uc2VzXCI7XG5cbi8qKiBEYXRhYnJpY2tzIGRvY3VtZW50YXRpb24gVVJMIGZvciBuYXRpdmUgd2ViLXNlYXJjaCBtb2RlbCBzdXBwb3J0LiAqL1xuZXhwb3J0IGNvbnN0IFdFQl9TRUFSQ0hfTU9ERUxTX1VSTCA9XG4gIFwiaHR0cHM6Ly9kb2NzLmRhdGFicmlja3MuY29tL2F3cy9lbi9tYWNoaW5lLWxlYXJuaW5nL21vZGVsLXNlcnZpbmcvd2ViLXNlYXJjaFwiO1xuXG4vKiogRGF0YWJyaWNrcyBkb2N1bWVudGF0aW9uIFVSTCBmb3IgRm91bmRhdGlvbiBNb2RlbCBBUEkgbGltaXRzLiAqL1xuZXhwb3J0IGNvbnN0IE1PREVMX1JBVEVfTElNSVRTX1VSTCA9XG4gIFwiaHR0cHM6Ly9kb2NzLmRhdGFicmlja3MuY29tL2F3cy9lbi9tYWNoaW5lLWxlYXJuaW5nL2ZvdW5kYXRpb24tbW9kZWwtYXBpcy9saW1pdHNcIjtcblxuLyoqIEJ1aWxkLWdlbmVyYXRlZCByZXRpcmVkLW1vZGVsIHNuYXBzaG90LiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXRpcmVkTW9kZWxzU25hcHNob3Qge1xuICByZWFkb25seSBnZW5lcmF0ZWRBdDogbnVtYmVyO1xuICByZWFkb25seSBtb2RlbHM6IHJlYWRvbmx5IHN0cmluZ1tdO1xufVxuXG4vKiogTm9ybWFsaXplZCBtb2RlbCBpZGVudGl0aWVzIGdyb3VwZWQgYnkgZG9jdW1lbnRlZCBjYXBhYmlsaXR5LiAqL1xuZXhwb3J0IGludGVyZmFjZSBNb2RlbENhcGFiaWxpdHlDYXRhbG9ndWUge1xuICByZWFkb25seSByZXNwb25zZXM6IHJlYWRvbmx5IHN0cmluZ1tdO1xuICByZWFkb25seSBpbWFnZUlucHV0OiByZWFkb25seSBzdHJpbmdbXTtcbiAgcmVhZG9ubHkgYXBwbHlQYXRjaDogcmVhZG9ubHkgc3RyaW5nW107XG4gIHJlYWRvbmx5IHdlYlNlYXJjaDogcmVhZG9ubHkgc3RyaW5nW107XG59XG5cbi8qKiBCdWlsZC1nZW5lcmF0ZWQgbW9kZWwtY2FwYWJpbGl0eSBzbmFwc2hvdC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTW9kZWxDYXBhYmlsaXRpZXNTbmFwc2hvdCB7XG4gIHJlYWRvbmx5IGdlbmVyYXRlZEF0OiBudW1iZXI7XG4gIHJlYWRvbmx5IGNhcGFiaWxpdGllczogTW9kZWxDYXBhYmlsaXR5Q2F0YWxvZ3VlO1xufVxuXG4vKiogUHVibGlzaGVkIHBheS1wZXItdG9rZW4gbGltaXRzIGZvciBvbmUgbW9kZWwuICovXG5leHBvcnQgaW50ZXJmYWNlIE1vZGVsUmF0ZUxpbWl0cyB7XG4gIHJlYWRvbmx5IGlucHV0VG9rZW5zUGVyTWludXRlOiBudW1iZXIgfCBudWxsO1xuICByZWFkb25seSBvdXRwdXRUb2tlbnNQZXJNaW51dGU6IG51bWJlciB8IG51bGw7XG4gIHJlYWRvbmx5IHF1ZXJpZXNQZXJIb3VyOiBudW1iZXIgfCBudWxsO1xufVxuXG4vKiogTW9kZWwgbGltaXRzIGtleWVkIGJ5IG5vcm1hbGl6ZWQgRGF0YWJyaWNrcyBtb2RlbCBpZGVudGl0eS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTW9kZWxSYXRlTGltaXRDYXRhbG9ndWUge1xuICByZWFkb25seSBtb2RlbHM6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIE1vZGVsUmF0ZUxpbWl0cz4+O1xufVxuXG4vKiogQnVpbGQtZ2VuZXJhdGVkIG1vZGVsLXJhdGUtbGltaXQgc25hcHNob3QuICovXG5leHBvcnQgaW50ZXJmYWNlIE1vZGVsUmF0ZUxpbWl0c1NuYXBzaG90IHtcbiAgcmVhZG9ubHkgZ2VuZXJhdGVkQXQ6IG51bWJlcjtcbiAgcmVhZG9ubHkgY2F0YWxvZ3VlOiBNb2RlbFJhdGVMaW1pdENhdGFsb2d1ZTtcbn1cbiJdfQ==
@@ -0,0 +1,7 @@
1
+ import type { ModelCapabilitiesSnapshot, ModelRateLimitsSnapshot, RetiredModelsSnapshot } from "./_metadata-contract.ts";
2
+ /** Parse retired model names from Databricks retirement-policy HTML. */
3
+ export declare function parseRetiredModels(html: string, generatedAt: number): RetiredModelsSnapshot;
4
+ /** Parse Responses and web-search documentation into model capability sets. */
5
+ export declare function parseModelCapabilities(responsesHtml: string, webSearchHtml: string, generatedAt: number): ModelCapabilitiesSnapshot;
6
+ /** Parse pay-per-token limits from Databricks Foundation Model API HTML. */
7
+ export declare function parseModelRateLimits(html: string, generatedAt: number): ModelRateLimitsSnapshot;
@@ -0,0 +1,182 @@
1
+ import { load } from "cheerio";
2
+ import { modelSearchQuery } from "./policy.js";
3
+ /** Parse retired model names from Databricks retirement-policy HTML. */
4
+ export function parseRetiredModels(html, generatedAt) {
5
+ const $ = load(html);
6
+ const models = new Set();
7
+ $("table").each((_, table) => {
8
+ const rows = $(table).find("tr");
9
+ const header = collapseText($(rows.get(0)).find("th, td").first()).toLowerCase();
10
+ if (header !== "open model" && header !== "partner model")
11
+ return;
12
+ rows.slice(1).each((__, row) => {
13
+ for (const name of collapseText($(row).find("th, td").first()).split("/")) {
14
+ const trimmed = name.trim();
15
+ if (trimmed)
16
+ models.add(trimmed);
17
+ }
18
+ });
19
+ });
20
+ if (models.size === 0)
21
+ throw new Error("Databricks retirement tables contained no model names");
22
+ return {
23
+ generatedAt,
24
+ models: [...models].sort((left, right) => left.localeCompare(right, "en", { sensitivity: "base" })),
25
+ };
26
+ }
27
+ /** Parse Responses and web-search documentation into model capability sets. */
28
+ export function parseModelCapabilities(responsesHtml, webSearchHtml, generatedAt) {
29
+ const responsesDocument = load(responsesHtml);
30
+ const responses = modelsAfterHeading(responsesDocument, "databricks-hosted-foundation-models");
31
+ if (responses.length === 0) {
32
+ throw new Error("Databricks documentation contained no OpenAI Responses models");
33
+ }
34
+ const inputTypes = sectionElements(responsesDocument, "supported-input-types")
35
+ .map((element) => collapseText(element))
36
+ .join(" ")
37
+ .toLowerCase();
38
+ const inputTypeWords = new Set(inputTypes.split(/[^a-z0-9]+/).filter(Boolean));
39
+ const imageInput = inputTypeWords.has("text") && inputTypeWords.has("image") ? responses : [];
40
+ const applyPatch = codeValuesAfterHeading(responsesDocument, "limitations").includes("apply_patch")
41
+ ? responses
42
+ : [];
43
+ const webSearch = nativeWebSearchModels(load(webSearchHtml), responses);
44
+ if (webSearch.length === 0) {
45
+ throw new Error("Databricks documentation contained no native web-search models");
46
+ }
47
+ return {
48
+ generatedAt,
49
+ capabilities: { responses, imageInput, applyPatch, webSearch },
50
+ };
51
+ }
52
+ /** Parse pay-per-token limits from Databricks Foundation Model API HTML. */
53
+ export function parseModelRateLimits(html, generatedAt) {
54
+ const $ = load(html);
55
+ const models = {};
56
+ $("table").each((_, table) => {
57
+ const rows = $(table).find("tr");
58
+ const headers = $(rows.get(0))
59
+ .find("th, td")
60
+ .toArray()
61
+ .map((cell) => collapseText($(cell)).toLowerCase());
62
+ const modelIndex = headers.findIndex((value) => value.includes("model"));
63
+ const inputIndex = headers.findIndex((value) => value.includes("itpm"));
64
+ const outputIndex = headers.findIndex((value) => value.includes("otpm"));
65
+ const queryIndex = headers.findIndex((value) => value.includes("qph"));
66
+ if (modelIndex < 0 || inputIndex < 0 || outputIndex < 0)
67
+ return;
68
+ rows.slice(1).each((__, row) => {
69
+ const cells = $(row)
70
+ .find("th, td")
71
+ .toArray()
72
+ .map((cell) => collapseText($(cell)));
73
+ const key = modelKey(cells[modelIndex]);
74
+ if (!key)
75
+ return;
76
+ models[key] = {
77
+ inputTokensPerMinute: number(cells[inputIndex]),
78
+ outputTokensPerMinute: number(cells[outputIndex]),
79
+ queriesPerHour: queryIndex < 0 ? null : number(cells[queryIndex]),
80
+ };
81
+ });
82
+ });
83
+ if (Object.keys(models).length === 0) {
84
+ throw new Error("Databricks model-limit documentation contained no models");
85
+ }
86
+ return { generatedAt, catalogue: { models: sortRecord(models) } };
87
+ }
88
+ function modelsAfterHeading($, headingId) {
89
+ return [
90
+ ...new Set(codeValuesAfterHeading($, headingId).flatMap((value) => modelKey(value) ?? [])),
91
+ ].sort();
92
+ }
93
+ function nativeWebSearchModels($, responses) {
94
+ const families = new Set();
95
+ const models = new Set();
96
+ let nativeSection = false;
97
+ for (const element of sectionElements($, "supported-models")) {
98
+ if (headingLevel(nodeTagName(element.get(0))) !== undefined) {
99
+ nativeSection = !collapseText(element).toLowerCase().includes("via mcp");
100
+ continue;
101
+ }
102
+ if (!nativeSection)
103
+ continue;
104
+ const values = nodeTagName(element.get(0)) === "code" ? [collapseText(element)] : [];
105
+ element.find("code").each((_, code) => {
106
+ values.push(collapseText($(code)));
107
+ });
108
+ for (const value of values) {
109
+ const model = modelKey(value);
110
+ if (!model)
111
+ continue;
112
+ models.add(model);
113
+ families.add(model.split("-", 1)[0]);
114
+ }
115
+ }
116
+ for (const model of responses) {
117
+ if (families.has(model.split("-", 1)[0]))
118
+ models.add(model);
119
+ }
120
+ return [...models].sort();
121
+ }
122
+ function codeValuesAfterHeading($, headingId) {
123
+ const values = [];
124
+ for (const element of sectionElements($, headingId)) {
125
+ if (nodeTagName(element.get(0)) === "code")
126
+ values.push(collapseText(element));
127
+ element.find("code").each((_, code) => {
128
+ values.push(collapseText($(code)));
129
+ });
130
+ }
131
+ return values;
132
+ }
133
+ function sectionElements($, headingId) {
134
+ const heading = $(`#${headingId}`).first();
135
+ if (heading.length === 0)
136
+ throw new Error(`Databricks capability page is missing section ${headingId}`);
137
+ const level = headingLevel(nodeTagName(heading.get(0)));
138
+ if (level === undefined)
139
+ throw new Error(`Databricks capability section ${headingId} is not a heading`);
140
+ const elements = [];
141
+ let sibling = heading.next();
142
+ while (sibling.length > 0) {
143
+ const siblingLevel = headingLevel(nodeTagName(sibling.get(0)));
144
+ if (siblingLevel !== undefined && siblingLevel <= level)
145
+ break;
146
+ elements.push(sibling);
147
+ sibling = sibling.next();
148
+ }
149
+ return elements;
150
+ }
151
+ function headingLevel(name) {
152
+ const match = /^h([1-6])$/.exec(name ?? "");
153
+ return match ? Number(match[1]) : undefined;
154
+ }
155
+ function collapseText(element) {
156
+ return element.text().split(/\s+/).filter(Boolean).join(" ");
157
+ }
158
+ function nodeTagName(node) {
159
+ if (!node || typeof node !== "object" || !("tagName" in node))
160
+ return undefined;
161
+ return typeof node.tagName === "string" ? node.tagName : undefined;
162
+ }
163
+ function modelKey(value) {
164
+ if (!value)
165
+ return undefined;
166
+ let name = value.trim().replace(/\*+$/, "").trim();
167
+ for (const suffix of ["(Public Preview)", "(Beta)", "(Preview)"]) {
168
+ if (name.endsWith(suffix))
169
+ name = name.slice(0, -suffix.length).trim();
170
+ }
171
+ return modelSearchQuery(name)?.replaceAll(" ", "-");
172
+ }
173
+ function number(value) {
174
+ if (!value)
175
+ return null;
176
+ const parsed = Number(value.replaceAll(",", "").trim());
177
+ return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : null;
178
+ }
179
+ function sortRecord(record) {
180
+ return Object.fromEntries(Object.entries(record).sort(([left], [right]) => left.localeCompare(right)));
181
+ }
182
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX21ldGFkYXRhLWdlbmVyYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9fbWV0YWRhdGEtZ2VuZXJhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQW1CLE1BQU0sU0FBUyxDQUFDO0FBUWhELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUkvQyx3RUFBd0U7QUFDeEUsTUFBTSxVQUFVLGtCQUFrQixDQUFDLElBQVksRUFBRSxXQUFtQjtJQUNsRSxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDckIsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUNqQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFO1FBQzNCLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDakMsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDakYsSUFBSSxNQUFNLEtBQUssWUFBWSxJQUFJLE1BQU0sS0FBSyxlQUFlO1lBQUUsT0FBTztRQUNsRSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRTtZQUM3QixLQUFLLE1BQU0sSUFBSSxJQUFJLFlBQVksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcs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LE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3hELE9BQU8sTUFBTSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxNQUFNLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztBQUNyRSxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUksTUFBbUM7SUFDeEQsT0FBTyxNQUFNLENBQUMsV0FBVyxDQUN2QixNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUM1RSxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGxvYWQsIHR5cGUgQ2hlZXJpb0FQSSB9IGZyb20gXCJjaGVlcmlvXCI7XG5cbmltcG9ydCB0eXBlIHtcbiAgTW9kZWxDYXBhYmlsaXRpZXNTbmFwc2hvdCxcbiAgTW9kZWxSYXRlTGltaXRDYXRhbG9ndWUsXG4gIE1vZGVsUmF0ZUxpbWl0c1NuYXBzaG90LFxuICBSZXRpcmVkTW9kZWxzU25hcHNob3QsXG59IGZyb20gXCIuL19tZXRhZGF0YS1jb250cmFjdC50c1wiO1xuaW1wb3J0IHsgbW9kZWxTZWFyY2hRdWVyeSB9IGZyb20gXCIuL3BvbGljeS50c1wiO1xuXG50eXBlIFNlbGVjdGlvbiA9IFJldHVyblR5cGU8Q2hlZXJpb0FQST47XG5cbi8qKiBQYXJzZSByZXRpcmVkIG1vZGVsIG5hbWVzIGZyb20gRGF0YWJyaWNrcyByZXRpcmVtZW50LXBvbGljeSBIVE1MLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlUmV0aXJlZE1vZGVscyhodG1sOiBzdHJpbmcsIGdlbmVyYXRlZEF0OiBudW1iZXIpOiBSZXRpcmVkTW9kZWxzU25hcHNob3Qge1xuICBjb25zdCAkID0gbG9hZChodG1sKTtcbiAgY29uc3QgbW9kZWxzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICQoXCJ0YWJsZVwiKS5lYWNoKChfLCB0YWJsZSkgPT4ge1xuICAgIGNvbnN0IHJvd3MgPSAkKHRhYmxlKS5maW5kKFwidHJcIik7XG4gICAgY29uc3QgaGVhZGVyID0gY29sbGFwc2VUZXh0KCQocm93cy5nZXQoMCkpLmZpbmQoXCJ0aCwgdGRcIikuZmlyc3QoKSkudG9Mb3dlckNhc2UoKTtcbiAgICBpZiAoaGVhZGVyICE9PSBcIm9wZW4gbW9kZWxcIiAmJiBoZWFkZXIgIT09IFwicGFydG5lciBtb2RlbFwiKSByZXR1cm47XG4gICAgcm93cy5zbGljZSgxKS5lYWNoKChfXywgcm93KSA9PiB7XG4gICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgY29sbGFwc2VUZXh0KCQocm93KS5maW5kKFwidGgsIHRkXCIpLmZpcnN0KCkpLnNwbGl0KFwiL1wiKSkge1xuICAgICAgICBjb25zdCB0cmltbWVkID0gbmFtZS50cmltKCk7XG4gICAgICAgIGlmICh0cmltbWVkKSBtb2RlbHMuYWRkKHRyaW1tZWQpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcbiAgaWYgKG1vZGVscy5zaXplID09PSAwKSB0aHJvdyBuZXcgRXJyb3IoXCJEYXRhYnJpY2tzIHJldGlyZW1lbnQgdGFibGVzIGNvbnRhaW5lZCBubyBtb2RlbCBuYW1lc1wiKTtcbiAgcmV0dXJuIHtcbiAgICBnZW5lcmF0ZWRBdCxcbiAgICBtb2RlbHM6IFsuLi5tb2RlbHNdLnNvcnQoKGxlZnQsIHJpZ2h0KSA9PlxuICAgICAgbGVmdC5sb2NhbGVDb21wYXJlKHJpZ2h0LCBcImVuXCIsIHsgc2Vuc2l0aXZpdHk6IFwiYmFzZVwiIH0pLFxuICAgICksXG4gIH07XG59XG5cbi8qKiBQYXJzZSBSZXNwb25zZXMgYW5kIHdlYi1zZWFyY2ggZG9jdW1lbnRhdGlvbiBpbnRvIG1vZGVsIGNhcGFiaWxpdHkgc2V0cy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZU1vZGVsQ2FwYWJpbGl0aWVzKFxuICByZXNwb25zZXNIdG1sOiBzdHJpbmcsXG4gIHdlYlNlYXJjaEh0bWw6IHN0cmluZyxcbiAgZ2VuZXJhdGVkQXQ6IG51bWJlcixcbik6IE1vZGVsQ2FwYWJpbGl0aWVzU25hcHNob3Qge1xuICBjb25zdCByZXNwb25zZXNEb2N1bWVudCA9IGxvYWQocmVzcG9uc2VzSHRtbCk7XG4gIGNvbnN0IHJlc3BvbnNlcyA9IG1vZGVsc0FmdGVySGVhZGluZyhyZXNwb25zZXNEb2N1bWVudCwgXCJkYXRhYnJpY2tzLWhvc3RlZC1mb3VuZGF0aW9uLW1vZGVsc1wiKTtcbiAgaWYgKHJlc3BvbnNlcy5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJEYXRhYnJpY2tzIGRvY3VtZW50YXRpb24gY29udGFpbmVkIG5vIE9wZW5BSSBSZXNwb25zZXMgbW9kZWxzXCIpO1xuICB9XG4gIGNvbnN0IGlucHV0VHlwZXMgPSBzZWN0aW9uRWxlbWVudHMocmVzcG9uc2VzRG9jdW1lbnQsIFwic3VwcG9ydGVkLWlucHV0LXR5cGVzXCIpXG4gICAgLm1hcCgoZWxlbWVudCkgPT4gY29sbGFwc2VUZXh0KGVsZW1lbnQpKVxuICAgIC5qb2luKFwiIFwiKVxuICAgIC50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCBpbnB1dFR5cGVXb3JkcyA9IG5ldyBTZXQoaW5wdXRUeXBlcy5zcGxpdCgvW15hLXowLTldKy8pLmZpbHRlcihCb29sZWFuKSk7XG4gIGNvbnN0IGltYWdlSW5wdXQgPSBpbnB1dFR5cGVXb3Jkcy5oYXMoXCJ0ZXh0XCIpICYmIGlucHV0VHlwZVdvcmRzLmhhcyhcImltYWdlXCIpID8gcmVzcG9uc2VzIDogW107XG4gIGNvbnN0IGFwcGx5UGF0Y2ggPSBjb2RlVmFsdWVzQWZ0ZXJIZWFkaW5nKHJlc3BvbnNlc0RvY3VtZW50LCBcImxpbWl0YXRpb25zXCIpLmluY2x1ZGVzKFxuICAgIFwiYXBwbHlfcGF0Y2hcIixcbiAgKVxuICAgID8gcmVzcG9uc2VzXG4gICAgOiBbXTtcbiAgY29uc3Qgd2ViU2VhcmNoID0gbmF0aXZlV2ViU2VhcmNoTW9kZWxzKGxvYWQod2ViU2VhcmNoSHRtbCksIHJlc3BvbnNlcyk7XG4gIGlmICh3ZWJTZWFyY2gubGVuZ3RoID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiRGF0YWJyaWNrcyBkb2N1bWVudGF0aW9uIGNvbnRhaW5lZCBubyBuYXRpdmUgd2ViLXNlYXJjaCBtb2RlbHNcIik7XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBnZW5lcmF0ZWRBdCxcbiAgICBjYXBhYmlsaXRpZXM6IHsgcmVzcG9uc2VzLCBpbWFnZUlucHV0LCBhcHBseVBhdGNoLCB3ZWJTZWFyY2ggfSxcbiAgfTtcbn1cblxuLyoqIFBhcnNlIHBheS1wZXItdG9rZW4gbGltaXRzIGZyb20gRGF0YWJyaWNrcyBGb3VuZGF0aW9uIE1vZGVsIEFQSSBIVE1MLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlTW9kZWxSYXRlTGltaXRzKGh0bWw6IHN0cmluZywgZ2VuZXJhdGVkQXQ6IG51bWJlcik6IE1vZGVsUmF0ZUxpbWl0c1NuYXBzaG90IHtcbiAgY29uc3QgJCA9IGxvYWQoaHRtbCk7XG4gIGNvbnN0IG1vZGVsczogUmVjb3JkPHN0cmluZywgTW9kZWxSYXRlTGltaXRDYXRhbG9ndWVbXCJtb2RlbHNcIl1bc3RyaW5nXT4gPSB7fTtcbiAgJChcInRhYmxlXCIpLmVhY2goKF8sIHRhYmxlKSA9PiB7XG4gICAgY29uc3Qgcm93cyA9ICQodGFibGUpLmZpbmQoXCJ0clwiKTtcbiAgICBjb25zdCBoZWFkZXJzID0gJChyb3dzLmdldCgwKSlcbiAgICAgIC5maW5kKFwidGgsIHRkXCIpXG4gICAgICAudG9BcnJheSgpXG4gICAgICAubWFwKChjZWxsKSA9PiBjb2xsYXBzZVRleHQoJChjZWxsKSkudG9Mb3dlckNhc2UoKSk7XG4gICAgY29uc3QgbW9kZWxJbmRleCA9IGhlYWRlcnMuZmluZEluZGV4KCh2YWx1ZSkgPT4gdmFsdWUuaW5jbHVkZXMoXCJtb2RlbFwiKSk7XG4gICAgY29uc3QgaW5wdXRJbmRleCA9IGhlYWRlcnMuZmluZEluZGV4KCh2YWx1ZSkgPT4gdmFsdWUuaW5jbHVkZXMoXCJpdHBtXCIpKTtcbiAgICBjb25zdCBvdXRwdXRJbmRleCA9IGhlYWRlcnMuZmluZEluZGV4KCh2YWx1ZSkgPT4gdmFsdWUuaW5jbHVkZXMoXCJvdHBtXCIpKTtcbiAgICBjb25zdCBxdWVyeUluZGV4ID0gaGVhZGVycy5maW5kSW5kZXgoKHZhbHVlKSA9PiB2YWx1ZS5pbmNsdWRlcyhcInFwaFwiKSk7XG4gICAgaWYgKG1vZGVsSW5kZXggPCAwIHx8IGlucHV0SW5kZXggPCAwIHx8IG91dHB1dEluZGV4IDwgMCkgcmV0dXJuO1xuICAgIHJvd3Muc2xpY2UoMSkuZWFjaCgoX18sIHJvdykgPT4ge1xuICAgICAgY29uc3QgY2VsbHMgPSAkKHJvdylcbiAgICAgICAgLmZpbmQoXCJ0aCwgdGRcIilcbiAgICAgICAgLnRvQXJyYXkoKVxuICAgICAgICAubWFwKChjZWxsKSA9PiBjb2xsYXBzZVRleHQoJChjZWxsKSkpO1xuICAgICAgY29uc3Qga2V5ID0gbW9kZWxLZXkoY2VsbHNbbW9kZWxJbmRleF0pO1xuICAgICAgaWYgKCFrZXkpIHJldHVybjtcbiAgICAgIG1vZGVsc1trZXldID0ge1xuICAgICAgICBpbnB1dFRva2Vuc1Blck1pbnV0ZTogbnVtYmVyKGNlbGxzW2lucHV0SW5kZXhdKSxcbiAgICAgICAgb3V0cHV0VG9rZW5zUGVyTWludXRlOiBudW1iZXIoY2VsbHNbb3V0cHV0SW5kZXhdKSxcbiAgICAgICAgcXVlcmllc1BlckhvdXI6IHF1ZXJ5SW5kZXggPCAwID8gbnVsbCA6IG51bWJlcihjZWxsc1txdWVyeUluZGV4XSksXG4gICAgICB9O1xuICAgIH0pO1xuICB9KTtcbiAgaWYgKE9iamVjdC5rZXlzKG1vZGVscykubGVuZ3RoID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiRGF0YWJyaWNrcyBtb2RlbC1saW1pdCBkb2N1bWVudGF0aW9uIGNvbnRhaW5lZCBubyBtb2RlbHNcIik7XG4gIH1cbiAgcmV0dXJuIHsgZ2VuZXJhdGVkQXQsIGNhdGFsb2d1ZTogeyBtb2RlbHM6IHNvcnRSZWNvcmQobW9kZWxzKSB9IH07XG59XG5cbmZ1bmN0aW9uIG1vZGVsc0FmdGVySGVhZGluZygkOiBDaGVlcmlvQVBJLCBoZWFkaW5nSWQ6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIFtcbiAgICAuLi5uZXcgU2V0KGNvZGVWYWx1ZXNBZnRlckhlYWRpbmcoJCwgaGVhZGluZ0lkKS5mbGF0TWFwKCh2YWx1ZSkgPT4gbW9kZWxLZXkodmFsdWUpID8/IFtdKSksXG4gIF0uc29ydCgpO1xufVxuXG5mdW5jdGlvbiBuYXRpdmVXZWJTZWFyY2hNb2RlbHMoJDogQ2hlZXJpb0FQSSwgcmVzcG9uc2VzOiByZWFkb25seSBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcbiAgY29uc3QgZmFtaWxpZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgY29uc3QgbW9kZWxzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIGxldCBuYXRpdmVTZWN0aW9uID0gZmFsc2U7XG4gIGZvciAoY29uc3QgZWxlbWVudCBvZiBzZWN0aW9uRWxlbWVudHMoJCwgXCJzdXBwb3J0ZWQtbW9kZWxzXCIpKSB7XG4gICAgaWYgKGhlYWRpbmdMZXZlbChub2RlVGFnTmFtZShlbGVtZW50LmdldCgwKSkpICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIG5hdGl2ZVNlY3Rpb24gPSAhY29sbGFwc2VUZXh0KGVsZW1lbnQpLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoXCJ2aWEgbWNwXCIpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmICghbmF0aXZlU2VjdGlvbikgY29udGludWU7XG4gICAgY29uc3QgdmFsdWVzID0gbm9kZVRhZ05hbWUoZWxlbWVudC5nZXQoMCkpID09PSBcImNvZGVcIiA/IFtjb2xsYXBzZVRleHQoZWxlbWVudCldIDogW107XG4gICAgZWxlbWVudC5maW5kKFwiY29kZVwiKS5lYWNoKChfLCBjb2RlKSA9PiB7XG4gICAgICB2YWx1ZXMucHVzaChjb2xsYXBzZVRleHQoJChjb2RlKSkpO1xuICAgIH0pO1xuICAgIGZvciAoY29uc3QgdmFsdWUgb2YgdmFsdWVzKSB7XG4gICAgICBjb25zdCBtb2RlbCA9IG1vZGVsS2V5KHZhbHVlKTtcbiAgICAgIGlmICghbW9kZWwpIGNvbnRpbnVlO1xuICAgICAgbW9kZWxzLmFkZChtb2RlbCk7XG4gICAgICBmYW1pbGllcy5hZGQobW9kZWwuc3BsaXQoXCItXCIsIDEpWzBdKTtcbiAgICB9XG4gIH1cbiAgZm9yIChjb25zdCBtb2RlbCBvZiByZXNwb25zZXMpIHtcbiAgICBpZiAoZmFtaWxpZXMuaGFzKG1vZGVsLnNwbGl0KFwiLVwiLCAxKVswXSkpIG1vZGVscy5hZGQobW9kZWwpO1xuICB9XG4gIHJldHVybiBbLi4ubW9kZWxzXS5zb3J0KCk7XG59XG5cbmZ1bmN0aW9uIGNvZGVWYWx1ZXNBZnRlckhlYWRpbmcoJDogQ2hlZXJpb0FQSSwgaGVhZGluZ0lkOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHZhbHVlczogc3RyaW5nW10gPSBbXTtcbiAgZm9yIChjb25zdCBlbGVtZW50IG9mIHNlY3Rpb25FbGVtZW50cygkLCBoZWFkaW5nSWQpKSB7XG4gICAgaWYgKG5vZGVUYWdOYW1lKGVsZW1lbnQuZ2V0KDApKSA9PT0gXCJjb2RlXCIpIHZhbHVlcy5wdXNoKGNvbGxhcHNlVGV4dChlbGVtZW50KSk7XG4gICAgZWxlbWVudC5maW5kKFwiY29kZVwiKS5lYWNoKChfLCBjb2RlKSA9PiB7XG4gICAgICB2YWx1ZXMucHVzaChjb2xsYXBzZVRleHQoJChjb2RlKSkpO1xuICAgIH0pO1xuICB9XG4gIHJldHVybiB2YWx1ZXM7XG59XG5cbmZ1bmN0aW9uIHNlY3Rpb25FbGVtZW50cygkOiBDaGVlcmlvQVBJLCBoZWFkaW5nSWQ6IHN0cmluZyk6IFNlbGVjdGlvbltdIHtcbiAgY29uc3QgaGVhZGluZyA9ICQoYCMke2hlYWRpbmdJZH1gKS5maXJzdCgpO1xuICBpZiAoaGVhZGluZy5sZW5ndGggPT09IDApXG4gICAgdGhyb3cgbmV3IEVycm9yKGBEYXRhYnJpY2tzIGNhcGFiaWxpdHkgcGFnZSBpcyBtaXNzaW5nIHNlY3Rpb24gJHtoZWFkaW5nSWR9YCk7XG4gIGNvbnN0IGxldmVsID0gaGVhZGluZ0xldmVsKG5vZGVUYWdOYW1lKGhlYWRpbmcuZ2V0KDApKSk7XG4gIGlmIChsZXZlbCA9PT0gdW5kZWZpbmVkKVxuICAgIHRocm93IG5ldyBFcnJvcihgRGF0YWJyaWNrcyBjYXBhYmlsaXR5IHNlY3Rpb24gJHtoZWFkaW5nSWR9IGlzIG5vdCBhIGhlYWRpbmdgKTtcbiAgY29uc3QgZWxlbWVudHM6IFNlbGVjdGlvbltdID0gW107XG4gIGxldCBzaWJsaW5nID0gaGVhZGluZy5uZXh0KCk7XG4gIHdoaWxlIChzaWJsaW5nLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCBzaWJsaW5nTGV2ZWwgPSBoZWFkaW5nTGV2ZWwobm9kZVRhZ05hbWUoc2libGluZy5nZXQoMCkpKTtcbiAgICBpZiAoc2libGluZ0xldmVsICE9PSB1bmRlZmluZWQgJiYgc2libGluZ0xldmVsIDw9IGxldmVsKSBicmVhaztcbiAgICBlbGVtZW50cy5wdXNoKHNpYmxpbmcpO1xuICAgIHNpYmxpbmcgPSBzaWJsaW5nLm5leHQoKTtcbiAgfVxuICByZXR1cm4gZWxlbWVudHM7XG59XG5cbmZ1bmN0aW9uIGhlYWRpbmdMZXZlbChuYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICBjb25zdCBtYXRjaCA9IC9eaChbMS02XSkkLy5leGVjKG5hbWUgPz8gXCJcIik7XG4gIHJldHVybiBtYXRjaCA/IE51bWJlcihtYXRjaFsxXSkgOiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIGNvbGxhcHNlVGV4dChlbGVtZW50OiBTZWxlY3Rpb24pOiBzdHJpbmcge1xuICByZXR1cm4gZWxlbWVudC50ZXh0KCkuc3BsaXQoL1xccysvKS5maWx0ZXIoQm9vbGVhbikuam9pbihcIiBcIik7XG59XG5cbmZ1bmN0aW9uIG5vZGVUYWdOYW1lKG5vZGU6IHVua25vd24pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAoIW5vZGUgfHwgdHlwZW9mIG5vZGUgIT09IFwib2JqZWN0XCIgfHwgIShcInRhZ05hbWVcIiBpbiBub2RlKSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgcmV0dXJuIHR5cGVvZiBub2RlLnRhZ05hbWUgPT09IFwic3RyaW5nXCIgPyBub2RlLnRhZ05hbWUgOiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIG1vZGVsS2V5KHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAoIXZhbHVlKSByZXR1cm4gdW5kZWZpbmVkO1xuICBsZXQgbmFtZSA9IHZhbHVlLnRyaW0oKS5yZXBsYWNlKC9cXCorJC8sIFwiXCIpLnRyaW0oKTtcbiAgZm9yIChjb25zdCBzdWZmaXggb2YgW1wiKFB1YmxpYyBQcmV2aWV3KVwiLCBcIihCZXRhKVwiLCBcIihQcmV2aWV3KVwiXSkge1xuICAgIGlmIChuYW1lLmVuZHNXaXRoKHN1ZmZpeCkpIG5hbWUgPSBuYW1lLnNsaWNlKDAsIC1zdWZmaXgubGVuZ3RoKS50cmltKCk7XG4gIH1cbiAgcmV0dXJuIG1vZGVsU2VhcmNoUXVlcnkobmFtZSk/LnJlcGxhY2VBbGwoXCIgXCIsIFwiLVwiKTtcbn1cblxuZnVuY3Rpb24gbnVtYmVyKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBudW1iZXIgfCBudWxsIHtcbiAgaWYgKCF2YWx1ZSkgcmV0dXJuIG51bGw7XG4gIGNvbnN0IHBhcnNlZCA9IE51bWJlcih2YWx1ZS5yZXBsYWNlQWxsKFwiLFwiLCBcIlwiKS50cmltKCkpO1xuICByZXR1cm4gTnVtYmVyLmlzU2FmZUludGVnZXIocGFyc2VkKSAmJiBwYXJzZWQgPj0gMCA/IHBhcnNlZCA6IG51bGw7XG59XG5cbmZ1bmN0aW9uIHNvcnRSZWNvcmQ8VD4ocmVjb3JkOiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBUPj4pOiBSZWNvcmQ8c3RyaW5nLCBUPiB7XG4gIHJldHVybiBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgT2JqZWN0LmVudHJpZXMocmVjb3JkKS5zb3J0KChbbGVmdF0sIFtyaWdodF0pID0+IGxlZnQubG9jYWxlQ29tcGFyZShyaWdodCkpLFxuICApO1xufVxuIl19
@@ -0,0 +1,20 @@
1
+ import { type ModelClass as ModelClassType, type ModelQuery, type RankedModel, type ServingEndpointSummary } from "@dbx-tools/shared-model/contracts";
2
+ type ModelClass = ModelClassType;
3
+ declare const ModelClass: {
4
+ readonly ChatThinking: "chat-thinking";
5
+ readonly ChatBalanced: "chat-balanced";
6
+ readonly ChatFast: "chat-fast";
7
+ readonly Embedding: "embedding";
8
+ };
9
+ interface NativeRankingOptions {
10
+ readonly includeDeprecated?: boolean;
11
+ readonly modelClass?: ModelClass;
12
+ readonly task?: string;
13
+ }
14
+ /** Rank endpoint records through the TypeScript-owned model policy. */
15
+ export declare function rankEndpoints(endpoints: readonly ServingEndpointSummary[], query?: ModelQuery, options?: NativeRankingOptions): RankedModel[];
16
+ /** Classify chat and embedding endpoints through the TypeScript-owned policy. */
17
+ export declare function classifyEndpointClasses(endpoints: readonly ServingEndpointSummary[]): ReadonlyMap<string, ModelClass>;
18
+ /** Normalize serialized SDK endpoint records without native bindings. */
19
+ export declare function normalizeEndpoints(endpoints: readonly unknown[]): ServingEndpointSummary[];
20
+ export {};