Skip to content
Closed
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"vercel:generate": "bun ./packages/core/script/sync-models.ts vercel",
"wandb:generate": "bun ./packages/core/script/sync-models.ts wandb",
"digitalocean:sync": "bun ./packages/core/script/sync-models.ts digitalocean",
"ambient:generate": "bun ./packages/core/script/generate-ambient.ts",
"ambient:sync": "bun ./packages/core/script/sync-models.ts ambient",
"models:sync": "bun ./packages/core/script/sync-models.ts",
"sync:models": "bun ./packages/core/script/sync-models.ts"
},
Expand Down
169 changes: 0 additions & 169 deletions packages/core/script/generate-ambient.ts

This file was deleted.

5 changes: 4 additions & 1 deletion packages/core/src/sync/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { mergeDeep } from "remeda";
import { z } from "zod";

import { AuthoredModel, AuthoredModelShape, ModelMetadata } from "../schema.js";
import { ambient } from "./providers/ambient.js";
import { anthropic } from "./providers/anthropic.js";
import { baseten } from "./providers/baseten.js";
import { chutes } from "./providers/chutes.js";
Expand Down Expand Up @@ -92,6 +93,7 @@ export interface SyncResult {
}

export const providers: {
ambient: SyncProvider<any>;
anthropic: SyncProvider<any>;
baseten: SyncProvider<any>;
chutes: SyncProvider<any>;
Expand All @@ -113,6 +115,7 @@ export const providers: {
wandb: SyncProvider<any>;
xai: SyncProvider<any>;
} = {
ambient,
anthropic,
baseten,
chutes,
Expand All @@ -138,7 +141,7 @@ export const providers: {
export const groups = {
aggregators: ["crossmodel", "empiriolabs", "huggingface", "kilo", "llmgateway", "openrouter", "vercel"],
cloudflare: ["cloudflare-workers-ai"],
direct: ["anthropic", "baseten", "chutes", "deepinfra", "digitalocean", "google", "openai", "ovhcloud", "pioneer", "venice", "wandb", "xai"],
direct: ["ambient", "anthropic", "baseten", "chutes", "deepinfra", "digitalocean", "google", "openai", "ovhcloud", "pioneer", "venice", "wandb", "xai"],
} as const;

type ProviderID = keyof typeof providers;
Expand Down
114 changes: 114 additions & 0 deletions packages/core/src/sync/providers/ambient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { z } from "zod";

import type { SyncProvider } from "../index.js";
import { buildOpenRouterModel, type OpenRouterModel } from "./openrouter.js";

const API_ENDPOINT = "https://api.ambient.xyz/v1/models";

export const AmbientModel = z.object({
id: z.string().min(1),
name: z.string().min(1),
created: z.number(),
hugging_face_id: z.string().nullable().optional(),
context_length: z.number(),
max_output_length: z.number(),
input_modalities: z.array(z.string()),
output_modalities: z.array(z.string()),
pricing: z.object({
prompt: z.string(),
completion: z.string(),
input_cache_read: z.string().optional(),
input_cache_write: z.string().optional(),
}).passthrough(),
supported_features: z.array(z.string()).default([]),
supported_sampling_parameters: z.array(z.string()).default([]),
openrouter: z.object({ slug: z.string() }).nullable().optional(),
is_ready: z.boolean().default(false),
}).passthrough();

export const AmbientResponse = z.object({
object: z.literal("list"),
data: z.array(AmbientModel),
}).passthrough();

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

function toOpenRouterShape(model: AmbientModel): OpenRouterModel {
return {
id: model.openrouter?.slug ?? model.id,
name: model.name,
created: model.created,
hugging_face_id: model.hugging_face_id ?? null,
knowledge_cutoff: null,
context_length: model.context_length,
architecture: {
input_modalities: model.input_modalities,
output_modalities: model.output_modalities,
},
pricing: {
prompt: model.pricing.prompt,
completion: model.pricing.completion,
input_cache_read: model.pricing.input_cache_read,
input_cache_write: model.pricing.input_cache_write,
},
top_provider: {
context_length: model.context_length,
max_completion_tokens: model.max_output_length,
},
supported_parameters: [...model.supported_features, ...model.supported_sampling_parameters],
};
}

export const ambient = {
id: "ambient",
name: "Ambient",
modelsDir: "providers/ambient/models",
deleteMissing: false,
sourceID(model) {
return model.id;
},
skippedNotice(ids) {
if (ids.length === 0) return [];
return [
`${ids.length} Ambient models were skipped because the catalog reports them as not ready (is_ready=false).`,
`Skipped remote IDs: ${ids.map((id) => `\`${id}\``).join(", ")}`,
];
},
missingNotice(paths) {
if (paths.length === 0) return [];
return [
`${paths.length} local Ambient models were absent from the catalog and were retained for manual lifecycle review.`,
`Retained local paths: ${paths.map((item) => `\`${item}\``).join(", ")}`,
];
},
async fetchModels() {
const response = await fetch(API_ENDPOINT);
if (!response.ok) {
throw new Error(`Ambient request failed: ${response.status} ${response.statusText}`);
}
return response.json();
},
parseModels(raw) {
return AmbientResponse.parse(raw).data;
},
translateModel(model, context) {
if (!model.is_ready) return undefined;
const built = buildOpenRouterModel(toOpenRouterShape(model), context.existing(model.id));
const reasoning = model.supported_features.includes("reasoning");
const withOptions = reasoning ? { ...built, reasoning_options: [] } : built;
const aliasName = ambientAliasName(model.id);
return {
id: model.id,
model: aliasName === undefined ? withOptions : { ...withOptions, name: aliasName },
};
},
} satisfies SyncProvider<AmbientModel>;

function ambientAliasName(id: string): string | undefined {
if (!id.startsWith("ambient/")) return undefined;
const label = id.slice("ambient/".length)
.split(/[/-]/)
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
return `Ambient ${label}`;
}
4 changes: 2 additions & 2 deletions providers/ambient/models/moonshotai/kimi-k2.7-code.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ reasoning_options = []
temperature = true

[cost]
input = 0.75
output = 3.5
input = 0.84
output = 3.99
cache_read = 0.16
cache_write = 0
12 changes: 12 additions & 0 deletions providers/ambient/models/zai-org/GLM-5.2-FP8.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
base_model = "zhipuai/glm-5.2"
reasoning_options = []

[cost]
input = 1.2
output = 4.2
cache_read = 0.26
cache_write = 0

[limit]
context = 202_752
output = 202_752
Loading