Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 458b7f4d1a | |||
| 8f9adc7567 | |||
| a671cc05d5 | |||
| 2e015de42d | |||
| 151e9c9071 | |||
| b96b074a3b | |||
| 2593e131a1 | |||
| bc95b42ccd | |||
| 6139fb8c69 | |||
| 3070758007 | |||
| 5525e83de4 | |||
| 359fd879b8 | |||
| 01b5a1a656 | |||
| b1958be099 | |||
| 08aa068523 | |||
| f31ad0b02f | |||
| 585aa7fa1b | |||
| c42a327b3e | |||
| 92ebbfb5c4 | |||
| 535fe8c971 | |||
| a3b4bfc16c | |||
| d0fcd6f11f | |||
| e55cd54218 | |||
| 0d73b82b9f | |||
| 83c7e2b63f | |||
| 83ae4cf813 | |||
| 77eae6eef7 | |||
| 8cbf6ed10e | |||
| 06d87e4411 | |||
| 2cb3832618 | |||
| df960d1a90 | |||
| 8f2f83ef61 | |||
| b133426465 | |||
| dafff5a770 | |||
| dd894f077f | |||
| 91590874e7 | |||
| a436236146 | |||
| 1415b4be97 | |||
| 70ac6fccda | |||
| dc3283417d | |||
| 34fd6673e5 | |||
| c5fbcc2c9b | |||
| ab2eb51b4e | |||
| 8e19ec580c | |||
| 3aecc94c46 | |||
| dbe92646c3 | |||
| 4717c67054 |
@@ -17,6 +17,7 @@
|
||||
"scripts": {
|
||||
"validate": "bun ./packages/core/script/validate.ts",
|
||||
"compare:migrations": "bun ./packages/core/script/compare-model-migrations.ts",
|
||||
"chutes:generate": "bun ./packages/core/script/generate-chutes.ts",
|
||||
"helicone:generate": "bun ./packages/core/script/generate-helicone.ts",
|
||||
"venice:generate": "bun ./packages/core/script/generate-venice.ts",
|
||||
"vercel:generate": "bun ./packages/core/script/generate-vercel.ts",
|
||||
|
||||
@@ -0,0 +1,589 @@
|
||||
#!/usr/bin/env bun
|
||||
|
||||
/**
|
||||
* Generates Chutes model TOML files from the Chutes LLM API.
|
||||
*
|
||||
* Flags:
|
||||
* --dry-run: Preview changes without writing files
|
||||
* --new-only: Only create new models, skip updating existing ones
|
||||
* --keep-orphans: Don't delete TOML files for models no longer in the API
|
||||
*/
|
||||
|
||||
import { z } from "zod";
|
||||
import path from "node:path";
|
||||
import { mkdir } from "node:fs/promises";
|
||||
import { ModelFamilyValues } from "../src/family.js";
|
||||
|
||||
const API_ENDPOINT = "https://llm.chutes.ai/v1/models";
|
||||
|
||||
enum SkipZeroFields {
|
||||
LimitContext = "limit.context",
|
||||
LimitOutput = "limit.output",
|
||||
}
|
||||
|
||||
const Pricing = z.object({
|
||||
prompt: z.number().optional(),
|
||||
completion: z.number().optional(),
|
||||
input_cache_read: z.number().optional(),
|
||||
}).passthrough();
|
||||
|
||||
const ChutesModel = z.object({
|
||||
id: z.string(),
|
||||
created: z.number(),
|
||||
pricing: Pricing.optional(),
|
||||
context_length: z.number().optional(),
|
||||
max_output_length: z.number().optional(),
|
||||
max_model_len: z.number().optional(),
|
||||
input_modalities: z.array(z.string()).optional(),
|
||||
output_modalities: z.array(z.string()).optional(),
|
||||
supported_features: z.array(z.string()).optional(),
|
||||
supported_sampling_parameters: z.array(z.string()).optional(),
|
||||
quantization: z.string().optional(),
|
||||
}).passthrough();
|
||||
|
||||
const ChutesResponse = z.object({
|
||||
data: z.array(ChutesModel),
|
||||
}).passthrough();
|
||||
|
||||
interface ExistingModel {
|
||||
name?: string;
|
||||
family?: string;
|
||||
attachment?: boolean;
|
||||
reasoning?: boolean;
|
||||
tool_call?: boolean;
|
||||
structured_output?: boolean;
|
||||
temperature?: boolean;
|
||||
knowledge?: string;
|
||||
release_date?: string;
|
||||
last_updated?: string;
|
||||
open_weights?: boolean;
|
||||
interleaved?: boolean | { field: string };
|
||||
status?: string;
|
||||
cost?: {
|
||||
input?: number;
|
||||
output?: number;
|
||||
cache_read?: number;
|
||||
};
|
||||
limit?: {
|
||||
context?: number;
|
||||
output?: number;
|
||||
};
|
||||
modalities?: {
|
||||
input?: string[];
|
||||
output?: string[];
|
||||
};
|
||||
}
|
||||
|
||||
interface MergedModel {
|
||||
name: string;
|
||||
family?: string;
|
||||
attachment: boolean;
|
||||
reasoning: boolean;
|
||||
tool_call: boolean;
|
||||
structured_output?: boolean;
|
||||
temperature: boolean;
|
||||
knowledge?: string;
|
||||
release_date: string;
|
||||
last_updated: string;
|
||||
open_weights: boolean;
|
||||
interleaved?: boolean | { field: string };
|
||||
status?: string;
|
||||
cost?: {
|
||||
input: number;
|
||||
output: number;
|
||||
cache_read?: number;
|
||||
};
|
||||
limit: {
|
||||
context: number;
|
||||
output: number;
|
||||
};
|
||||
modalities: {
|
||||
input: string[];
|
||||
output: string[];
|
||||
};
|
||||
}
|
||||
|
||||
interface Changes {
|
||||
field: string;
|
||||
oldValue: string;
|
||||
newValue: string;
|
||||
}
|
||||
|
||||
// ── Utility functions ────────────────────────────────────────────────
|
||||
|
||||
function timestampToDate(timestamp: number): string {
|
||||
const date = new Date(timestamp * 1000);
|
||||
return date.toISOString().slice(0, 10);
|
||||
}
|
||||
|
||||
function getTodayDate(): string {
|
||||
return new Date().toISOString().slice(0, 10);
|
||||
}
|
||||
|
||||
function formatNumber(n: number): string {
|
||||
if (n >= 1000) {
|
||||
return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, "_");
|
||||
}
|
||||
return n.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Humanize a model ID into a readable name.
|
||||
* Strips the org prefix and replaces hyphens with spaces.
|
||||
* e.g. "Qwen/Qwen3-32B-TEE" → "Qwen3 32B TEE"
|
||||
*/
|
||||
function humanizeModelName(modelId: string): string {
|
||||
const parts = modelId.split("/");
|
||||
const modelPart = parts[parts.length - 1];
|
||||
return modelPart.replace(/-/g, " ");
|
||||
}
|
||||
|
||||
// ── Family inference (same approach as generate-vercel.ts) ───────────
|
||||
|
||||
function isSubstring(target: string, family: string): boolean {
|
||||
return target.toLowerCase().includes(family.toLowerCase());
|
||||
}
|
||||
|
||||
function matchesFamily(target: string, family: string): boolean {
|
||||
const targetLower = target.toLowerCase();
|
||||
const familyLower = family.toLowerCase();
|
||||
let familyIdx = 0;
|
||||
|
||||
for (let i = 0; i < targetLower.length && familyIdx < familyLower.length; i++) {
|
||||
if (targetLower[i] === familyLower[familyIdx]) {
|
||||
familyIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
return familyIdx === familyLower.length;
|
||||
}
|
||||
|
||||
function inferFamily(modelId: string, modelName: string): string | undefined {
|
||||
const sortedFamilies = [...ModelFamilyValues].sort((a, b) => b.length - a.length);
|
||||
|
||||
// First pass: try exact substring matches
|
||||
for (const family of sortedFamilies) {
|
||||
if (isSubstring(modelId, family)) {
|
||||
return family;
|
||||
}
|
||||
}
|
||||
|
||||
for (const family of sortedFamilies) {
|
||||
if (isSubstring(modelName, family)) {
|
||||
return family;
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass: fall back to subsequence matching
|
||||
for (const family of sortedFamilies) {
|
||||
if (matchesFamily(modelId, family)) {
|
||||
return family;
|
||||
}
|
||||
}
|
||||
|
||||
for (const family of sortedFamilies) {
|
||||
if (matchesFamily(modelName, family)) {
|
||||
return family;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// ── Load existing TOML ───────────────────────────────────────────────
|
||||
|
||||
async function loadExistingModel(filePath: string): Promise<ExistingModel | null> {
|
||||
try {
|
||||
const file = Bun.file(filePath);
|
||||
if (!(await file.exists())) {
|
||||
return null;
|
||||
}
|
||||
const toml = await import(filePath, { with: { type: "toml" } }).then(
|
||||
(mod) => mod.default,
|
||||
);
|
||||
return toml as ExistingModel;
|
||||
} catch (e) {
|
||||
console.warn(`Warning: Failed to parse existing file ${filePath}:`, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Merge API data with existing TOML ────────────────────────────────
|
||||
|
||||
function mergeModel(
|
||||
apiModel: z.infer<typeof ChutesModel>,
|
||||
existing: ExistingModel | null,
|
||||
): MergedModel {
|
||||
const features = new Set(apiModel.supported_features ?? []);
|
||||
const samplingParams = new Set(apiModel.supported_sampling_parameters ?? []);
|
||||
const inputMods = apiModel.input_modalities ?? ["text"];
|
||||
const outputMods = apiModel.output_modalities ?? ["text"];
|
||||
|
||||
// Capabilities from API features
|
||||
const hasAttachment = inputMods.some((m) =>
|
||||
m === "image" || m === "video" || m === "pdf",
|
||||
);
|
||||
const hasReasoning = features.has("reasoning");
|
||||
const hasToolCall = features.has("tools");
|
||||
const hasStructuredOutput = features.has("structured_outputs");
|
||||
const hasTemperature = samplingParams.size > 0
|
||||
? samplingParams.has("temperature")
|
||||
: true; // default true if no sampling params info
|
||||
|
||||
// Preserve existing values when available (manually specified)
|
||||
const modelName = existing?.name ?? humanizeModelName(apiModel.id);
|
||||
const family = existing?.family ?? inferFamily(apiModel.id, modelName);
|
||||
const knowledge = existing?.knowledge;
|
||||
const interleaved = existing?.interleaved;
|
||||
const status = existing?.status;
|
||||
|
||||
// Release date: existing > API created timestamp > today
|
||||
const releaseDate = existing?.release_date
|
||||
?? timestampToDate(apiModel.created)
|
||||
?? getTodayDate();
|
||||
|
||||
// Context limit: prefer context_length, fallback to max_model_len
|
||||
const apiContext = apiModel.context_length ?? apiModel.max_model_len ?? 0;
|
||||
const contextLimit = apiContext > 0
|
||||
? apiContext
|
||||
: (existing?.limit?.context ?? 0);
|
||||
|
||||
// Output limit: prefer max_output_length, fallback to existing
|
||||
const apiOutput = apiModel.max_output_length ?? 0;
|
||||
const outputLimit = apiOutput > 0
|
||||
? apiOutput
|
||||
: (existing?.limit?.output ?? 0);
|
||||
|
||||
const merged: MergedModel = {
|
||||
name: modelName,
|
||||
family,
|
||||
attachment: hasAttachment,
|
||||
reasoning: hasReasoning,
|
||||
tool_call: hasToolCall,
|
||||
temperature: hasTemperature,
|
||||
release_date: releaseDate,
|
||||
last_updated: getTodayDate(),
|
||||
open_weights: true, // Chutes hosts open-weight models
|
||||
...(hasStructuredOutput && { structured_output: hasStructuredOutput }),
|
||||
...(knowledge && { knowledge }),
|
||||
...(interleaved !== undefined && { interleaved }),
|
||||
...(status && { status }),
|
||||
limit: {
|
||||
context: contextLimit,
|
||||
output: outputLimit,
|
||||
},
|
||||
modalities: {
|
||||
input: inputMods,
|
||||
output: outputMods,
|
||||
},
|
||||
};
|
||||
|
||||
// Cost: API values are already in USD per 1M tokens — use directly
|
||||
if (apiModel.pricing) {
|
||||
const inputPrice = apiModel.pricing.prompt;
|
||||
const outputPrice = apiModel.pricing.completion;
|
||||
const cacheReadPrice = apiModel.pricing.input_cache_read;
|
||||
|
||||
if (inputPrice !== undefined && outputPrice !== undefined) {
|
||||
merged.cost = {
|
||||
input: inputPrice,
|
||||
output: outputPrice,
|
||||
...(cacheReadPrice !== undefined && { cache_read: cacheReadPrice }),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return merged;
|
||||
}
|
||||
|
||||
// ── TOML formatting ──────────────────────────────────────────────────
|
||||
|
||||
function formatToml(model: MergedModel): string {
|
||||
const lines: string[] = [];
|
||||
|
||||
lines.push(`# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.`);
|
||||
lines.push(`# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status`);
|
||||
lines.push(`name = "${model.name.replace(/"/g, '\\"')}"`);
|
||||
if (model.family) {
|
||||
lines.push(`family = "${model.family}"`);
|
||||
}
|
||||
lines.push(`release_date = "${model.release_date}"`);
|
||||
lines.push(`last_updated = "${model.last_updated}"`);
|
||||
lines.push(`attachment = ${model.attachment}`);
|
||||
lines.push(`reasoning = ${model.reasoning}`);
|
||||
lines.push(`temperature = ${model.temperature}`);
|
||||
lines.push(`tool_call = ${model.tool_call}`);
|
||||
if (model.structured_output !== undefined) {
|
||||
lines.push(`structured_output = ${model.structured_output}`);
|
||||
}
|
||||
lines.push(`open_weights = ${model.open_weights}`);
|
||||
if (model.knowledge) {
|
||||
lines.push(`knowledge = "${model.knowledge}"`);
|
||||
}
|
||||
if (model.status) {
|
||||
lines.push(`status = "${model.status}"`);
|
||||
}
|
||||
|
||||
if (model.cost) {
|
||||
lines.push("");
|
||||
lines.push(`[cost]`);
|
||||
lines.push(`input = ${model.cost.input}`);
|
||||
lines.push(`output = ${model.cost.output}`);
|
||||
if (model.cost.cache_read !== undefined) {
|
||||
lines.push(`cache_read = ${model.cost.cache_read}`);
|
||||
}
|
||||
}
|
||||
|
||||
lines.push("");
|
||||
lines.push(`[limit]`);
|
||||
lines.push(`context = ${formatNumber(model.limit.context)}`);
|
||||
lines.push(`output = ${formatNumber(model.limit.output)}`);
|
||||
|
||||
lines.push("");
|
||||
lines.push(`[modalities]`);
|
||||
lines.push(`input = [${model.modalities.input.map((m) => `"${m}"`).join(", ")}]`);
|
||||
lines.push(`output = [${model.modalities.output.map((m) => `"${m}"`).join(", ")}]`);
|
||||
|
||||
if (model.interleaved !== undefined) {
|
||||
lines.push("");
|
||||
if (model.interleaved === true) {
|
||||
lines.push(`interleaved = true`);
|
||||
} else if (typeof model.interleaved === "object") {
|
||||
lines.push(`[interleaved]`);
|
||||
lines.push(`field = "${model.interleaved.field}"`);
|
||||
}
|
||||
}
|
||||
|
||||
return lines.join("\n") + "\n";
|
||||
}
|
||||
|
||||
// ── Change detection ─────────────────────────────────────────────────
|
||||
|
||||
function detectChanges(
|
||||
existing: ExistingModel | null,
|
||||
merged: MergedModel,
|
||||
): Changes[] {
|
||||
if (!existing) return [];
|
||||
|
||||
const changes: Changes[] = [];
|
||||
const EPSILON = 0.001;
|
||||
|
||||
const shouldSkipZero = (field: string, oldVal: unknown, newVal: unknown): boolean => {
|
||||
if (!Object.values(SkipZeroFields).includes(field as SkipZeroFields)) {
|
||||
return false;
|
||||
}
|
||||
return (typeof oldVal === "number" && oldVal === 0) || (typeof newVal === "number" && newVal === 0);
|
||||
};
|
||||
|
||||
const formatValue = (val: unknown): string => {
|
||||
if (typeof val === "number") return formatNumber(val);
|
||||
if (Array.isArray(val)) return `[${val.join(", ")}]`;
|
||||
if (val === undefined) return "(none)";
|
||||
return String(val);
|
||||
};
|
||||
|
||||
const isMaterialPriceDiff = (oldPrice: unknown, newPrice: unknown): boolean => {
|
||||
if (oldPrice === 0 && newPrice === undefined) return false;
|
||||
if (oldPrice !== undefined && newPrice !== undefined) {
|
||||
return Math.abs((oldPrice as number) - (newPrice as number)) > EPSILON;
|
||||
}
|
||||
return oldPrice !== newPrice;
|
||||
};
|
||||
|
||||
const compare = (field: string, oldVal: unknown, newVal: unknown) => {
|
||||
if (shouldSkipZero(field, oldVal, newVal)) return;
|
||||
|
||||
const isDiff = field.startsWith("cost.")
|
||||
? isMaterialPriceDiff(oldVal, newVal)
|
||||
: JSON.stringify(oldVal) !== JSON.stringify(newVal);
|
||||
|
||||
if (isDiff) {
|
||||
changes.push({
|
||||
field,
|
||||
oldValue: formatValue(oldVal),
|
||||
newValue: formatValue(newVal),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
compare("name", existing.name, merged.name);
|
||||
compare("family", existing.family, merged.family);
|
||||
compare("attachment", existing.attachment, merged.attachment);
|
||||
compare("reasoning", existing.reasoning, merged.reasoning);
|
||||
compare("tool_call", existing.tool_call, merged.tool_call);
|
||||
compare("structured_output", existing.structured_output, merged.structured_output);
|
||||
compare("open_weights", existing.open_weights, merged.open_weights);
|
||||
compare("release_date", existing.release_date, merged.release_date);
|
||||
compare("cost.input", existing.cost?.input, merged.cost?.input);
|
||||
compare("cost.output", existing.cost?.output, merged.cost?.output);
|
||||
compare("cost.cache_read", existing.cost?.cache_read, merged.cost?.cache_read);
|
||||
compare("limit.context", existing.limit?.context, merged.limit.context);
|
||||
compare("limit.output", existing.limit?.output, merged.limit.output);
|
||||
compare("modalities.input", existing.modalities?.input, merged.modalities.input);
|
||||
compare("modalities.output", existing.modalities?.output, merged.modalities.output);
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
// ── Main ─────────────────────────────────────────────────────────────
|
||||
|
||||
async function main() {
|
||||
const args = process.argv.slice(2);
|
||||
const dryRun = args.includes("--dry-run");
|
||||
const newOnly = args.includes("--new-only");
|
||||
const keepOrphans = args.includes("--keep-orphans");
|
||||
|
||||
const modelsDir = path.join(
|
||||
import.meta.dirname,
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"providers",
|
||||
"chutes",
|
||||
"models",
|
||||
);
|
||||
|
||||
console.log(`${dryRun ? "[DRY RUN] " : ""}${newOnly ? "[NEW ONLY] " : ""}${keepOrphans ? "[KEEP ORPHANS] " : ""}Fetching Chutes models from API...`);
|
||||
|
||||
const res = await fetch(API_ENDPOINT);
|
||||
if (!res.ok) {
|
||||
console.error(`Failed to fetch API: ${res.status} ${res.statusText}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const json = await res.json();
|
||||
const parsed = ChutesResponse.safeParse(json);
|
||||
if (!parsed.success) {
|
||||
console.error("Invalid API response:", parsed.error.errors);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const apiModels = parsed.data.data;
|
||||
|
||||
// Scan existing TOML files
|
||||
const existingFiles = new Set<string>();
|
||||
try {
|
||||
for await (const file of new Bun.Glob("**/*.toml").scan({
|
||||
cwd: modelsDir,
|
||||
absolute: false,
|
||||
})) {
|
||||
existingFiles.add(file);
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
|
||||
console.log(`Found ${apiModels.length} models in API, ${existingFiles.size} existing files\n`);
|
||||
|
||||
const apiModelIds = new Set<string>();
|
||||
|
||||
let created = 0;
|
||||
let updated = 0;
|
||||
let unchanged = 0;
|
||||
|
||||
for (const apiModel of apiModels) {
|
||||
const relativePath = `${apiModel.id}.toml`;
|
||||
const filePath = path.join(modelsDir, relativePath);
|
||||
const dirPath = path.dirname(filePath);
|
||||
|
||||
apiModelIds.add(relativePath);
|
||||
|
||||
const existing = await loadExistingModel(filePath);
|
||||
const merged = mergeModel(apiModel, existing);
|
||||
const tomlContent = formatToml(merged);
|
||||
|
||||
if (existing === null) {
|
||||
created++;
|
||||
if (dryRun) {
|
||||
console.log(`[DRY RUN] Would create: ${relativePath}`);
|
||||
console.log(` name = "${merged.name}"`);
|
||||
if (merged.family) {
|
||||
console.log(` family = "${merged.family}" (inferred)`);
|
||||
}
|
||||
console.log("");
|
||||
} else {
|
||||
await mkdir(dirPath, { recursive: true });
|
||||
await Bun.write(filePath, tomlContent);
|
||||
console.log(`Created: ${relativePath}`);
|
||||
}
|
||||
} else {
|
||||
if (newOnly) {
|
||||
unchanged++;
|
||||
continue;
|
||||
}
|
||||
|
||||
const changes = detectChanges(existing, merged);
|
||||
const existingContent = await Bun.file(filePath).text();
|
||||
const formatChanged = existingContent !== tomlContent;
|
||||
|
||||
if (changes.length > 0 || formatChanged) {
|
||||
updated++;
|
||||
if (dryRun) {
|
||||
console.log(`[DRY RUN] Would update: ${relativePath}`);
|
||||
} else {
|
||||
await mkdir(dirPath, { recursive: true });
|
||||
await Bun.write(filePath, tomlContent);
|
||||
console.log(`Updated: ${relativePath}`);
|
||||
}
|
||||
for (const change of changes) {
|
||||
console.log(` ${change.field}: ${change.oldValue} → ${change.newValue}`);
|
||||
}
|
||||
if (changes.length === 0 && formatChanged) {
|
||||
console.log(` (format-only change)`);
|
||||
}
|
||||
console.log("");
|
||||
} else {
|
||||
unchanged++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle orphaned files (on disk but not in API)
|
||||
const orphaned: string[] = [];
|
||||
for (const file of existingFiles) {
|
||||
if (!apiModelIds.has(file)) {
|
||||
orphaned.push(file);
|
||||
const orphanPath = path.join(modelsDir, file);
|
||||
if (keepOrphans) {
|
||||
console.log(`Orphaned (kept): ${file}`);
|
||||
} else if (dryRun) {
|
||||
console.log(`[DRY RUN] Would delete: ${file}`);
|
||||
} else {
|
||||
await Bun.file(orphanPath).delete();
|
||||
console.log(`Deleted: ${file}`);
|
||||
|
||||
// Clean up empty parent directories
|
||||
const parentDir = path.dirname(orphanPath);
|
||||
try {
|
||||
const remaining = [];
|
||||
for await (const entry of new Bun.Glob("*").scan({ cwd: parentDir })) {
|
||||
remaining.push(entry);
|
||||
}
|
||||
if (remaining.length === 0) {
|
||||
const { rmdir } = await import("node:fs/promises");
|
||||
await rmdir(parentDir);
|
||||
console.log(` Removed empty directory: ${path.basename(parentDir)}/`);
|
||||
}
|
||||
} catch {
|
||||
// Directory not empty or other error, ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log("");
|
||||
if (dryRun) {
|
||||
console.log(
|
||||
`Summary: ${created} would be created, ${updated} would be updated, ${unchanged} unchanged, ${orphaned.length} would be deleted`,
|
||||
);
|
||||
} else if (keepOrphans) {
|
||||
console.log(
|
||||
`Summary: ${created} created, ${updated} updated, ${unchanged} unchanged, ${orphaned.length} orphaned (kept)`,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
`Summary: ${created} created, ${updated} updated, ${unchanged} unchanged, ${orphaned.length} deleted`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await main();
|
||||
@@ -209,7 +209,18 @@ interface ExistingModel {
|
||||
output?: number;
|
||||
cache_read?: number;
|
||||
cache_write?: number;
|
||||
context_min?: number;
|
||||
};
|
||||
tiers?: Array<{
|
||||
tier: {
|
||||
type?: "context";
|
||||
size: number;
|
||||
};
|
||||
input?: number;
|
||||
output?: number;
|
||||
cache_read?: number;
|
||||
cache_write?: number;
|
||||
}>;
|
||||
};
|
||||
limit?: {
|
||||
context?: number;
|
||||
@@ -262,6 +273,7 @@ interface MergedModel {
|
||||
output: number;
|
||||
cache_read?: number;
|
||||
cache_write?: number;
|
||||
context_min?: number;
|
||||
};
|
||||
};
|
||||
limit: {
|
||||
@@ -310,6 +322,35 @@ function inferFamily(modelId: string, modelName: string): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getExistingLongContextCost(existing: ExistingModel | null) {
|
||||
const tier = existing?.cost?.tiers?.find(
|
||||
(tier) =>
|
||||
(tier.tier.type === undefined || tier.tier.type === "context") &&
|
||||
tier.tier.size >= 200_000,
|
||||
);
|
||||
if (tier) {
|
||||
return {
|
||||
...tier,
|
||||
context_min: tier.tier.size,
|
||||
};
|
||||
}
|
||||
|
||||
return existing?.cost?.context_over_200k === undefined
|
||||
? undefined
|
||||
: {
|
||||
...existing.cost.context_over_200k,
|
||||
context_min: 200_000,
|
||||
};
|
||||
}
|
||||
|
||||
function getLongContextMin(cost: { context_min?: number }) {
|
||||
return cost.context_min ?? 200_000;
|
||||
}
|
||||
|
||||
function formatInlineNumber(n: number): string {
|
||||
return n >= 1000 ? n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, "_") : n.toString();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Merge API data with existing TOML
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -394,27 +435,30 @@ function mergeModel(
|
||||
};
|
||||
|
||||
// Context-tiered pricing (>200k) from the static-content API
|
||||
const existingLongContextCost = getExistingLongContextCost(existing);
|
||||
if (pricing?.inputOver200k !== undefined && pricing?.outputOver200k !== undefined) {
|
||||
merged.cost.context_over_200k = {
|
||||
input: pricing.inputOver200k,
|
||||
output: pricing.outputOver200k,
|
||||
...(existing?.cost?.context_over_200k?.cache_read !== undefined && {
|
||||
cache_read: existing.cost.context_over_200k.cache_read,
|
||||
context_min: existingLongContextCost?.context_min ?? 200_000,
|
||||
...(existingLongContextCost?.cache_read !== undefined && {
|
||||
cache_read: existingLongContextCost.cache_read,
|
||||
}),
|
||||
...(existing?.cost?.context_over_200k?.cache_write !== undefined && {
|
||||
cache_write: existing.cost.context_over_200k.cache_write,
|
||||
...(existingLongContextCost?.cache_write !== undefined && {
|
||||
cache_write: existingLongContextCost.cache_write,
|
||||
}),
|
||||
};
|
||||
} else if (existing?.cost?.context_over_200k) {
|
||||
// Preserve manually-entered context_over_200k if API has no data
|
||||
} else if (existingLongContextCost) {
|
||||
// Preserve manually-entered tiered pricing if API has no data
|
||||
merged.cost.context_over_200k = {
|
||||
input: existing.cost.context_over_200k.input ?? inputPrice,
|
||||
output: existing.cost.context_over_200k.output ?? outputPrice,
|
||||
...(existing.cost.context_over_200k.cache_read !== undefined && {
|
||||
cache_read: existing.cost.context_over_200k.cache_read,
|
||||
input: existingLongContextCost.input ?? inputPrice,
|
||||
output: existingLongContextCost.output ?? outputPrice,
|
||||
context_min: existingLongContextCost.context_min,
|
||||
...(existingLongContextCost.cache_read !== undefined && {
|
||||
cache_read: existingLongContextCost.cache_read,
|
||||
}),
|
||||
...(existing.cost.context_over_200k.cache_write !== undefined && {
|
||||
cache_write: existing.cost.context_over_200k.cache_write,
|
||||
...(existingLongContextCost.cache_write !== undefined && {
|
||||
cache_write: existingLongContextCost.cache_write,
|
||||
}),
|
||||
};
|
||||
}
|
||||
@@ -463,7 +507,8 @@ function formatToml(model: MergedModel): string {
|
||||
|
||||
if (model.cost.context_over_200k) {
|
||||
lines.push("");
|
||||
lines.push(`[cost.context_over_200k]`);
|
||||
lines.push(`[[cost.tiers]]`);
|
||||
lines.push(`tier = { size = ${formatInlineNumber(getLongContextMin(model.cost.context_over_200k))} }`);
|
||||
lines.push(`input = ${model.cost.context_over_200k.input}`);
|
||||
lines.push(`output = ${model.cost.context_over_200k.output}`);
|
||||
if (model.cost.context_over_200k.cache_read !== undefined)
|
||||
@@ -524,8 +569,9 @@ function detectChanges(existing: ExistingModel | null, merged: MergedModel): Cha
|
||||
compare("status", existing.status, merged.status);
|
||||
compare("cost.input", existing.cost?.input, merged.cost?.input);
|
||||
compare("cost.output", existing.cost?.output, merged.cost?.output);
|
||||
compare("cost.context_over_200k.input", existing.cost?.context_over_200k?.input, merged.cost?.context_over_200k?.input);
|
||||
compare("cost.context_over_200k.output", existing.cost?.context_over_200k?.output, merged.cost?.context_over_200k?.output);
|
||||
const existingLongContextCost = getExistingLongContextCost(existing);
|
||||
compare("cost.context_over_200k.input", existingLongContextCost?.input, merged.cost?.context_over_200k?.input);
|
||||
compare("cost.context_over_200k.output", existingLongContextCost?.output, merged.cost?.context_over_200k?.output);
|
||||
compare("limit.context", existing.limit?.context, merged.limit.context);
|
||||
compare("limit.output", existing.limit?.output, merged.limit.output);
|
||||
compare("modalities.input", existing.modalities?.input, merged.modalities.input);
|
||||
|
||||
@@ -162,7 +162,18 @@ interface ExistingModel {
|
||||
output?: number;
|
||||
cache_read?: number;
|
||||
cache_write?: number;
|
||||
context_min?: number;
|
||||
};
|
||||
tiers?: Array<{
|
||||
tier: {
|
||||
type?: "context";
|
||||
size: number;
|
||||
};
|
||||
input?: number;
|
||||
output?: number;
|
||||
cache_read?: number;
|
||||
cache_write?: number;
|
||||
}>;
|
||||
};
|
||||
limit?: {
|
||||
context?: number;
|
||||
@@ -195,6 +206,30 @@ async function loadExistingModel(filePath: string): Promise<ExistingModel | null
|
||||
}
|
||||
}
|
||||
|
||||
function getExistingLongContextMin(existing: ExistingModel | null) {
|
||||
return (
|
||||
existing?.cost?.tiers?.find(
|
||||
(tier) =>
|
||||
(tier.tier.type === undefined || tier.tier.type === "context") &&
|
||||
tier.tier.size >= 200_000,
|
||||
)?.tier.size ?? 200_000
|
||||
);
|
||||
}
|
||||
|
||||
function getExistingLongContextCost(existing: ExistingModel | null) {
|
||||
return (
|
||||
existing?.cost?.tiers?.find(
|
||||
(tier) =>
|
||||
(tier.tier.type === undefined || tier.tier.type === "context") &&
|
||||
tier.tier.size >= 200_000,
|
||||
) ?? existing?.cost?.context_over_200k
|
||||
);
|
||||
}
|
||||
|
||||
function getLongContextMin(cost: { context_min?: number }) {
|
||||
return cost.context_min ?? 200_000;
|
||||
}
|
||||
|
||||
interface MergedModel {
|
||||
name: string;
|
||||
family?: string;
|
||||
@@ -219,6 +254,7 @@ interface MergedModel {
|
||||
output: number;
|
||||
cache_read?: number;
|
||||
cache_write?: number;
|
||||
context_min?: number;
|
||||
};
|
||||
};
|
||||
limit: {
|
||||
@@ -292,6 +328,7 @@ function mergeModel(
|
||||
merged.cost.context_over_200k = {
|
||||
input: spec.pricing.extended.input.usd,
|
||||
output: spec.pricing.extended.output.usd,
|
||||
context_min: spec.pricing.extended.context_token_threshold,
|
||||
...(spec.pricing.extended.cache_input && { cache_read: spec.pricing.extended.cache_input.usd }),
|
||||
...(spec.pricing.extended.cache_write && { cache_write: spec.pricing.extended.cache_write.usd }),
|
||||
};
|
||||
@@ -366,7 +403,8 @@ function formatToml(model: MergedModel): string {
|
||||
|
||||
if (model.cost.context_over_200k) {
|
||||
lines.push("");
|
||||
lines.push(`[cost.context_over_200k]`);
|
||||
lines.push(`[[cost.tiers]]`);
|
||||
lines.push(`tier = { size = ${formatNumber(getLongContextMin(model.cost.context_over_200k))} }`);
|
||||
lines.push(`input = ${model.cost.context_over_200k.input}`);
|
||||
lines.push(`output = ${model.cost.context_over_200k.output}`);
|
||||
if (model.cost.context_over_200k.cache_read !== undefined) {
|
||||
@@ -438,10 +476,11 @@ function detectChanges(
|
||||
compare("cost.output", existing.cost?.output, merged.cost?.output);
|
||||
compare("cost.cache_read", existing.cost?.cache_read, merged.cost?.cache_read);
|
||||
compare("cost.cache_write", existing.cost?.cache_write, merged.cost?.cache_write);
|
||||
compare("cost.context_over_200k.input", existing.cost?.context_over_200k?.input, merged.cost?.context_over_200k?.input);
|
||||
compare("cost.context_over_200k.output", existing.cost?.context_over_200k?.output, merged.cost?.context_over_200k?.output);
|
||||
compare("cost.context_over_200k.cache_read", existing.cost?.context_over_200k?.cache_read, merged.cost?.context_over_200k?.cache_read);
|
||||
compare("cost.context_over_200k.cache_write", existing.cost?.context_over_200k?.cache_write, merged.cost?.context_over_200k?.cache_write);
|
||||
const existingLongContextCost = getExistingLongContextCost(existing);
|
||||
compare("cost.context_over_200k.input", existingLongContextCost?.input, merged.cost?.context_over_200k?.input);
|
||||
compare("cost.context_over_200k.output", existingLongContextCost?.output, merged.cost?.context_over_200k?.output);
|
||||
compare("cost.context_over_200k.cache_read", existingLongContextCost?.cache_read, merged.cost?.context_over_200k?.cache_read);
|
||||
compare("cost.context_over_200k.cache_write", existingLongContextCost?.cache_write, merged.cost?.context_over_200k?.cache_write);
|
||||
compare("limit.context", existing.limit?.context, merged.limit.context);
|
||||
compare("limit.output", existing.limit?.output, merged.limit.output);
|
||||
compare("modalities.input", existing.modalities?.input, merged.modalities.input);
|
||||
|
||||
@@ -55,6 +55,7 @@ export const ModelFamilyValues = [
|
||||
"deepseek",
|
||||
"deepseek-thinking",
|
||||
"deepseek-flash",
|
||||
"deepseek-flash-free",
|
||||
"deepseek-flash-think",
|
||||
|
||||
// Microsoft Phi
|
||||
@@ -289,12 +290,14 @@ export const ModelFamilyValues = [
|
||||
"rnj",
|
||||
|
||||
// Tecent Hy
|
||||
"hy3",
|
||||
"hy3-free",
|
||||
|
||||
// Ling & Ring (InclusionAI)
|
||||
"ling",
|
||||
"ling-flash-free",
|
||||
"ring",
|
||||
"ring-1t-free",
|
||||
|
||||
// Kat Coder
|
||||
"kat-coder",
|
||||
|
||||
@@ -2,9 +2,9 @@ import path from "path";
|
||||
import { mergeDeep } from "remeda";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Provider, Model } from "./schema.js";
|
||||
import { Provider, Model, AuthoredModel, AuthoredModelShape } from "./schema.js";
|
||||
|
||||
const ExtendsModel = Model.sourceType()
|
||||
const ExtendsModel = AuthoredModelShape
|
||||
.partial()
|
||||
.extend({
|
||||
extends: z
|
||||
@@ -71,12 +71,12 @@ export async function generate(directory: string) {
|
||||
});
|
||||
continue;
|
||||
}
|
||||
const model = Model.safeParse(toml);
|
||||
const model = AuthoredModel.safeParse(toml);
|
||||
if (!model.success) {
|
||||
model.error.cause = { modelPath, toml };
|
||||
throw model.error;
|
||||
}
|
||||
provider.data.models[modelID] = model.data;
|
||||
provider.data.models[modelID] = normalizeModelCost(model.data);
|
||||
}
|
||||
result[providerID] = provider.data;
|
||||
}
|
||||
@@ -144,7 +144,7 @@ export async function generate(directory: string) {
|
||||
}
|
||||
}
|
||||
|
||||
const model = Model.safeParse(merged);
|
||||
const model = Model.safeParse(normalizeCost(merged));
|
||||
if (!model.success) {
|
||||
model.error.cause = { modelPath: pendingModel.modelPath, toml: merged };
|
||||
throw model.error;
|
||||
@@ -155,3 +155,51 @@ export async function generate(directory: string) {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function normalizeModelCost(model: z.infer<typeof AuthoredModel>): Model {
|
||||
return normalizeCost(model) as Model;
|
||||
}
|
||||
|
||||
function normalizeCost(model: Record<string, unknown>) {
|
||||
const cost = model.cost;
|
||||
if (cost === undefined || cost === null || typeof cost !== "object" || Array.isArray(cost)) {
|
||||
return model;
|
||||
}
|
||||
|
||||
const tiers = (cost as { tiers?: unknown }).tiers;
|
||||
if (!Array.isArray(tiers)) {
|
||||
return model;
|
||||
}
|
||||
|
||||
if (tiers.length !== 1) {
|
||||
return model;
|
||||
}
|
||||
|
||||
const contextOver200k = tiers.find((tier) => {
|
||||
if (tier === null || typeof tier !== "object" || Array.isArray(tier)) return false;
|
||||
const tierConfig = (tier as { tier?: unknown }).tier;
|
||||
if (tierConfig === null || typeof tierConfig !== "object" || Array.isArray(tierConfig)) return false;
|
||||
const type = (tierConfig as { type?: unknown }).type;
|
||||
const size = (tierConfig as { size?: unknown }).size;
|
||||
// context_over_200k is a legacy compatibility field. It intentionally
|
||||
// includes higher thresholds; cost.tiers carries the exact threshold.
|
||||
return (
|
||||
(type === undefined || type === "context") &&
|
||||
typeof size === "number" &&
|
||||
size >= 200_000
|
||||
);
|
||||
});
|
||||
|
||||
if (contextOver200k === undefined) {
|
||||
return model;
|
||||
}
|
||||
|
||||
const { tier: _tier, ...legacyCost } = contextOver200k as Record<string, unknown>;
|
||||
return {
|
||||
...model,
|
||||
cost: {
|
||||
...(cost as Record<string, unknown>),
|
||||
context_over_200k: legacyCost,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
+151
-97
@@ -21,110 +21,164 @@ const JsonValue: z.ZodType<JsonValue> = z.lazy(() =>
|
||||
]),
|
||||
);
|
||||
|
||||
const Cost = z.object({
|
||||
input: z.number().min(0, "Input price cannot be negative"),
|
||||
output: z.number().min(0, "Output price cannot be negative"),
|
||||
reasoning: z.number().min(0, "Input price cannot be negative").optional(),
|
||||
cache_read: z
|
||||
.number()
|
||||
.min(0, "Cache read price cannot be negative")
|
||||
const Cost = z
|
||||
.object({
|
||||
input: z.number().min(0, "Input price cannot be negative"),
|
||||
output: z.number().min(0, "Output price cannot be negative"),
|
||||
reasoning: z
|
||||
.number()
|
||||
.min(0, "Reasoning price cannot be negative")
|
||||
.optional(),
|
||||
cache_read: z
|
||||
.number()
|
||||
.min(0, "Cache read price cannot be negative")
|
||||
.optional(),
|
||||
cache_write: z
|
||||
.number()
|
||||
.min(0, "Cache write price cannot be negative")
|
||||
.optional(),
|
||||
input_audio: z
|
||||
.number()
|
||||
.min(0, "Audio input price cannot be negative")
|
||||
.optional(),
|
||||
output_audio: z
|
||||
.number()
|
||||
.min(0, "Audio output price cannot be negative")
|
||||
.optional(),
|
||||
});
|
||||
|
||||
const CostTier = Cost.extend({
|
||||
tier: z
|
||||
.object({
|
||||
type: z.literal("context").default("context"),
|
||||
size: z.number().int().min(0, "Context tier size cannot be negative"),
|
||||
})
|
||||
.strict(),
|
||||
}).strict();
|
||||
|
||||
const AuthoredCost = Cost.extend({
|
||||
context_over_200k: z.never().optional(),
|
||||
tiers: z.array(CostTier).optional(),
|
||||
});
|
||||
|
||||
const OutputCost = Cost.extend({
|
||||
context_over_200k: Cost.optional(),
|
||||
tiers: z.array(CostTier).optional(),
|
||||
});
|
||||
|
||||
const ModelBase = z.object({
|
||||
id: z.string(),
|
||||
name: z.string().min(1, "Model name cannot be empty"),
|
||||
family: ModelFamily.optional(),
|
||||
attachment: z.boolean(),
|
||||
reasoning: z.boolean(),
|
||||
tool_call: z.boolean(),
|
||||
interleaved: z
|
||||
.union([
|
||||
z.literal(true),
|
||||
z
|
||||
.object({
|
||||
field: z.enum(["reasoning_content", "reasoning_details"]),
|
||||
})
|
||||
.strict(),
|
||||
])
|
||||
.optional(),
|
||||
cache_write: z
|
||||
.number()
|
||||
.min(0, "Cache write price cannot be negative")
|
||||
structured_output: z.boolean().optional(),
|
||||
temperature: z.boolean().optional(),
|
||||
knowledge: z
|
||||
.string()
|
||||
.regex(/^\d{4}-\d{2}(-\d{2})?$/, {
|
||||
message: "Must be in YYYY-MM or YYYY-MM-DD format",
|
||||
})
|
||||
.optional(),
|
||||
input_audio: z
|
||||
.number()
|
||||
.min(0, "Audio input price cannot be negative")
|
||||
release_date: z.string().regex(/^\d{4}-\d{2}(-\d{2})?$/, {
|
||||
message: "Must be in YYYY-MM or YYYY-MM-DD format",
|
||||
}),
|
||||
last_updated: z.string().regex(/^\d{4}-\d{2}(-\d{2})?$/, {
|
||||
message: "Must be in YYYY-MM or YYYY-MM-DD format",
|
||||
}),
|
||||
modalities: z.object({
|
||||
input: z.array(z.enum(["text", "audio", "image", "video", "pdf"])),
|
||||
output: z.array(z.enum(["text", "audio", "image", "video", "pdf"])),
|
||||
}),
|
||||
open_weights: z.boolean(),
|
||||
limit: z.object({
|
||||
context: z.number().min(0, "Context window must be positive"),
|
||||
input: z.number().min(0, "Input tokens must be positive").optional(),
|
||||
output: z.number().min(0, "Output tokens must be positive"),
|
||||
}),
|
||||
status: z.enum(["alpha", "beta", "deprecated"]).optional(),
|
||||
experimental: z
|
||||
.object({
|
||||
modes: z
|
||||
.record(
|
||||
z.object({
|
||||
cost: Cost.optional(),
|
||||
provider: z
|
||||
.object({
|
||||
body: z.record(JsonValue).optional(),
|
||||
headers: z.record(z.string()).optional(),
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
)
|
||||
.optional(),
|
||||
})
|
||||
.optional(),
|
||||
output_audio: z
|
||||
.number()
|
||||
.min(0, "Audio output price cannot be negative")
|
||||
provider: z
|
||||
.object({
|
||||
npm: z.string().optional(),
|
||||
api: z.string().optional(),
|
||||
shape: z.enum(["responses", "completions"]).optional(),
|
||||
body: z.record(JsonValue).optional(),
|
||||
headers: z.record(z.string()).optional(),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
export const Model = z
|
||||
|
||||
function refineModel<T extends z.ZodTypeAny>(schema: T) {
|
||||
return schema
|
||||
.refine(
|
||||
(data) => {
|
||||
return !(data.reasoning === false && data.cost?.reasoning !== undefined);
|
||||
},
|
||||
{
|
||||
message: "Cannot set cost.reasoning when reasoning is false",
|
||||
path: ["cost", "reasoning"],
|
||||
},
|
||||
)
|
||||
.refine(
|
||||
(data) => {
|
||||
const tiers = data.cost?.tiers;
|
||||
if (tiers === undefined) return true;
|
||||
|
||||
const sizes = tiers.map((tier: { tier: { size: number } }) => tier.tier.size);
|
||||
return new Set(sizes).size === sizes.length;
|
||||
},
|
||||
{
|
||||
message: "Cost context tiers must not have duplicate sizes",
|
||||
path: ["cost", "tiers"],
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export const ModelShape = z
|
||||
.object({
|
||||
id: z.string(),
|
||||
name: z.string().min(1, "Model name cannot be empty"),
|
||||
family: ModelFamily.optional(),
|
||||
attachment: z.boolean(),
|
||||
reasoning: z.boolean(),
|
||||
tool_call: z.boolean(),
|
||||
interleaved: z
|
||||
.union([
|
||||
z.literal(true),
|
||||
z
|
||||
.object({
|
||||
field: z.enum(["reasoning_content", "reasoning_details"]),
|
||||
})
|
||||
.strict(),
|
||||
])
|
||||
.optional(),
|
||||
structured_output: z.boolean().optional(),
|
||||
temperature: z.boolean().optional(),
|
||||
knowledge: z
|
||||
.string()
|
||||
.regex(/^\d{4}-\d{2}(-\d{2})?$/, {
|
||||
message: "Must be in YYYY-MM or YYYY-MM-DD format",
|
||||
})
|
||||
.optional(),
|
||||
release_date: z.string().regex(/^\d{4}-\d{2}(-\d{2})?$/, {
|
||||
message: "Must be in YYYY-MM or YYYY-MM-DD format",
|
||||
}),
|
||||
last_updated: z.string().regex(/^\d{4}-\d{2}(-\d{2})?$/, {
|
||||
message: "Must be in YYYY-MM or YYYY-MM-DD format",
|
||||
}),
|
||||
modalities: z.object({
|
||||
input: z.array(z.enum(["text", "audio", "image", "video", "pdf"])),
|
||||
output: z.array(z.enum(["text", "audio", "image", "video", "pdf"])),
|
||||
}),
|
||||
open_weights: z.boolean(),
|
||||
cost: Cost.extend({
|
||||
context_over_200k: Cost.optional(),
|
||||
}).optional(),
|
||||
limit: z.object({
|
||||
context: z.number().min(0, "Context window must be positive"),
|
||||
input: z.number().min(0, "Input tokens must be positive").optional(),
|
||||
output: z.number().min(0, "Output tokens must be positive"),
|
||||
}),
|
||||
status: z.enum(["alpha", "beta", "deprecated"]).optional(),
|
||||
experimental: z
|
||||
.object({
|
||||
modes: z
|
||||
.record(
|
||||
z.object({
|
||||
cost: Cost.optional(),
|
||||
provider: z
|
||||
.object({
|
||||
body: z.record(JsonValue).optional(),
|
||||
headers: z.record(z.string()).optional(),
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
)
|
||||
.optional(),
|
||||
})
|
||||
.optional(),
|
||||
provider: z
|
||||
.object({
|
||||
npm: z.string().optional(),
|
||||
api: z.string().optional(),
|
||||
shape: z.enum(["responses", "completions"]).optional(),
|
||||
body: z.record(JsonValue).optional(),
|
||||
headers: z.record(z.string()).optional(),
|
||||
})
|
||||
.optional(),
|
||||
...ModelBase.shape,
|
||||
cost: OutputCost.optional(),
|
||||
})
|
||||
.strict()
|
||||
.refine(
|
||||
(data) => {
|
||||
return !(data.reasoning === false && data.cost?.reasoning !== undefined);
|
||||
},
|
||||
{
|
||||
message: "Cannot set cost.reasoning when reasoning is false",
|
||||
path: ["cost", "reasoning"],
|
||||
},
|
||||
);
|
||||
.strict();
|
||||
|
||||
export const AuthoredModelShape = z
|
||||
.object({
|
||||
...ModelBase.shape,
|
||||
cost: AuthoredCost.optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
export const Model = refineModel(ModelShape);
|
||||
|
||||
export const AuthoredModel = refineModel(AuthoredModelShape);
|
||||
|
||||
export type Model = z.infer<typeof Model>;
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@ output = 25.000
|
||||
cache_read = 0.500
|
||||
cache_write = 6.250
|
||||
|
||||
[cost.context_over_200k]
|
||||
[[cost.tiers]]
|
||||
tier = { size = 200_000 }
|
||||
input = 10.000
|
||||
output = 37.500
|
||||
cache_read = 1.000
|
||||
|
||||
@@ -16,7 +16,8 @@ output = 180.000
|
||||
cache_read = 0
|
||||
cache_write = 0
|
||||
|
||||
[cost.context_over_200k]
|
||||
[[cost.tiers]]
|
||||
tier = { size = 272_000 }
|
||||
input = 60.000
|
||||
output = 270.000
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@ output = 15.000
|
||||
cache_read = 0.250
|
||||
cache_write = 0
|
||||
|
||||
[cost.context_over_200k]
|
||||
[[cost.tiers]]
|
||||
tier = { size = 272_000 }
|
||||
input = 5.000
|
||||
output = 22.500
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
name = "Claude Opus 4.7 Thinking"
|
||||
family = "claude-opus"
|
||||
release_date = "2026-04-16"
|
||||
last_updated = "2026-04-16"
|
||||
attachment = true
|
||||
reasoning = true
|
||||
temperature = false
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
knowledge = "2026-01-31"
|
||||
open_weights = false
|
||||
|
||||
[cost]
|
||||
input = 5
|
||||
output = 25
|
||||
cache_read = 0.5
|
||||
cache_write = 6.25
|
||||
|
||||
[limit]
|
||||
context = 200_000
|
||||
output = 32_000
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image"]
|
||||
output = ["text"]
|
||||
@@ -15,7 +15,8 @@ output = 15.00
|
||||
cache_read = 0.30
|
||||
cache_write = 3.75
|
||||
|
||||
[cost.context_over_200k]
|
||||
[[cost.tiers]]
|
||||
tier = { size = 200_000 }
|
||||
input = 6.00
|
||||
output = 22.50
|
||||
cache_read = 0.60
|
||||
|
||||
@@ -15,7 +15,8 @@ output = 15.00
|
||||
cache_read = 0.30
|
||||
cache_write = 3.75
|
||||
|
||||
[cost.context_over_200k]
|
||||
[[cost.tiers]]
|
||||
tier = { size = 200_000 }
|
||||
input = 6.00
|
||||
output = 22.50
|
||||
cache_read = 0.60
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
name = "Coding-GLM-5-Free"
|
||||
family = "glm"
|
||||
release_date = "2026-02-11"
|
||||
last_updated = "2026-02-11"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
open_weights = false
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
|
||||
[cost]
|
||||
input = 0.0
|
||||
output = 0.0
|
||||
|
||||
[limit]
|
||||
context = 204800
|
||||
output = 131072
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
+9
-8
@@ -1,24 +1,25 @@
|
||||
name = "GLM5"
|
||||
name = "Coding GLM 5.1 (free)"
|
||||
family = "glm"
|
||||
release_date = "2026-02-12"
|
||||
last_updated = "2026-02-12"
|
||||
release_date = "2026-04-11"
|
||||
last_updated = "2026-04-11"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
open_weights = false
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
|
||||
[cost]
|
||||
input = 0.0
|
||||
output = 0.0
|
||||
input = 0
|
||||
output = 0
|
||||
cache_read = 0
|
||||
|
||||
[limit]
|
||||
context = 202752
|
||||
output = 131000
|
||||
context = 204_800
|
||||
output = 128_000
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
+7
-9
@@ -1,23 +1,21 @@
|
||||
name = "MiniMax-M2.1"
|
||||
name = "Coding MiniMax M2.7 Highspeed"
|
||||
family = "minimax"
|
||||
release_date = "2025-12-23"
|
||||
last_updated = "2025-12-23"
|
||||
release_date = "2026-03-18"
|
||||
last_updated = "2026-03-18"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_details"
|
||||
|
||||
[cost]
|
||||
input = 0.288
|
||||
output = 1.152
|
||||
input = 0.2
|
||||
output = 0.2
|
||||
|
||||
[limit]
|
||||
context = 204_800
|
||||
output = 192_000
|
||||
output = 13_100
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
+7
-6
@@ -1,20 +1,21 @@
|
||||
name = "MiniMax-M2.1"
|
||||
name = "Coding MiniMax M2.7"
|
||||
family = "minimax"
|
||||
release_date = "2025-12-23"
|
||||
last_updated = "2025-12-23"
|
||||
release_date = "2026-03-18"
|
||||
last_updated = "2026-03-18"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.0
|
||||
output = 0.0
|
||||
input = 0.2
|
||||
output = 0.2
|
||||
|
||||
[limit]
|
||||
context = 204_800
|
||||
output = 131_072
|
||||
output = 13_100
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
name = "Gemini 3.1 Flash Lite Preview"
|
||||
name = "Gemini 3.1 Flash Lite"
|
||||
family = "gemini-flash-lite"
|
||||
release_date = "2026-03-03"
|
||||
last_updated = "2026-03-03"
|
||||
@@ -0,0 +1,30 @@
|
||||
name = "Gemini 3.1 Pro Preview Custom Tools"
|
||||
family = "gemini-pro"
|
||||
release_date = "2026-02-19"
|
||||
last_updated = "2026-02-19"
|
||||
attachment = true
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
knowledge = "2025-01"
|
||||
open_weights = false
|
||||
|
||||
[cost]
|
||||
input = 2
|
||||
output = 12
|
||||
cache_read = 0.2
|
||||
|
||||
[[cost.tiers]]
|
||||
tier = { size = 200_000 }
|
||||
input = 4
|
||||
output = 18
|
||||
cache_read = 0.4
|
||||
|
||||
[limit]
|
||||
context = 1_048_576
|
||||
output = 65_536
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image", "audio", "video", "pdf"]
|
||||
output = ["text"]
|
||||
@@ -1,25 +0,0 @@
|
||||
name = "GLM-5"
|
||||
family = "glm"
|
||||
release_date = "2026-02-11"
|
||||
last_updated = "2026-02-11"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
open_weights = true
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
|
||||
[cost]
|
||||
input = 0.88
|
||||
output = 2.816
|
||||
cache_read = 0.176
|
||||
|
||||
[limit]
|
||||
context = 202_752
|
||||
output = 0
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
@@ -0,0 +1,26 @@
|
||||
name = "GLM 5 Vision Turbo"
|
||||
family = "glm"
|
||||
release_date = "2026-05-09"
|
||||
last_updated = "2026-05-09"
|
||||
attachment = true
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = false
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
|
||||
[cost]
|
||||
input = 0.7042
|
||||
output = 3.09848
|
||||
cache_read = 0.169008
|
||||
|
||||
[limit]
|
||||
context = 200_000
|
||||
output = 128_000
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image", "video"]
|
||||
output = ["text"]
|
||||
@@ -0,0 +1,29 @@
|
||||
name = "Grok 4.3"
|
||||
family = "grok"
|
||||
release_date = "2026-05-01"
|
||||
last_updated = "2026-05-01"
|
||||
attachment = true
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = false
|
||||
|
||||
[cost]
|
||||
input = 1.25
|
||||
output = 2.5
|
||||
cache_read = 0.2
|
||||
|
||||
[[cost.tiers]]
|
||||
tier = { size = 200_000 }
|
||||
input = 2.5
|
||||
output = 5.0
|
||||
cache_read = 0.4
|
||||
|
||||
[limit]
|
||||
context = 1_000_000
|
||||
output = 1_000_000
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image"]
|
||||
output = ["text"]
|
||||
@@ -1,24 +0,0 @@
|
||||
name = "Qwen3 Coder Plus"
|
||||
family = "qwen"
|
||||
release_date = "2025-07-23"
|
||||
last_updated = "2025-07-23"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = true
|
||||
knowledge = "2025-04"
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.137
|
||||
output = 0.548
|
||||
cache_read = 0.137
|
||||
|
||||
[limit]
|
||||
context = 2_000_000
|
||||
output = 64_000
|
||||
input = 262_144
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
@@ -1,23 +0,0 @@
|
||||
name = "Qwen3 Max"
|
||||
family = "qwen"
|
||||
release_date = "2025-09-23"
|
||||
last_updated = "2025-09-23"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = true
|
||||
knowledge = "2025-04"
|
||||
open_weights = false
|
||||
|
||||
[cost]
|
||||
input = 0.34246
|
||||
output = 1.36984
|
||||
cache_read = 0.34246
|
||||
|
||||
[limit]
|
||||
context = 252_000
|
||||
output = 32_000
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
@@ -1,11 +1,12 @@
|
||||
name = "Qwen3.6 Plus"
|
||||
name = "Qwen3.6 Flash"
|
||||
family = "qwen"
|
||||
release_date = "2026-04-02"
|
||||
last_updated = "2026-04-02"
|
||||
attachment = false
|
||||
attachment = true
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
knowledge = "2025-04"
|
||||
open_weights = false
|
||||
|
||||
@@ -16,8 +17,8 @@ cache_read = 0.0169
|
||||
cache_write = 0.21125
|
||||
|
||||
[limit]
|
||||
context = 1_000_000
|
||||
output = 65_536
|
||||
context = 991_000
|
||||
output = 64_000
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image", "video"]
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
name = "Qwen3.6 Max Preview"
|
||||
family = "qwen"
|
||||
release_date = "2026-05-09"
|
||||
last_updated = "2026-05-09"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
knowledge = "2025-04"
|
||||
open_weights = false
|
||||
|
||||
[cost]
|
||||
input = 1.268
|
||||
output = 7.608
|
||||
cache_read = 0.1268
|
||||
cache_write = 1.585
|
||||
|
||||
[limit]
|
||||
context = 240_000
|
||||
output = 64_000
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
+9
-8
@@ -1,19 +1,20 @@
|
||||
name = "Qwen3.5 Plus"
|
||||
name = "Qwen3.6 Plus"
|
||||
family = "qwen"
|
||||
release_date = "2026-02-16"
|
||||
last_updated = "2026-02-16"
|
||||
attachment = false
|
||||
release_date = "2026-05-09"
|
||||
last_updated = "2026-05-09"
|
||||
attachment = true
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
knowledge = "2025-04"
|
||||
open_weights = false
|
||||
|
||||
[cost]
|
||||
input = 0.1096
|
||||
output = 0.6576
|
||||
cache_read = 0.01096
|
||||
cache_write = 0.137
|
||||
input = 0.282
|
||||
output = 1.692
|
||||
cache_read = 0.0282
|
||||
cache_write = 0.3525
|
||||
|
||||
[limit]
|
||||
context = 991_000
|
||||
@@ -10,10 +10,17 @@ tool_call = true
|
||||
open_weights = false
|
||||
|
||||
[cost]
|
||||
input = 0.276
|
||||
output = 1.651
|
||||
cache_read = 0.028
|
||||
cache_write = 0.344
|
||||
input = 0.50
|
||||
output = 3.00
|
||||
cache_read = 0.05
|
||||
cache_write = 0.625
|
||||
|
||||
[[cost.tiers]]
|
||||
tier = { size = 256_000 }
|
||||
input = 2.00
|
||||
output = 6.00
|
||||
cache_read = 0.20
|
||||
cache_write = 2.50
|
||||
|
||||
[limit]
|
||||
context = 1_000_000
|
||||
|
||||
@@ -10,10 +10,17 @@ tool_call = true
|
||||
open_weights = false
|
||||
|
||||
[cost]
|
||||
input = 0.276
|
||||
output = 1.651
|
||||
cache_read = 0.028
|
||||
cache_write = 0.344
|
||||
input = 0.50
|
||||
output = 3.00
|
||||
cache_read = 0.05
|
||||
cache_write = 0.625
|
||||
|
||||
[[cost.tiers]]
|
||||
tier = { size = 256_000 }
|
||||
input = 2.00
|
||||
output = 6.00
|
||||
cache_read = 0.20
|
||||
cache_write = 2.50
|
||||
|
||||
[limit]
|
||||
context = 1_000_000
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
name = "Nova Premier"
|
||||
family = "nova"
|
||||
release_date = "2024-12-03"
|
||||
last_updated = "2024-12-03"
|
||||
attachment = true
|
||||
reasoning = true
|
||||
temperature = true
|
||||
knowledge = "2024-10"
|
||||
tool_call = true
|
||||
open_weights = false
|
||||
|
||||
[cost]
|
||||
input = 2.50
|
||||
output = 12.50
|
||||
|
||||
[limit]
|
||||
context = 1_000_000
|
||||
output = 16_384
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image", "video"]
|
||||
output = ["text"]
|
||||
@@ -1,2 +0,0 @@
|
||||
[extends]
|
||||
from = "anthropic/claude-3-5-haiku-20241022"
|
||||
@@ -1,2 +0,0 @@
|
||||
[extends]
|
||||
from = "anthropic/claude-3-5-sonnet-20240620"
|
||||
@@ -1,24 +0,0 @@
|
||||
name = "Claude Sonnet 3.5 v2"
|
||||
family = "claude-sonnet"
|
||||
release_date = "2024-10-22"
|
||||
last_updated = "2024-10-22"
|
||||
attachment = true
|
||||
reasoning = false
|
||||
temperature = true
|
||||
knowledge = "2024-04"
|
||||
tool_call = true
|
||||
open_weights = false
|
||||
|
||||
[cost]
|
||||
input = 3.00
|
||||
output = 15.00
|
||||
cache_read = 0.30
|
||||
cache_write = 3.75
|
||||
|
||||
[limit]
|
||||
context = 200_000
|
||||
output = 8_192
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image", "pdf"]
|
||||
output = ["text"]
|
||||
@@ -1,24 +0,0 @@
|
||||
name = "Claude Sonnet 3.7"
|
||||
family = "claude-sonnet"
|
||||
release_date = "2025-02-19"
|
||||
last_updated = "2025-02-19"
|
||||
attachment = true
|
||||
reasoning = false
|
||||
temperature = true
|
||||
knowledge = "2024-04"
|
||||
tool_call = true
|
||||
open_weights = false
|
||||
|
||||
[cost]
|
||||
input = 3.00
|
||||
output = 15.00
|
||||
cache_read = 0.30
|
||||
cache_write = 3.75
|
||||
|
||||
[limit]
|
||||
context = 200_000
|
||||
output = 8_192
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image", "pdf"]
|
||||
output = ["text"]
|
||||
@@ -1,22 +0,0 @@
|
||||
name = "Claude Haiku 3"
|
||||
family = "claude-haiku"
|
||||
release_date = "2024-03-13"
|
||||
last_updated = "2024-03-13"
|
||||
attachment = true
|
||||
reasoning = false
|
||||
temperature = true
|
||||
knowledge = "2024-02"
|
||||
tool_call = true
|
||||
open_weights = false
|
||||
|
||||
[cost]
|
||||
input = 0.25
|
||||
output = 1.25
|
||||
|
||||
[limit]
|
||||
context = 200_000
|
||||
output = 4_096
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image", "pdf"]
|
||||
output = ["text"]
|
||||
@@ -1,2 +0,0 @@
|
||||
[extends]
|
||||
from = "anthropic/claude-opus-4-20250514"
|
||||
@@ -1,2 +0,0 @@
|
||||
[extends]
|
||||
from = "anthropic/claude-sonnet-4-20250514"
|
||||
@@ -0,0 +1,4 @@
|
||||
name = "Claude Haiku 4.5 (AU)"
|
||||
|
||||
[extends]
|
||||
from = "anthropic/claude-haiku-4-5-20251001"
|
||||
@@ -0,0 +1,4 @@
|
||||
name = "Claude Sonnet 4.5 (AU)"
|
||||
|
||||
[extends]
|
||||
from = "anthropic/claude-sonnet-4-5"
|
||||
@@ -1,4 +0,0 @@
|
||||
name = "Claude Sonnet 4 (EU)"
|
||||
|
||||
[extends]
|
||||
from = "anthropic/claude-sonnet-4-20250514"
|
||||
@@ -1,4 +0,0 @@
|
||||
name = "Claude Sonnet 4 (Global)"
|
||||
|
||||
[extends]
|
||||
from = "anthropic/claude-sonnet-4-20250514"
|
||||
@@ -0,0 +1,4 @@
|
||||
name = "Claude Opus 4.7 (JP)"
|
||||
|
||||
[extends]
|
||||
from = "anthropic/claude-opus-4-7"
|
||||
@@ -0,0 +1,4 @@
|
||||
name = "Claude Sonnet 4.5 (JP)"
|
||||
|
||||
[extends]
|
||||
from = "anthropic/claude-sonnet-4-5"
|
||||
@@ -0,0 +1,4 @@
|
||||
name = "Claude Sonnet 4.6 (JP)"
|
||||
|
||||
[extends]
|
||||
from = "anthropic/claude-sonnet-4-6"
|
||||
@@ -1,4 +0,0 @@
|
||||
name = "Claude Opus 4 (US)"
|
||||
|
||||
[extends]
|
||||
from = "anthropic/claude-opus-4-20250514"
|
||||
@@ -1,4 +0,0 @@
|
||||
name = "Claude Sonnet 4 (US)"
|
||||
|
||||
[extends]
|
||||
from = "anthropic/claude-sonnet-4-20250514"
|
||||
@@ -0,0 +1,4 @@
|
||||
name = "DeepSeek-R1 (US)"
|
||||
|
||||
[extends]
|
||||
from = "amazon-bedrock/deepseek.r1-v1:0"
|
||||
@@ -0,0 +1,4 @@
|
||||
name = "Llama 4 Maverick 17B Instruct (US)"
|
||||
|
||||
[extends]
|
||||
from = "amazon-bedrock/meta.llama4-maverick-17b-instruct-v1:0"
|
||||
@@ -0,0 +1,4 @@
|
||||
name = "Llama 4 Scout 17B Instruct (US)"
|
||||
|
||||
[extends]
|
||||
from = "amazon-bedrock/meta.llama4-scout-17b-instruct-v1:0"
|
||||
@@ -15,7 +15,8 @@ output = 25.00
|
||||
cache_read = 0.50
|
||||
cache_write = 6.25
|
||||
|
||||
[cost.context_over_200k]
|
||||
[[cost.tiers]]
|
||||
tier = { size = 200_000 }
|
||||
input = 10.00
|
||||
output = 37.50
|
||||
cache_read = 1.00
|
||||
|
||||
@@ -15,7 +15,8 @@ output = 25.00
|
||||
cache_read = 0.50
|
||||
cache_write = 6.25
|
||||
|
||||
[cost.context_over_200k]
|
||||
[[cost.tiers]]
|
||||
tier = { size = 200_000 }
|
||||
input = 10.00
|
||||
output = 37.50
|
||||
cache_read = 1.00
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
name = "MiniMax M2.1 TEE"
|
||||
family = "minimax"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-27"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.27
|
||||
output = 1.12
|
||||
|
||||
[limit]
|
||||
context = 196_608
|
||||
output = 65_536
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "MiniMax M2.5 TEE"
|
||||
family = "minimax"
|
||||
release_date = "2026-02-15"
|
||||
last_updated = "2026-02-15"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
@@ -10,9 +12,9 @@ structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.30
|
||||
output = 1.10
|
||||
cache_read = 0.15
|
||||
input = 0.15
|
||||
output = 1.2
|
||||
cache_read = 0.075
|
||||
|
||||
[limit]
|
||||
context = 196_608
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "DeepHermes 3 Mistral 24B Preview"
|
||||
family = "nousresearch"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
@@ -10,8 +12,9 @@ structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.02
|
||||
output = 0.10
|
||||
input = 0.0245
|
||||
output = 0.0978
|
||||
cache_read = 0.01225
|
||||
|
||||
[limit]
|
||||
context = 32_768
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Hermes 4 14B"
|
||||
family = "nousresearch"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
@@ -10,8 +12,9 @@ structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.01
|
||||
output = 0.05
|
||||
input = 0.0136
|
||||
output = 0.0543
|
||||
cache_read = 0.0068
|
||||
|
||||
[limit]
|
||||
context = 40_960
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
name = "Hermes 4 405B FP8 TEE"
|
||||
family = "nousresearch"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.30
|
||||
output = 1.20
|
||||
|
||||
[limit]
|
||||
context = 131_072
|
||||
output = 65_536
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
@@ -1,22 +0,0 @@
|
||||
name = "InternVL3 78B TEE"
|
||||
family = "opengvlab"
|
||||
release_date = "2025-01-06"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = false
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.10
|
||||
output = 0.39
|
||||
|
||||
[limit]
|
||||
context = 32_768
|
||||
output = 32_768
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image"]
|
||||
output = ["text"]
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Qwen2.5 72B Instruct"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
@@ -10,8 +12,9 @@ structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.13
|
||||
output = 0.52
|
||||
input = 0.2989
|
||||
output = 1.1957
|
||||
cache_read = 0.14945
|
||||
|
||||
[limit]
|
||||
context = 32_768
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Qwen2.5 Coder 32B Instruct"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
@@ -10,8 +12,9 @@ structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.03
|
||||
output = 0.11
|
||||
input = 0.0272
|
||||
output = 0.1087
|
||||
cache_read = 0.0136
|
||||
|
||||
[limit]
|
||||
context = 32_768
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Qwen2.5 VL 32B Instruct"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
last_updated = "2026-04-25"
|
||||
attachment = true
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = false
|
||||
@@ -10,8 +12,9 @@ structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.05
|
||||
output = 0.22
|
||||
input = 0.0543
|
||||
output = 0.2174
|
||||
cache_read = 0.02715
|
||||
|
||||
[limit]
|
||||
context = 16_384
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
name = "Qwen2.5 VL 72B Instruct TEE"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = false
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.15
|
||||
output = 0.60
|
||||
|
||||
[limit]
|
||||
context = 32_768
|
||||
output = 32_768
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image"]
|
||||
output = ["text"]
|
||||
@@ -1,25 +0,0 @@
|
||||
name = "Qwen3 14B"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.05
|
||||
output = 0.22
|
||||
|
||||
[limit]
|
||||
context = 40_960
|
||||
output = 40_960
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Qwen3 235B A22B Instruct 2507 TEE"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
@@ -10,9 +12,9 @@ structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.08
|
||||
output = 0.55
|
||||
cache_read = 0.04
|
||||
input = 0.1
|
||||
output = 0.6
|
||||
cache_read = 0.05
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Qwen3 235B A22B Thinking 2507"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
@@ -11,7 +13,8 @@ open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.11
|
||||
output = 0.60
|
||||
output = 0.6
|
||||
cache_read = 0.055
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
name = "Qwen3 235B A22B"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.30
|
||||
output = 1.20
|
||||
|
||||
[limit]
|
||||
context = 40_960
|
||||
output = 40_960
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
@@ -1,22 +0,0 @@
|
||||
name = "Qwen3 30B A3B Instruct 2507"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.08
|
||||
output = 0.33
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
output = 262_144
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Qwen3 30B A3B"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
@@ -12,6 +14,7 @@ open_weights = true
|
||||
[cost]
|
||||
input = 0.06
|
||||
output = 0.22
|
||||
cache_read = 0.03
|
||||
|
||||
[limit]
|
||||
context = 40_960
|
||||
|
||||
+5
-6
@@ -1,7 +1,9 @@
|
||||
name = "Qwen3 32B"
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Qwen3 32B TEE"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
release_date = "2026-04-25"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
@@ -21,6 +23,3 @@ output = 40_960
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
@@ -1,23 +0,0 @@
|
||||
name = "Qwen3 Coder 480B A35B Instruct FP8 TEE"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.22
|
||||
output = 0.95
|
||||
cache_read = 0.11
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
output = 262_144
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
@@ -0,0 +1,25 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Qwen3 Coder Next TEE"
|
||||
family = "qwen"
|
||||
release_date = "2026-04-25"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.12
|
||||
output = 0.75
|
||||
cache_read = 0.06
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
output = 65_536
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
@@ -1,22 +0,0 @@
|
||||
name = "Qwen3 Coder Next"
|
||||
family = "qwen"
|
||||
release_date = "2026-02-05"
|
||||
last_updated = "2026-02-05"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.07
|
||||
output = 0.30
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
output = 65_536
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Qwen3 Next 80B A3B Instruct"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
@@ -10,8 +12,9 @@ structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.10
|
||||
output = 0.80
|
||||
input = 0.1
|
||||
output = 0.8
|
||||
cache_read = 0.05
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
name = "Qwen3 VL 235B A22B Instruct"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.30
|
||||
output = 1.20
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
output = 262_144
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image"]
|
||||
output = ["text"]
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Qwen3.5 397B A17B TEE"
|
||||
family = "qwen"
|
||||
release_date = "2026-02-18"
|
||||
last_updated = "2026-02-18"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = true
|
||||
reasoning = true
|
||||
temperature = true
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Qwen3.6 27B TEE"
|
||||
family = "qwen"
|
||||
release_date = "2026-04-25"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = true
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.195
|
||||
output = 1.56
|
||||
cache_read = 0.0975
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
output = 65_536
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image"]
|
||||
output = ["text"]
|
||||
@@ -1,17 +1,18 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Qwen3Guard Gen 0.6B"
|
||||
family = "qwen"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = false
|
||||
structured_output = false
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.01
|
||||
output = 0.01
|
||||
output = 0.0109
|
||||
cache_read = 0.005
|
||||
|
||||
[limit]
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "MiMo V2 Flash TEE"
|
||||
family = "mimo"
|
||||
release_date = "2026-04-25"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.09
|
||||
output = 0.29
|
||||
cache_read = 0.045
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
output = 65_536
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
@@ -1,22 +0,0 @@
|
||||
name = "MiMo V2 Flash"
|
||||
family = "mimo"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-27"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = false
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.09
|
||||
output = 0.29
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
output = 32_000
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
@@ -1,23 +0,0 @@
|
||||
name = "Mistral Small 3.1 24B Instruct 2503"
|
||||
family = "chutesai"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.03
|
||||
output = 0.11
|
||||
cache_read = 0.015
|
||||
|
||||
[limit]
|
||||
context = 131_072
|
||||
output = 131_072
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image"]
|
||||
output = ["text"]
|
||||
@@ -1,22 +0,0 @@
|
||||
name = "Mistral Small 3.2 24B Instruct 2506"
|
||||
family = "chutesai"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.06
|
||||
output = 0.18
|
||||
|
||||
[limit]
|
||||
context = 131_072
|
||||
output = 131_072
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image"]
|
||||
output = ["text"]
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "DeepSeek R1 0528 TEE"
|
||||
family = "deepseek-thinking"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
@@ -10,8 +12,9 @@ structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.40
|
||||
output = 1.75
|
||||
input = 0.45
|
||||
output = 2.15
|
||||
cache_read = 0.225
|
||||
|
||||
[limit]
|
||||
context = 163_840
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "DeepSeek R1 Distill Llama 70B"
|
||||
family = "deepseek-thinking"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
@@ -10,8 +12,9 @@ structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.03
|
||||
output = 0.11
|
||||
input = 0.0272
|
||||
output = 0.1087
|
||||
cache_read = 0.0136
|
||||
|
||||
[limit]
|
||||
context = 131_072
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
name = "DeepSeek R1 TEE"
|
||||
family = "deepseek-thinking"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = false
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.30
|
||||
output = 1.20
|
||||
|
||||
[limit]
|
||||
context = 163_840
|
||||
output = 163_840
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "DeepSeek V3 0324 TEE"
|
||||
family = "deepseek"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
@@ -10,9 +12,9 @@ structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.19
|
||||
output = 0.87
|
||||
cache_read = 0.095
|
||||
input = 0.25
|
||||
output = 1
|
||||
cache_read = 0.125
|
||||
|
||||
[limit]
|
||||
context = 163_840
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "DeepSeek V3.1 TEE"
|
||||
family = "deepseek"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
@@ -10,8 +12,9 @@ structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.20
|
||||
output = 0.80
|
||||
input = 0.27
|
||||
output = 1
|
||||
cache_read = 0.135
|
||||
|
||||
[limit]
|
||||
context = 163_840
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
name = "DeepSeek V3.1 Terminus TEE"
|
||||
family = "deepseek"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.23
|
||||
output = 0.90
|
||||
|
||||
[limit]
|
||||
context = 163_840
|
||||
output = 65_536
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
@@ -1,25 +0,0 @@
|
||||
name = "DeepSeek V3.2 Speciale TEE"
|
||||
family = "deepseek"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = false
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.27
|
||||
output = 0.41
|
||||
|
||||
[limit]
|
||||
context = 163_840
|
||||
output = 65_536
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "DeepSeek V3.2 TEE"
|
||||
family = "deepseek"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
name = "DeepSeek V3"
|
||||
family = "deepseek"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = false
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.30
|
||||
output = 1.20
|
||||
|
||||
[limit]
|
||||
context = 163_840
|
||||
output = 163_840
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
@@ -0,0 +1,25 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "gemma 4 31B turbo TEE"
|
||||
family = "gemma"
|
||||
release_date = "2026-04-25"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = true
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.13
|
||||
output = 0.38
|
||||
cache_read = 0.065
|
||||
|
||||
[limit]
|
||||
context = 131_072
|
||||
output = 65_536
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image"]
|
||||
output = ["text"]
|
||||
@@ -1,22 +0,0 @@
|
||||
name = "MiroThinker V1.5 235B"
|
||||
release_date = "2026-01-10"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = false
|
||||
structured_output = false
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.30
|
||||
output = 1.20
|
||||
cache_read = 0.15
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
output = 8_192
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
@@ -1,23 +0,0 @@
|
||||
name = "Kimi K2 Instruct 0905"
|
||||
family = "kimi"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.39
|
||||
output = 1.90
|
||||
cache_read = 0.195
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
output = 262_144
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
@@ -1,21 +1,21 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Kimi K2.5 TEE"
|
||||
family = "kimi"
|
||||
release_date = "2026-01-27"
|
||||
last_updated = "2026-01-27"
|
||||
attachment = false
|
||||
last_updated = "2026-04-25"
|
||||
attachment = true
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
knowledge = "2024-10"
|
||||
open_weights = true
|
||||
structured_output = true
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
open_weights = true
|
||||
knowledge = "2024-10"
|
||||
|
||||
[cost]
|
||||
input = 0.60
|
||||
output = 3.00
|
||||
input = 0.44
|
||||
output = 2
|
||||
cache_read = 0.22
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
@@ -24,3 +24,6 @@ output = 65_535
|
||||
[modalities]
|
||||
input = ["text", "image", "video"]
|
||||
output = ["text"]
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
|
||||
@@ -1,26 +1,29 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "Kimi K2.6 TEE"
|
||||
family = "kimi"
|
||||
release_date = "2026-04-20"
|
||||
last_updated = "2026-04-23"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = true
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
knowledge = "2025-12"
|
||||
open_weights = true
|
||||
structured_output = true
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
open_weights = true
|
||||
knowledge = "2025-12"
|
||||
|
||||
[cost]
|
||||
input = 0.44
|
||||
output = 2.00
|
||||
input = 0.95
|
||||
output = 4
|
||||
cache_read = 0.475
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
output = 262_144
|
||||
output = 65_535
|
||||
|
||||
[modalities]
|
||||
input = ["text", "image", "video"]
|
||||
output = ["text"]
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
name = "NVIDIA Nemotron 3 Nano 30B A3B BF16"
|
||||
family = "nemotron"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.06
|
||||
output = 0.24
|
||||
|
||||
[limit]
|
||||
context = 262_144
|
||||
output = 262_144
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
@@ -1,7 +1,9 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "gpt oss 120b TEE"
|
||||
family = "gpt-oss"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
@@ -10,8 +12,9 @@ structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.04
|
||||
output = 0.18
|
||||
input = 0.09
|
||||
output = 0.36
|
||||
cache_read = 0.045
|
||||
|
||||
[limit]
|
||||
context = 131_072
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "dots.ocr"
|
||||
family = "rednote"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
last_updated = "2026-04-25"
|
||||
attachment = true
|
||||
reasoning = false
|
||||
temperature = true
|
||||
tool_call = false
|
||||
@@ -11,7 +13,7 @@ open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.01
|
||||
output = 0.01
|
||||
output = 0.0109
|
||||
cache_read = 0.005
|
||||
|
||||
[limit]
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
name = "DeepSeek R1T Chimera"
|
||||
family = "tngtech"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = false
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.30
|
||||
output = 1.20
|
||||
|
||||
[limit]
|
||||
context = 163_840
|
||||
output = 163_840
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
@@ -0,0 +1,25 @@
|
||||
# Auto-generated by generate-chutes.ts — do not edit pricing, limits, or capabilities.
|
||||
# Manual overrides preserved on re-run: name, family, knowledge, interleaved, status
|
||||
name = "DeepSeek TNG R1T2 Chimera TEE"
|
||||
family = "deepseek"
|
||||
release_date = "2026-04-25"
|
||||
last_updated = "2026-04-25"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.3
|
||||
output = 1.1
|
||||
cache_read = 0.15
|
||||
|
||||
[limit]
|
||||
context = 163_840
|
||||
output = 163_840
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
@@ -1,25 +0,0 @@
|
||||
name = "DeepSeek TNG R1T2 Chimera"
|
||||
family = "tngtech"
|
||||
release_date = "2025-12-29"
|
||||
last_updated = "2026-01-10"
|
||||
attachment = false
|
||||
reasoning = true
|
||||
temperature = true
|
||||
tool_call = true
|
||||
structured_output = true
|
||||
open_weights = true
|
||||
|
||||
[cost]
|
||||
input = 0.25
|
||||
output = 0.85
|
||||
|
||||
[limit]
|
||||
context = 163_840
|
||||
output = 163_840
|
||||
|
||||
[modalities]
|
||||
input = ["text"]
|
||||
output = ["text"]
|
||||
|
||||
[interleaved]
|
||||
field = "reasoning_content"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user