Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .github/workflows/sync-models.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ jobs:
run: bun models:sync ${{ matrix.provider }}
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
ANYAPI_API_KEY: ${{ secrets.ANYAPI_API_KEY }}
BASETEN_API_KEY: ${{ secrets.BASETEN_API_KEY }}
DEEPINFRA_API_KEY: ${{ secrets.DEEPINFRA_API_KEY }}
DIGITALOCEAN_API_TOKEN: ${{ secrets.DIGITALOCEAN_API_TOKEN }}
Expand Down
5 changes: 4 additions & 1 deletion 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 { ambient } from "./providers/ambient.js";
import { anthropic } from "./providers/anthropic.js";
import { anyapi } from "./providers/anyapi.js";
import { baseten } from "./providers/baseten.js";
import { chutes } from "./providers/chutes.js";
import { cloudflareWorkersAi } from "./providers/cloudflare-workers-ai.js";
Expand Down Expand Up @@ -94,6 +95,7 @@ export interface SyncResult {

export const providers: {
ambient: SyncProvider<any>;
anyapi: SyncProvider<any>;
anthropic: SyncProvider<any>;
baseten: SyncProvider<any>;
chutes: SyncProvider<any>;
Expand All @@ -116,6 +118,7 @@ export const providers: {
xai: SyncProvider<any>;
} = {
ambient,
anyapi,
anthropic,
baseten,
chutes,
Expand All @@ -139,7 +142,7 @@ export const providers: {
};

export const groups = {
aggregators: ["crossmodel", "empiriolabs", "huggingface", "kilo", "llmgateway", "openrouter", "vercel"],
aggregators: ["anyapi", "crossmodel", "empiriolabs", "huggingface", "kilo", "llmgateway", "openrouter", "vercel"],
cloudflare: ["cloudflare-workers-ai"],
direct: ["ambient", "anthropic", "baseten", "chutes", "deepinfra", "digitalocean", "google", "openai", "ovhcloud", "pioneer", "venice", "wandb", "xai"],
} as const;
Expand Down
67 changes: 67 additions & 0 deletions packages/core/src/sync/providers/anyapi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { z } from "zod";

import { AuthoredModel } from "../../schema.js";
import type { ExistingModel, SyncProvider, SyncedModel } from "../index.js";

const API_ENDPOINT = "https://api.anyapi.ai/v1/models";

const AnyAPIModel = z.object({
id: z.string(),
});

const AnyAPIResponse = z.object({
data: z.array(AnyAPIModel.passthrough()),
}).passthrough();

export type AnyAPIModel = z.infer<typeof AnyAPIModel>;

function preserveAuthoredModel(id: string, authored: ExistingModel): SyncedModel {
if (authored.base_model !== undefined) return authored as SyncedModel;

const parsed = AuthoredModel.safeParse({ id, ...authored });
if (!parsed.success) {
parsed.error.cause = { provider: "anyapi", model: id };
throw parsed.error;
}
const { id: _id, ...model } = parsed.data;
return model;
}

export const anyapi = {
id: "anyapi",
name: "AnyAPI",
modelsDir: "providers/anyapi/models",
skipCreates: true,
deleteMissing: false,
sourceID(model) {
return model.id;
},
skippedNotice(ids) {
if (ids.length === 0) return [];
return [
`${ids.length} AnyAPI models returned by the API were not created because the /v1/models endpoint is not authoritative beyond model IDs. Existing models are still updated while new models require hand-authored metadata.`,
`Skipped remote IDs: ${ids.map((id) => `\`${id}\``).join(", ")}`,
];
},
async fetchModels() {
const key = process.env.ANYAPI_API_KEY;
if (!key) {
throw new Error("ANYAPI_API_KEY environment variable is required");
}
const response = await fetch(API_ENDPOINT, {
headers: { Authorization: "Bearer " + key },
});
if (!response.ok) {
throw new Error("AnyAPI request failed: " + response.status + " " + response.statusText);
}
return response.json();
},
parseModels(raw) {
return AnyAPIResponse.parse(raw).data;
},
translateModel(model, context) {
const authored = context.authored(model.id);
if (authored === undefined) return undefined;
return { id: model.id, model: preserveAuthoredModel(model.id, authored) };
},
} satisfies SyncProvider<AnyAPIModel>;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
base_model = "anthropic/claude-haiku-4-5"
# AnyAPI accepts thinking.type="enabled" with budget_tokens, but documents no
# model-specific 1,024..63,999 bounds or off mapping; these remain upstream facts.
# https://docs.anyapi.ai/guides/parameters
# https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking
base_model = "anthropic/claude-haiku-4-5"
reasoning_options = [{ type = "toggle" }, { type = "effort", values = ["low", "medium", "high"] }, { type = "budget_tokens", min = 1_024, max = 63_999 }]
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
base_model = "anthropic/claude-opus-4-6"
# AnyAPI accepts thinking.type="enabled" with budget_tokens, but documents no
# model-specific 1,024..127,999 bounds or off mapping; these remain upstream facts.
# https://docs.anyapi.ai/guides/parameters
# https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking
base_model = "anthropic/claude-opus-4-6"
reasoning_options = [{ type = "toggle" }, { type = "effort", values = ["low", "medium", "high"] }, { type = "budget_tokens", min = 1_024, max = 127_999 }]

[experimental.modes.fast]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
base_model = "anthropic/claude-opus-4-7"
# AnyAPI documents generic effort and thinking fields, but no Opus 4.7-specific
# mapping or budget bounds; accepted schema does not prove effective control.
# https://docs.anyapi.ai/guides/parameters
base_model = "anthropic/claude-opus-4-7"
reasoning_options = [{ type = "toggle" }, { type = "effort", values = ["low", "medium", "high"] }]

[experimental.modes.fast]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
base_model = "anthropic/claude-sonnet-4-5"
# AnyAPI accepts thinking.type="enabled" with budget_tokens, but documents no
# model-specific 1,024..63,999 bounds or off mapping; these remain upstream facts.
# https://docs.anyapi.ai/guides/parameters
# https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking
base_model = "anthropic/claude-sonnet-4-5"
reasoning_options = [{ type = "toggle" }, { type = "effort", values = ["low", "medium", "high"] }, { type = "budget_tokens", min = 1_024, max = 63_999 }]
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
base_model = "anthropic/claude-sonnet-4-6"
# AnyAPI accepts thinking.type="enabled" with budget_tokens, but documents no
# model-specific 1,024..63,999 bounds or off mapping; these remain upstream facts.
# https://docs.anyapi.ai/guides/parameters
# https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking
base_model = "anthropic/claude-sonnet-4-6"
reasoning_options = [{ type = "toggle" }, { type = "effort", values = ["low", "medium", "high"] }, { type = "budget_tokens", min = 1_024, max = 63_999 }]
2 changes: 2 additions & 0 deletions providers/anyapi/models/google/gemini-3-pro-image.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
base_model = "google/gemini-3-pro-image"
reasoning_options = []
2 changes: 0 additions & 2 deletions providers/anyapi/models/google/gemini-3-pro-preview.toml

This file was deleted.

2 changes: 1 addition & 1 deletion providers/anyapi/models/openai/gpt-5-mini.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
base_model = "openai/gpt-5-mini"
# AnyAPI accepts low/medium/high generically but documents no model-specific
# effectiveness; unsupported parameters may be silently ignored.
# https://docs.anyapi.ai/guides/parameters
base_model = "openai/gpt-5-mini"
reasoning_options = [{ type = "effort", values = ["low", "medium", "high"] }]
2 changes: 1 addition & 1 deletion providers/anyapi/models/openai/gpt-5.1.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
base_model = "openai/gpt-5.1"
# AnyAPI accepts low/medium/high generically but documents no model-specific
# effectiveness; unsupported parameters may be silently ignored.
# https://docs.anyapi.ai/guides/parameters
base_model = "openai/gpt-5.1"
reasoning_options = [{ type = "effort", values = ["low", "medium", "high"] }]
2 changes: 1 addition & 1 deletion providers/anyapi/models/openai/gpt-5.2.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
base_model = "openai/gpt-5.2"
# AnyAPI accepts low/medium/high generically but documents no model-specific
# effectiveness; unsupported parameters may be silently ignored.
# https://docs.anyapi.ai/guides/parameters
base_model = "openai/gpt-5.2"
reasoning_options = [{ type = "effort", values = ["low", "medium", "high"] }]
2 changes: 1 addition & 1 deletion providers/anyapi/models/openai/gpt-5.4.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
base_model = "openai/gpt-5.4"
# AnyAPI accepts low/medium/high generically but documents no model-specific
# effectiveness; unsupported parameters may be silently ignored.
# https://docs.anyapi.ai/guides/parameters
base_model = "openai/gpt-5.4"
reasoning_options = [{ type = "effort", values = ["low", "medium", "high"] }]

[experimental.modes.fast]
Expand Down
2 changes: 1 addition & 1 deletion providers/anyapi/models/openai/gpt-5.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
base_model = "openai/gpt-5"
# AnyAPI accepts low/medium/high generically but documents no model-specific
# effectiveness; unsupported parameters may be silently ignored.
# https://docs.anyapi.ai/guides/parameters
base_model = "openai/gpt-5"
reasoning_options = [{ type = "effort", values = ["low", "medium", "high"] }]
2 changes: 1 addition & 1 deletion providers/anyapi/models/openai/o3-mini.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
base_model = "openai/o3-mini"
# AnyAPI accepts low/medium/high generically but documents no model-specific
# effectiveness; unsupported parameters may be silently ignored.
# https://docs.anyapi.ai/guides/parameters
base_model = "openai/o3-mini"
reasoning_options = [{ type = "effort", values = ["low", "medium", "high"] }]
2 changes: 1 addition & 1 deletion providers/anyapi/models/openai/o3.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
base_model = "openai/o3"
# AnyAPI accepts low/medium/high generically but documents no model-specific
# effectiveness; unsupported parameters may be silently ignored.
# https://docs.anyapi.ai/guides/parameters
base_model = "openai/o3"
reasoning_options = [{ type = "effort", values = ["low", "medium", "high"] }]
2 changes: 1 addition & 1 deletion providers/anyapi/models/openai/o4-mini.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
base_model = "openai/o4-mini"
# AnyAPI accepts low/medium/high generically but documents no model-specific
# effectiveness; unsupported parameters may be silently ignored.
# https://docs.anyapi.ai/guides/parameters
base_model = "openai/o4-mini"
reasoning_options = [{ type = "effort", values = ["low", "medium", "high"] }]
Loading