()
| 177 | ]; |
| 178 | |
| 179 | async function main() { |
| 180 | console.log( |
| 181 | `${dryRun ? "[DRY RUN] " : ""}${newOnly ? "[NEW ONLY] " : ""}Fetching Databricks foundation-models...`, |
| 182 | ); |
| 183 | |
| 184 | const url = `https://${workspace}/api/2.0/serving-endpoints:foundation-models`; |
| 185 | const res = await fetch(url, { |
| 186 | headers: { Authorization: `Bearer ${token}` }, |
| 187 | }); |
| 188 | if (!res.ok) { |
| 189 | console.error(`Failed to fetch API: ${res.status} ${res.statusText}`); |
| 190 | console.error(await res.text().catch(() => "")); |
| 191 | process.exit(1); |
| 192 | } |
| 193 | |
| 194 | const json = await res.json(); |
| 195 | const parsed = FoundationModelsResponse.safeParse(json); |
| 196 | if (!parsed.success) { |
| 197 | console.error("Invalid API response:", parsed.error.errors); |
| 198 | process.exit(1); |
| 199 | } |
| 200 | |
| 201 | const endpoints = parsed.data.endpoints.filter( |
| 202 | (e) => |
| 203 | !IGNORE_PREFIXES.some((p) => e.name.startsWith(p)) && |
| 204 | e.config?.served_entities?.some( |
| 205 | (se) => |
| 206 | se.foundation_model?.ai_gateway_v2_supported === true && |
| 207 | se.foundation_model?.api_types?.includes("mlflow/v1/chat/completions"), |
| 208 | ), |
| 209 | ); |
| 210 | |
| 211 | const existingFiles = new Set<string>(); |
| 212 | try { |
| 213 | for await (const f of new Bun.Glob("*.toml").scan({ cwd: MODELS_DIR })) { |
| 214 | existingFiles.add(f); |
| 215 | } |
| 216 | } catch { |
| 217 | // directory may not exist yet |
| 218 | } |
| 219 | |
| 220 | console.log( |
| 221 | `Found ${endpoints.length} models in API, ${existingFiles.size} existing files\n`, |
| 222 | ); |
| 223 | |
| 224 | const apiModelIds = new Set<string>(); |
| 225 | let created = 0; |
| 226 | let updated = 0; |
| 227 | let unchanged = 0; |
| 228 | |
| 229 | for (const ep of endpoints) { |
| 230 | const filename = `${ep.name}.toml`; |
| 231 | apiModelIds.add(filename); |
| 232 | const filePath = path.join(MODELS_DIR, filename); |
| 233 | |
| 234 | const resolution = await resolveCanonical(ep.name); |
| 235 | const newContent = formatToml(resolution, ep.name); |
| 236 | const tag = resolution?.type === "base_model" ? `base_model ${resolution.from}` : resolution?.type ?? "stub"; |
no test coverage detected