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
5 changes: 4 additions & 1 deletion packages/core/src/sync/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { hyper } from "./providers/hyper.js";
import { huggingface } from "./providers/huggingface.js";
import { kilo } from "./providers/kilo.js";
import { llmgateway } from "./providers/llmgateway.js";
import { omnious } from "./providers/omnious.js";
import { openai } from "./providers/openai.js";
import { openrouter } from "./providers/openrouter.js";
import { ovhcloud } from "./providers/ovhcloud.js";
Expand Down Expand Up @@ -119,6 +120,7 @@ export const providers: {
huggingface: SyncProvider<any>;
kilo: SyncProvider<any>;
llmgateway: SyncProvider<any>;
omnious: SyncProvider<any>;
openai: SyncProvider<any>;
openrouter: SyncProvider<any>;
ovhcloud: SyncProvider<any>;
Expand All @@ -142,6 +144,7 @@ export const providers: {
huggingface,
kilo,
llmgateway,
omnious,
openai,
openrouter,
ovhcloud,
Expand All @@ -153,7 +156,7 @@ export const providers: {
};

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

import { z } from "zod";

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

// Repo-level base-model metadata directory (mirrors openrouter.ts MODELS_DIR).
const MODELS_DIR = path.join(import.meta.dirname, "..", "..", "..", "..", "..", "models");

// Omnious is an OpenAI-compatible market rather than a fixed-price gateway: every
// request runs a scoring auction and the winner is paid a second-score price
// capped by a genuine rival, so the served price for a model class moves with the
// book. `GET /v1/models` is public (no key required) and reports the current best
// bid per class, which is the only volatile data we sync — capability, context and
// modality facts stay inherited from the base model.
// https://api.omnious.xyz/v1/models
// OMNIOUS_MODELS_URL overrides the endpoint (e.g. a local router) for testing.
const API_ENDPOINT = process.env.OMNIOUS_MODELS_URL ?? "https://api.omnious.xyz/v1/models";

export const OmniousModel = z
.object({
// Classes carry `model_class`; the catalog also lists routing aliases such as
// `auto`, which have no class and are filtered out in parseModels.
model_class: z.string(),
// Best current bid per 1M tokens, in USDC base units (6 dp).
best_in: z.number(),
best_out: z.number(),
// Who made the model, from the router's class catalog. Null for uncataloged
// classes, which fall back to a unique-suffix lookup in deriveBaseModel.
issuer: z.string().nullable().optional(),
})
.passthrough();

export const OmniousResponse = z.object({ data: z.array(z.unknown()) }).passthrough();

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

// Omnious issuer -> models.dev base-model author prefix. Issuers naming a lab
// models.dev doesn't carry yet (Arcee AI, Liquid AI, …) are absent on purpose:
// deriveBaseModel skips those classes rather than inventing an author for them.
const AUTHOR_BY_ISSUER: Record<string, string> = {
OpenAI: "openai",
Anthropic: "anthropic",
Google: "google",
Alibaba: "alibaba",
"Mistral AI": "mistral",
"Z.ai": "zhipuai",
MiniMax: "minimax",
DeepSeek: "deepseek",
Kimi: "moonshotai",
Perplexity: "perplexity",
"Thinking Machines": "thinkingmachines",
Meta: "meta",
xAI: "xai",
Xiaomi: "xiaomi",
Tencent: "tencent",
Microsoft: "microsoft",
NVIDIA: "nvidia",
Cohere: "cohere",
Poolside: "poolside",
StepFun: "stepfun",
};

/**
* The base models an Omnious entry can inherit from, indexed once per run.
*
* Both maps are keyed lowercase and resolve back to the ID as authored, because
* Omnious class names are lowercase while some base models are not (MiniMax
* ships `minimax/MiniMax-M2`). Resolving through this index rather than probing
* the filesystem also keeps the lookup honest on a case-insensitive volume,
* where an `existsSync` for `minimax/minimax-m2.toml` answers yes and then fails
* catalog generation on Linux.
*
* A base model is indexed only when it declares `limit.output`. Omnious publishes
* price, not limits, so an entry here carries `[cost]` and inherits the rest —
* which means a base without an output limit would merge into a model that fails
* validation. Those classes are skipped rather than given an invented ceiling.
*
* `bySuffix` is the fallback for classes with no issuer: a class maps only when
* exactly one author publishes that model ID, so an ambiguous short name is
* skipped rather than attributed to whichever author sorted first.
*/
let catalogIndex: { byID: Map<string, string>; bySuffix: Map<string, string[]> } | undefined;

function catalog() {
if (catalogIndex !== undefined) return catalogIndex;
const byID = new Map<string, string>();
const bySuffix = new Map<string, string[]>();
for (const author of readdirSync(MODELS_DIR, { withFileTypes: true })) {
if (!author.isDirectory()) continue;
for (const file of readdirSync(path.join(MODELS_DIR, author.name))) {
if (!file.endsWith(".toml")) continue;
const short = file.slice(0, -".toml".length);
const id = `${author.name}/${short}`;
const base = Bun.TOML.parse(
readFileSync(path.join(MODELS_DIR, author.name, file), "utf8"),
) as { limit?: { output?: unknown } };
if (typeof base.limit?.output !== "number") continue;
byID.set(id.toLowerCase(), id);
const key = short.toLowerCase();
bySuffix.set(key, [...(bySuffix.get(key) ?? []), id]);
}
}
catalogIndex = { byID, bySuffix };
return catalogIndex;
}

function deriveBaseModel(model: OmniousModel): string | undefined {
const { byID, bySuffix } = catalog();
const issuer = model.issuer ?? undefined;
const author = issuer === undefined ? undefined : AUTHOR_BY_ISSUER[issuer];
// A known issuer is authoritative: if models.dev doesn't carry that author's
// copy of the class, the class is skipped rather than matched to another lab.
if (author !== undefined) {
return byID.get(`${author}/${model.model_class}`.toLowerCase());
}
const candidates = bySuffix.get(model.model_class.toLowerCase());
return candidates?.length === 1 ? candidates[0] : undefined;
}

/** USDC base units (6 dp) per 1M tokens -> USD per 1M tokens. */
function price(units: number): number | undefined {
if (!Number.isFinite(units) || units <= 0) return undefined;
return Math.round(units) / 1_000_000;
}

export const omnious = {
id: "omnious",
name: "Omnious",
modelsDir: "providers/omnious/models",
async fetchModels() {
const response = await fetch(API_ENDPOINT);
if (!response.ok) {
throw new Error(`Omnious request failed: ${response.status} ${response.statusText}`);
}
return response.json();
},
parseModels(raw) {
// The catalog mixes model classes with routing aliases (`auto`), which carry
// no class or price. Parse per entry so one malformed row can't drop the run.
return OmniousResponse.parse(raw)
.data.map((entry) => OmniousModel.safeParse(entry))
.filter((result) => result.success)
.map((result) => result.data);
},
sourceID(model) {
return model.model_class;
},
translateModel(model) {
const input = price(model.best_in);
const output = price(model.best_out);
// A class with no live bid on one side has no served price to publish.
if (input === undefined || output === undefined) return undefined;

// Skip classes we can't attribute, and classes whose base metadata models.dev
// doesn't carry yet — those need their author metadata added under models/
// first, exactly as for the other aggregators.
const baseModel = deriveBaseModel(model);
if (baseModel === undefined) return undefined;

// Only the auction price is provider-specific. Context, modalities and
// capability flags are provider-agnostic facts and stay inherited from the
// base model, so this entry never contradicts it.
const synced: SyncedModel = { base_model: baseModel, cost: { input, output } };
return { id: model.model_class, model: synced };
},
} satisfies SyncProvider<OmniousModel>;
8 changes: 8 additions & 0 deletions providers/omnious/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions providers/omnious/models/claude-fable-5.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "anthropic/claude-fable-5"
reasoning_options = []

[cost]
input = 11
output = 55
6 changes: 6 additions & 0 deletions providers/omnious/models/claude-sonnet-5.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "anthropic/claude-sonnet-5"
reasoning_options = []

[cost]
input = 2.2
output = 11
5 changes: 5 additions & 0 deletions providers/omnious/models/command-r-08-2024.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
base_model = "cohere/command-r-08-2024"

[cost]
input = 0.165
output = 0.66
5 changes: 5 additions & 0 deletions providers/omnious/models/command-r-plus-08-2024.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
base_model = "cohere/command-r-plus-08-2024"

[cost]
input = 2.75
output = 11
5 changes: 5 additions & 0 deletions providers/omnious/models/command-r7b-12-2024.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
base_model = "cohere/command-r7b-12-2024"

[cost]
input = 0.04125
output = 0.165
5 changes: 5 additions & 0 deletions providers/omnious/models/deepseek-chat.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
base_model = "deepseek/deepseek-chat"

[cost]
input = 0.283142
output = 1.13157
6 changes: 6 additions & 0 deletions providers/omnious/models/deepseek-r1.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "deepseek/deepseek-r1"
reasoning_options = []

[cost]
input = 0.77
output = 2.75
6 changes: 6 additions & 0 deletions providers/omnious/models/deepseek-v4-flash.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "deepseek/deepseek-v4-flash"
reasoning_options = []

[cost]
input = 0.154
output = 0.308
6 changes: 6 additions & 0 deletions providers/omnious/models/deepseek-v4-pro.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "deepseek/deepseek-v4-pro"
reasoning_options = []

[cost]
input = 0.4785
output = 0.957
6 changes: 6 additions & 0 deletions providers/omnious/models/gemini-2.5-flash-lite.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "google/gemini-2.5-flash-lite"
reasoning_options = []

[cost]
input = 0.11
output = 0.44
6 changes: 6 additions & 0 deletions providers/omnious/models/gemini-2.5-flash.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "google/gemini-2.5-flash"
reasoning_options = []

[cost]
input = 0.33
output = 2.75
6 changes: 6 additions & 0 deletions providers/omnious/models/gemini-2.5-pro.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "google/gemini-2.5-pro"
reasoning_options = []

[cost]
input = 1.375
output = 11
6 changes: 6 additions & 0 deletions providers/omnious/models/gemini-3-flash-preview.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "google/gemini-3-flash-preview"
reasoning_options = []

[cost]
input = 0.55
output = 3.3
6 changes: 6 additions & 0 deletions providers/omnious/models/gemini-3.1-flash-lite-preview.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "google/gemini-3.1-flash-lite-preview"
reasoning_options = []

[cost]
input = 0.275
output = 1.65
6 changes: 6 additions & 0 deletions providers/omnious/models/gemini-3.1-flash-lite.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "google/gemini-3.1-flash-lite"
reasoning_options = []

[cost]
input = 0.275
output = 1.65
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "google/gemini-3.1-pro-preview-customtools"
reasoning_options = []

[cost]
input = 2.2
output = 13.2
6 changes: 6 additions & 0 deletions providers/omnious/models/gemini-3.1-pro-preview.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "google/gemini-3.1-pro-preview"
reasoning_options = []

[cost]
input = 2.2
output = 13.2
6 changes: 6 additions & 0 deletions providers/omnious/models/gemini-3.5-flash.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "google/gemini-3.5-flash"
reasoning_options = []

[cost]
input = 1.65
output = 9.9
6 changes: 6 additions & 0 deletions providers/omnious/models/gemini-flash-latest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "google/gemini-flash-latest"
reasoning_options = []

[cost]
input = 1.65
output = 8.25
6 changes: 6 additions & 0 deletions providers/omnious/models/gemma-4-26b-a4b-it.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "google/gemma-4-26b-a4b-it"
reasoning_options = []

[cost]
input = 0.077
output = 0.374
6 changes: 6 additions & 0 deletions providers/omnious/models/gemma-4-31b-it.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "google/gemma-4-31b-it"
reasoning_options = []

[cost]
input = 0.11
output = 0.374
6 changes: 6 additions & 0 deletions providers/omnious/models/glm-4.5-air.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "zhipuai/glm-4.5-air"
reasoning_options = []

[cost]
input = 0.143
output = 0.935
6 changes: 6 additions & 0 deletions providers/omnious/models/glm-4.5.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "zhipuai/glm-4.5"
reasoning_options = []

[cost]
input = 0.418
output = 1.76
6 changes: 6 additions & 0 deletions providers/omnious/models/glm-4.5v.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "zhipuai/glm-4.5v"
reasoning_options = []

[cost]
input = 0.66
output = 1.98
6 changes: 6 additions & 0 deletions providers/omnious/models/glm-4.6.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "zhipuai/glm-4.6"
reasoning_options = []

[cost]
input = 0.55
output = 2.2
6 changes: 6 additions & 0 deletions providers/omnious/models/glm-4.6v.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "zhipuai/glm-4.6v"
reasoning_options = []

[cost]
input = 0.33
output = 0.99
6 changes: 6 additions & 0 deletions providers/omnious/models/glm-4.7-flash.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
base_model = "zhipuai/glm-4.7-flash"
reasoning_options = []

[cost]
input = 0.066
output = 0.44
Loading
Loading