Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
ea97ff1
fix(sync): write per-tier audio pricing
Sep 9, 2026
3cfdf62
feat(aihubmix): sync pricing and deprecation from the public catalog
Sep 9, 2026
ba56a47
feat(aihubmix): sync the full model catalog from the endpoint
Sep 10, 2026
63a9b6b
fix(aihubmix): resolve relay casing and read backfilled limits as absent
Sep 10, 2026
4b72fb3
feat(aihubmix): resolve vanity and upstream-compute routing prefixes
Sep 10, 2026
c97eddd
chore(aihubmix): pick up corrected output limits from the endpoint
Sep 10, 2026
5682db7
feat(aihubmix): peel dated release tags and map two more labs
Sep 10, 2026
2f9320b
docs(sync): describe how AIHubMix relay IDs resolve to lab models
Sep 10, 2026
71596f7
Revert "feat(aihubmix): peel dated release tags and map two more labs"
Sep 10, 2026
bb68f93
docs(sync): say why AIHubMix date tags stay on the relay ID
Sep 10, 2026
e0ca438
feat(aihubmix): resolve relays from the catalog's own vendor and vari…
Sep 11, 2026
4bf1dcc
chore(aihubmix): leave the catalog files to the sync automation
Sep 11, 2026
fe493be
feat(aihubmix): re-author the toggle wire path on every sync
Sep 11, 2026
7556964
fix(aihubmix): keep prices the endpoint does not quote
Sep 11, 2026
15d1e91
fix(aihubmix): fold the toggle into effort=none per AGENTS.md
Sep 11, 2026
3849205
fix(aihubmix): stop a sync from wiping what only the file records
Sep 11, 2026
f62d6a6
fix(aihubmix): let the endpoint widen modalities, never narrow them
Sep 11, 2026
7f76e79
fix(aihubmix): stop a create from overriding lab metadata off
Sep 11, 2026
1ca2066
fix(aihubmix): answer review round 5 — limits, standalone, skip tracking
Sep 14, 2026
8d02b14
aihubmix: resolve limit restatements against the lab window, keep hum…
Sep 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions packages/core/src/sync/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { z } from "zod";
import { AuthoredModel, AuthoredModelShape, ModelMetadata } from "../schema.js";
import { openMissingModelIssues } from "./missing-issues.js";
import { MissingReasoningOptionsError } from "./missing-reasoning-options.js";
import { aihubmix } from "./providers/aihubmix.js";
import { ambient } from "./providers/ambient.js";
import { anthropic } from "./providers/anthropic.js";
import { baseten } from "./providers/baseten.js";
Expand Down Expand Up @@ -80,7 +81,12 @@ export interface SyncProvider<SourceModel> {
* deduped GitHub issue per missing model ID.
*/
skipCreates?: boolean;
/** Report remote-only models skipped by skipCreates as GitHub issues. */
/**
* Open one deduped GitHub issue per model the provider skipped. Implied by
* skipCreates, and settable on its own by a provider that creates models but
* still skips the ones it cannot write — without it those skips produce a
* notice nobody acts on.
*/
trackMissingModels?: boolean;
deleteMissing?: boolean;
preserveSymlinks?: boolean;
Expand All @@ -103,6 +109,12 @@ export interface SyncProvider<SourceModel> {
context: {
existing(id: string): ExistingModel | undefined;
authored(id: string): ExistingModel | undefined;
/**
* The leading comment block already on the file, so a provider that owns
* its header (authoritativeHeaders) can refresh the part it generates
* without discarding notes a human wrote around it.
*/
header?(id: string): string | undefined;
},
): {
id: string;
Expand Down Expand Up @@ -130,6 +142,7 @@ export interface SyncResult {
}

export const providers: {
aihubmix: SyncProvider<any>;
ambient: SyncProvider<any>;
anthropic: SyncProvider<any>;
baseten: SyncProvider<any>;
Expand Down Expand Up @@ -165,6 +178,7 @@ export const providers: {
wandb: SyncProvider<any>;
xai: SyncProvider<any>;
} = {
aihubmix,
ambient,
anthropic,
baseten,
Expand Down Expand Up @@ -203,6 +217,7 @@ export const providers: {

export const groups = {
aggregators: [
"aihubmix",
"crossmodel",
"edenai",
"empiriolabs",
Expand Down Expand Up @@ -264,6 +279,9 @@ export async function syncProvider<SourceModel>(
authored(id) {
return existing.get(`${id}.toml`)?.authored;
},
header(id) {
return existing.get(`${id}.toml`)?.header || undefined;
},
});
} catch (error) {
if (!(error instanceof MissingReasoningOptionsError)) throw error;
Expand Down Expand Up @@ -485,7 +503,7 @@ export async function syncProvider<SourceModel>(
];

const issueModels = [
...(provider.skipCreates === true ? skippedRemote : []),
...(provider.skipCreates === true || provider.trackMissingModels === true ? skippedRemote : []),
...missingReasoning.keys(),
];
if (
Expand Down Expand Up @@ -1055,6 +1073,12 @@ export function formatToml(model: z.infer<typeof SyncedAuthoredModel>) {
if (tier.reasoning !== undefined) lines.push(`reasoning = ${formatNumber(tier.reasoning)}`);
if (tier.cache_read !== undefined) lines.push(`cache_read = ${formatNumber(tier.cache_read)}`);
if (tier.cache_write !== undefined) lines.push(`cache_write = ${formatNumber(tier.cache_write)}`);
if (tier.input_audio !== undefined) {
lines.push(`input_audio = ${formatNumber(tier.input_audio)}`);
}
if (tier.output_audio !== undefined) {
lines.push(`output_audio = ${formatNumber(tier.output_audio)}`);
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/sync/missing-issues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function issueBody(provider: MissingModelIssueTarget, modelId: string, reason?:
`| Expected path | \`${provider.modelsDir}/${modelId}.toml\` |`,
"",
reason === undefined
? "This provider uses `skipCreates` because the remote source is not enough to auto-author a full TOML."
? "The sync did not author this model: the remote source is not enough to write a full TOML, or the model belongs on `base_model` and its `models/` metadata is missing."
: `Sync diagnostic: ${reason}`,
"Add the model manually (prefer `base_model` when matching `models/` metadata exists).",
...(reason === undefined ? [] : [
Expand Down
Loading
Loading