| 327 | } |
| 328 | |
| 329 | function detectChanges( |
| 330 | existing: ExistingModel | null, |
| 331 | merged: MergedModel, |
| 332 | ): Changes[] { |
| 333 | if (!existing) return []; |
| 334 | |
| 335 | const changes: Changes[] = []; |
| 336 | |
| 337 | const compare = (field: string, oldVal: unknown, newVal: unknown) => { |
| 338 | const oldStr = JSON.stringify(oldVal); |
| 339 | const newStr = JSON.stringify(newVal); |
| 340 | if (oldStr !== newStr) { |
| 341 | changes.push({ |
| 342 | field, |
| 343 | oldValue: formatValue(oldVal), |
| 344 | newValue: formatValue(newVal), |
| 345 | }); |
| 346 | } |
| 347 | }; |
| 348 | |
| 349 | const formatValue = (val: unknown): string => { |
| 350 | if (typeof val === "number") return formatNumber(val); |
| 351 | if (Array.isArray(val)) return `[${val.join(", ")}]`; |
| 352 | if (val === undefined) return "(none)"; |
| 353 | return String(val); |
| 354 | }; |
| 355 | |
| 356 | compare("name", existing.name, merged.name); |
| 357 | compare("family", existing.family, merged.family); |
| 358 | compare("attachment", existing.attachment, merged.attachment); |
| 359 | compare("reasoning", existing.reasoning, merged.reasoning); |
| 360 | compare("tool_call", existing.tool_call, merged.tool_call); |
| 361 | compare( |
| 362 | "structured_output", |
| 363 | existing.structured_output, |
| 364 | merged.structured_output, |
| 365 | ); |
| 366 | compare("open_weights", existing.open_weights, merged.open_weights); |
| 367 | compare("release_date", existing.release_date, merged.release_date); |
| 368 | compare("cost.input", existing.cost?.input, merged.cost?.input); |
| 369 | compare("cost.output", existing.cost?.output, merged.cost?.output); |
| 370 | compare("limit.context", existing.limit?.context, merged.limit.context); |
| 371 | compare("limit.output", existing.limit?.output, merged.limit.output); |
| 372 | compare("modalities.input", existing.modalities?.input, merged.modalities.input); |
| 373 | |
| 374 | return changes; |
| 375 | } |
| 376 | |
| 377 | async function main() { |
| 378 | const args = process.argv.slice(2); |