feat(ai): provider factories, per-provider catalogs, createProvider (phase 3)
Auth helpers in src/auth/helpers.ts: envApiKeyAuth() (stored key wins, then env vars in order, with secret-prompt login) and lazyOAuth() (flow loads on first use through bundler-opaque dynamic imports in utils/oauth/load.ts; the OAuthAuth flow exports land in phase 4). There is no OAuth factory toggle: providers that support OAuth always attach it, advertising costs nothing until login/refresh runs. createProvider() in models.ts builds providers from parts: single API implementation or a map dispatched on model.api (mixed-API providers like opencode and github-copilot); unknown api yields a stream error. generate-models.ts now emits one providers/<id>.models.ts catalog per provider (35 files, biome-excluded like models.generated.ts) and models.generated.ts becomes a generated aggregator, so importing one provider factory pulls one catalog. Typed getModel globals unchanged. One factory per built-in provider under src/providers/: envApiKeyAuth for standard providers, OAuth for anthropic/openai-codex/github-copilot, ambient ApiKeyAuth for amazon-bedrock (AWS env/profile/IAM) and google-vertex (explicit key or ADC+project+location). providers/all.ts: builtinProviders(), builtinModels(), getBuiltin* re-exports. fauxProvider() factory returns a real Provider for tests; legacy registerFauxProvider() unchanged.
This commit is contained in:
@@ -31,6 +31,7 @@
|
|||||||
"!**/node_modules/**/*",
|
"!**/node_modules/**/*",
|
||||||
"!**/test-sessions.ts",
|
"!**/test-sessions.ts",
|
||||||
"!**/models.generated.ts",
|
"!**/models.generated.ts",
|
||||||
|
"!**/*.models.ts",
|
||||||
"!packages/mom/data/**/*",
|
"!packages/mom/data/**/*",
|
||||||
"!!**/node_modules"
|
"!!**/node_modules"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ All built-ins, explicitly heavy metadata entrypoint:
|
|||||||
```ts
|
```ts
|
||||||
import { builtinModels } from "@earendil-works/pi-ai/providers/all";
|
import { builtinModels } from "@earendil-works/pi-ai/providers/all";
|
||||||
|
|
||||||
const models = builtinModels({ oauth: "node" });
|
const models = builtinModels();
|
||||||
```
|
```
|
||||||
|
|
||||||
`providers/all` may import all provider metadata/catalogs. It still must not eagerly import SDK implementations; provider streams use lazy wrappers.
|
`providers/all` may import all provider metadata/catalogs. It still must not eagerly import SDK implementations; provider streams use lazy wrappers.
|
||||||
@@ -581,31 +581,22 @@ export type AuthEvent =
|
|||||||
|
|
||||||
`prompt()` returns the entered/selected string (`select` returns the option id). Flows race a `manual_code` prompt against a callback server by setting `AuthPrompt.signal` and aborting the prompt when the callback wins.
|
`prompt()` returns the entered/selected string (`select` returns the option id). Flows race a `manual_code` prompt against a callback server by setting `AuthPrompt.signal` and aborting the prompt when the callback wins.
|
||||||
|
|
||||||
### OAuth implementation target
|
### OAuth attachment
|
||||||
|
|
||||||
OAuth must not force Node-only code (`node:http`, `node:crypto`) into browser bundles. Keep OAuth lazy; the provider factory decides which implementation to attach:
|
Providers that support OAuth always attach it. There is no factory toggle: the flow is lazy-loaded, so advertising OAuth costs nothing until `login()`/`refresh()` actually runs, and a host that never logs in never loads it.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
export type OAuthTarget = "node" | "web" | false;
|
export function anthropicProvider(): Provider {
|
||||||
|
|
||||||
export interface AnthropicProviderOptions {
|
|
||||||
oauth?: OAuthTarget; // default false
|
|
||||||
}
|
|
||||||
|
|
||||||
export function anthropicProvider(options: AnthropicProviderOptions = {}): Provider {
|
|
||||||
return createProvider({
|
return createProvider({
|
||||||
id: "anthropic",
|
id: "anthropic",
|
||||||
name: "Anthropic",
|
name: "Anthropic",
|
||||||
baseUrl: "https://api.anthropic.com/v1",
|
baseUrl: "https://api.anthropic.com/v1",
|
||||||
auth: {
|
auth: {
|
||||||
apiKey: envApiKeyAuth("Anthropic API key", ["ANTHROPIC_API_KEY"]),
|
apiKey: envApiKeyAuth("Anthropic API key", ["ANTHROPIC_API_KEY"]),
|
||||||
oauth:
|
oauth: lazyOAuth({
|
||||||
options.oauth === "node"
|
name: "Anthropic (Claude Pro/Max)",
|
||||||
? lazyOAuth({
|
load: () => import("../utils/oauth/anthropic.ts").then((m) => m.anthropicOAuth),
|
||||||
name: "Anthropic (Claude Pro/Max)",
|
}),
|
||||||
load: () => import("../utils/oauth/anthropic.ts").then((m) => m.anthropicOAuth),
|
|
||||||
})
|
|
||||||
: undefined,
|
|
||||||
},
|
},
|
||||||
models: ANTHROPIC_MODELS,
|
models: ANTHROPIC_MODELS,
|
||||||
api: anthropicMessagesApi(),
|
api: anthropicMessagesApi(),
|
||||||
@@ -613,10 +604,6 @@ export function anthropicProvider(options: AnthropicProviderOptions = {}): Provi
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- Individual factories default to `oauth: false`.
|
|
||||||
- `builtinModels({ oauth: "node" })` for pi CLI/coding-agent.
|
|
||||||
- `"web"` is reserved; web flows (sitegeist-style: Web Crypto PKCE, auth tab, extension tab APIs watching the localhost redirect, fetch token exchange, device-code polling for Copilot) are a follow-up. Until implemented, passing `"web"` throws at login time with a clear message.
|
|
||||||
|
|
||||||
`lazyOAuth()` wraps a dynamically imported `OAuthAuth` so provider definitions can advertise OAuth without importing the implementation (`toAuth` is async for exactly this reason):
|
`lazyOAuth()` wraps a dynamically imported `OAuthAuth` so provider definitions can advertise OAuth without importing the implementation (`toAuth` is async for exactly this reason):
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
@@ -626,6 +613,8 @@ export function lazyOAuth(input: {
|
|||||||
}): OAuthAuth;
|
}): OAuthAuth;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
OAuth must not force Node-only code (`node:http`, `node:crypto`) into browser bundles: the dynamic import inside `lazyOAuth()` uses the same bundler-opaque variable-specifier trick as the bedrock lazy wrapper. Browser hosts never trigger the load (no stored node OAuth credentials, no login flow). If web OAuth lands later (sitegeist proved feasibility: Web Crypto PKCE, auth tab, fetch token exchange, device-code polling), it is just a different `OAuthAuth` implementation — no reserved option values.
|
||||||
|
|
||||||
The existing flows in `src/utils/oauth/` (anthropic, openai-codex, github-copilot) are adapted to `OAuthAuth` (`login`/`refresh`/`toAuth`, replacing `login`/`refreshToken`/`getApiKey`/`modifyModels`) with the new callbacks, staying Node-targeted and lazy-loaded. Copilot's `modifyModels` baseUrl rewriting becomes `toAuth` returning `ModelAuth.baseUrl`.
|
The existing flows in `src/utils/oauth/` (anthropic, openai-codex, github-copilot) are adapted to `OAuthAuth` (`login`/`refresh`/`toAuth`, replacing `login`/`refreshToken`/`getApiKey`/`modifyModels`) with the new callbacks, staying Node-targeted and lazy-loaded. Copilot's `modifyModels` baseUrl rewriting becomes `toAuth` returning `ModelAuth.baseUrl`.
|
||||||
|
|
||||||
## Provider wrappers and models.json
|
## Provider wrappers and models.json
|
||||||
@@ -699,7 +688,7 @@ Built-in provider factories use `createProvider()` internally. models.json custo
|
|||||||
|
|
||||||
Old semantics being preserved: global `stream()` dispatched purely on `model.api` via the api-registry, with env API key injection. The compat module reproduces this:
|
Old semantics being preserved: global `stream()` dispatched purely on `model.api` via the api-registry, with env API key injection. The compat module reproduces this:
|
||||||
|
|
||||||
- Lazily creates a default `Models` singleton from `builtinModels({ oauth: "node" })` on first use.
|
- Lazily creates a default `Models` singleton from `builtinModels()` on first use.
|
||||||
- `stream/complete/streamSimple/completeSimple(model, ctx, opts)`: look up `getProvider(model.provider)`; if found, route through the singleton (auth resolution included). If not found (custom models.json/extension models), fall back to api-dispatch through a hidden `createProvider()` map containing all builtin API implementations plus anything registered via compat `registerApiProvider()`.
|
- `stream/complete/streamSimple/completeSimple(model, ctx, opts)`: look up `getProvider(model.provider)`; if found, route through the singleton (auth resolution included). If not found (custom models.json/extension models), fall back to api-dispatch through a hidden `createProvider()` map containing all builtin API implementations plus anything registered via compat `registerApiProvider()`.
|
||||||
- `registerApiProvider()/unregisterApiProviders()` feed that fallback dispatch map. `api-registry.ts` dies as a real mechanism.
|
- `registerApiProvider()/unregisterApiProviders()` feed that fallback dispatch map. `api-registry.ts` dies as a real mechanism.
|
||||||
- Sync `getModel/getModels/getProviders` become deprecated aliases of `getBuiltinModel/getBuiltinModels/getBuiltinProviders` (they were always pure generated-catalog reads — verified: nothing ever mutated the old `modelRegistry`).
|
- Sync `getModel/getModels/getProviders` become deprecated aliases of `getBuiltinModel/getBuiltinModels/getBuiltinProviders` (they were always pure generated-catalog reads — verified: nothing ever mutated the old `modelRegistry`).
|
||||||
@@ -730,7 +719,7 @@ Rules:
|
|||||||
2. Provider modules import their catalog, auth helpers, and lazy API wrappers only.
|
2. Provider modules import their catalog, auth helpers, and lazy API wrappers only.
|
||||||
3. Lazy API wrappers dynamically import real API implementations.
|
3. Lazy API wrappers dynamically import real API implementations.
|
||||||
4. Real API implementations import SDK dependencies.
|
4. Real API implementations import SDK dependencies.
|
||||||
5. OAuth implementations are selected by factory option (`oauth: "node" | "web" | false`) and lazy-loaded; provider metadata never eagerly imports Node-only OAuth code.
|
5. OAuth implementations are always attached via `lazyOAuth()` and lazy-loaded behind a bundler-opaque dynamic import; provider metadata never eagerly imports Node-only OAuth code.
|
||||||
6. `providers/all` may import all provider metadata, but no eager SDK imports.
|
6. `providers/all` may import all provider metadata, but no eager SDK imports.
|
||||||
7. Provider modules are side-effect-free; importing a provider does not register anything globally.
|
7. Provider modules are side-effect-free; importing a provider does not register anything globally.
|
||||||
8. `package.json` sets `sideEffects: false`.
|
8. `package.json` sets `sideEffects: false`.
|
||||||
@@ -809,18 +798,17 @@ Check items off as they land. Keep this list current; it is the working state fo
|
|||||||
|
|
||||||
### Phase 3 — provider factories + catalogs
|
### Phase 3 — provider factories + catalogs
|
||||||
|
|
||||||
- [ ] Auth helpers in `src/auth/`: `envApiKeyAuth()`, `lazyOAuth()`, `OAuthTarget`.
|
- [x] Auth helpers in `src/auth/helpers.ts`: `envApiKeyAuth()` (with secret-prompt `login`), `lazyOAuth()`. OAuth flow loads go through `utils/oauth/load.ts` (bundler-opaque dynamic import); the `OAuthAuth` exports it references land in Phase 4.
|
||||||
- [ ] `createProvider()` (single + mixed `api` map, dispatch on `model.api`).
|
- [x] `createProvider()` in `models.ts` (single + mixed `api` map, dispatch on `model.api`, unknown api -> stream error).
|
||||||
- [ ] Per-provider factories under `src/providers/` for all built-in catalog providers, `oauth` factory options where applicable.
|
- [x] Per-provider factories under `src/providers/` for all built-in catalog providers; OAuth attached via `lazyOAuth()` (anthropic, openai-codex, github-copilot); ambient `ApiKeyAuth` for amazon-bedrock (AWS env/profile) and google-vertex (key or ADC+project+location).
|
||||||
- [ ] `providers/all.ts`: `builtinModels({ oauth? })`, `getBuiltinModel/getBuiltinModels/getBuiltinProviders`.
|
- [x] `providers/all.ts`: `builtinProviders()`, `builtinModels()`, `getBuiltinModel/getBuiltinModels/getBuiltinProviders` re-exports.
|
||||||
- [ ] Faux provider factory (`providers/faux.ts`) for tests.
|
- [x] Faux provider factory (`fauxProvider()` in `providers/faux.ts`) for tests; legacy `registerFauxProvider()` kept until compat dies.
|
||||||
- [ ] Split generated catalogs per provider via `scripts/generate-models.ts` (`providers/<id>.models.ts`) — or record explicitly that this is deferred.
|
- [x] Split generated catalogs per provider via `scripts/generate-models.ts` (`providers/<id>.models.ts`); `models.generated.ts` becomes a generated aggregator.
|
||||||
|
|
||||||
### Phase 4 — OAuth adaptation
|
### Phase 4 — OAuth adaptation
|
||||||
|
|
||||||
- [ ] Adapt `utils/oauth/anthropic.ts`, `openai-codex.ts`, `github-copilot.ts` to `OAuthAuth` (`login`/`refresh`/`toAuth`) + `prompt()/notify()`; `modifyModels` baseUrl rewriting becomes `toAuth().baseUrl`.
|
- [ ] Adapt `utils/oauth/anthropic.ts`, `openai-codex.ts`, `github-copilot.ts` to `OAuthAuth` (`login`/`refresh`/`toAuth`) + `prompt()/notify()`; `modifyModels` baseUrl rewriting becomes `toAuth().baseUrl`.
|
||||||
- [ ] Remove `usesCallbackServer`; callback-server flows race a `manual_code` prompt instead.
|
- [ ] Remove `usesCallbackServer`; callback-server flows race a `manual_code` prompt instead.
|
||||||
- [ ] `oauth: "web"` reserved: throws at login with clear message.
|
|
||||||
|
|
||||||
### Phase 5 — packaging
|
### Phase 5 — packaging
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
import { writeFileSync } from "fs";
|
import { readdirSync, rmSync, writeFileSync } from "fs";
|
||||||
import { join, dirname } from "path";
|
import { join, dirname } from "path";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
import {
|
import {
|
||||||
@@ -2103,62 +2103,80 @@ async function generateModels() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate TypeScript file
|
// Generate TypeScript files: one catalog per provider plus an aggregator
|
||||||
let output = `// This file is auto-generated by scripts/generate-models.ts
|
const generatedHeader = `// This file is auto-generated by scripts/generate-models.ts
|
||||||
// Do not edit manually - run 'npm run generate-models' to update
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
import type { Model } from "./types.ts";
|
|
||||||
|
|
||||||
export const MODELS = {
|
|
||||||
`;
|
`;
|
||||||
|
const catalogConstName = (providerId: string) => `${providerId.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_MODELS`;
|
||||||
|
|
||||||
// Generate provider sections (sorted for deterministic output)
|
function emitModel(model: Model<any>, indent: string): string {
|
||||||
const sortedProviderIds = Object.keys(providers).sort();
|
let output = `${indent}"${model.id}": {\n`;
|
||||||
for (const providerId of sortedProviderIds) {
|
output += `${indent}\tid: "${model.id}",\n`;
|
||||||
const models = providers[providerId];
|
output += `${indent}\tname: "${model.name}",\n`;
|
||||||
output += `\t${JSON.stringify(providerId)}: {\n`;
|
output += `${indent}\tapi: "${model.api}",\n`;
|
||||||
|
output += `${indent}\tprovider: "${model.provider}",\n`;
|
||||||
const sortedModelIds = Object.keys(models).sort();
|
if (model.baseUrl !== undefined) {
|
||||||
for (const modelId of sortedModelIds) {
|
output += `${indent}\tbaseUrl: "${model.baseUrl}",\n`;
|
||||||
const model = models[modelId];
|
|
||||||
output += `\t\t"${model.id}": {\n`;
|
|
||||||
output += `\t\t\tid: "${model.id}",\n`;
|
|
||||||
output += `\t\t\tname: "${model.name}",\n`;
|
|
||||||
output += `\t\t\tapi: "${model.api}",\n`;
|
|
||||||
output += `\t\t\tprovider: "${model.provider}",\n`;
|
|
||||||
if (model.baseUrl !== undefined) {
|
|
||||||
output += `\t\t\tbaseUrl: "${model.baseUrl}",\n`;
|
|
||||||
}
|
|
||||||
if (model.headers) {
|
|
||||||
output += `\t\t\theaders: ${JSON.stringify(model.headers)},\n`;
|
|
||||||
}
|
|
||||||
if (model.compat) {
|
|
||||||
output += ` compat: ${JSON.stringify(model.compat)},
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
output += `\t\t\treasoning: ${model.reasoning},\n`;
|
|
||||||
if (model.thinkingLevelMap) {
|
|
||||||
output += `\t\t\tthinkingLevelMap: ${JSON.stringify(model.thinkingLevelMap)},\n`;
|
|
||||||
}
|
|
||||||
output += `\t\t\tinput: [${model.input.map(i => `"${i}"`).join(", ")}],\n`;
|
|
||||||
output += `\t\t\tcost: {\n`;
|
|
||||||
output += `\t\t\t\tinput: ${model.cost.input},\n`;
|
|
||||||
output += `\t\t\t\toutput: ${model.cost.output},\n`;
|
|
||||||
output += `\t\t\t\tcacheRead: ${model.cost.cacheRead},\n`;
|
|
||||||
output += `\t\t\t\tcacheWrite: ${model.cost.cacheWrite},\n`;
|
|
||||||
output += `\t\t\t},\n`;
|
|
||||||
output += `\t\t\tcontextWindow: ${model.contextWindow},\n`;
|
|
||||||
output += `\t\t\tmaxTokens: ${model.maxTokens},\n`;
|
|
||||||
output += `\t\t} satisfies Model<"${model.api}">,\n`;
|
|
||||||
}
|
}
|
||||||
|
if (model.headers) {
|
||||||
output += `\t},\n`;
|
output += `${indent}\theaders: ${JSON.stringify(model.headers)},\n`;
|
||||||
|
}
|
||||||
|
if (model.compat) {
|
||||||
|
output += `${indent}\tcompat: ${JSON.stringify(model.compat)},\n`;
|
||||||
|
}
|
||||||
|
output += `${indent}\treasoning: ${model.reasoning},\n`;
|
||||||
|
if (model.thinkingLevelMap) {
|
||||||
|
output += `${indent}\tthinkingLevelMap: ${JSON.stringify(model.thinkingLevelMap)},\n`;
|
||||||
|
}
|
||||||
|
output += `${indent}\tinput: [${model.input.map(i => `"${i}"`).join(", ")}],\n`;
|
||||||
|
output += `${indent}\tcost: {\n`;
|
||||||
|
output += `${indent}\t\tinput: ${model.cost.input},\n`;
|
||||||
|
output += `${indent}\t\toutput: ${model.cost.output},\n`;
|
||||||
|
output += `${indent}\t\tcacheRead: ${model.cost.cacheRead},\n`;
|
||||||
|
output += `${indent}\t\tcacheWrite: ${model.cost.cacheWrite},\n`;
|
||||||
|
output += `${indent}\t},\n`;
|
||||||
|
output += `${indent}\tcontextWindow: ${model.contextWindow},\n`;
|
||||||
|
output += `${indent}\tmaxTokens: ${model.maxTokens},\n`;
|
||||||
|
output += `${indent}} satisfies Model<"${model.api}">,\n`;
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
output += `} as const;
|
const sortedProviderIds = Object.keys(providers).sort();
|
||||||
`;
|
const providersDir = join(packageRoot, "src/providers");
|
||||||
|
|
||||||
// Write file
|
// Remove stale per-provider catalogs
|
||||||
|
for (const entry of readdirSync(providersDir)) {
|
||||||
|
if (entry.endsWith(".models.ts")) {
|
||||||
|
rmSync(join(providersDir, entry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per-provider catalogs (sorted for deterministic output)
|
||||||
|
for (const providerId of sortedProviderIds) {
|
||||||
|
const models = providers[providerId];
|
||||||
|
let output = generatedHeader;
|
||||||
|
output += `import type { Model } from "../types.ts";\n\n`;
|
||||||
|
output += `export const ${catalogConstName(providerId)} = {\n`;
|
||||||
|
const sortedModelIds = Object.keys(models).sort();
|
||||||
|
for (const modelId of sortedModelIds) {
|
||||||
|
output += emitModel(models[modelId], "\t");
|
||||||
|
}
|
||||||
|
output += `} as const;\n`;
|
||||||
|
writeFileSync(join(providersDir, `${providerId}.models.ts`), output);
|
||||||
|
}
|
||||||
|
console.log(`Generated ${sortedProviderIds.length} catalogs under src/providers/`);
|
||||||
|
|
||||||
|
// Aggregator
|
||||||
|
let output = generatedHeader;
|
||||||
|
for (const providerId of sortedProviderIds) {
|
||||||
|
output += `import { ${catalogConstName(providerId)} } from "./providers/${providerId}.models.ts";\n`;
|
||||||
|
}
|
||||||
|
output += `\nexport const MODELS = {\n`;
|
||||||
|
for (const providerId of sortedProviderIds) {
|
||||||
|
output += `\t${JSON.stringify(providerId)}: ${catalogConstName(providerId)},\n`;
|
||||||
|
}
|
||||||
|
output += `} as const;\n`;
|
||||||
writeFileSync(join(packageRoot, "src/models.generated.ts"), output);
|
writeFileSync(join(packageRoot, "src/models.generated.ts"), output);
|
||||||
console.log("Generated src/models.generated.ts");
|
console.log("Generated src/models.generated.ts");
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import type { ApiKeyAuth, OAuthAuth } from "./types.ts";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard api-key auth: a stored credential key wins, otherwise the first
|
||||||
|
* set env var resolves. Includes a `login` that prompts for the key.
|
||||||
|
* Providers with non-standard resolution (metadata, ambient files, IAM)
|
||||||
|
* write their own `ApiKeyAuth`.
|
||||||
|
*/
|
||||||
|
export function envApiKeyAuth(name: string, envVars: readonly string[]): ApiKeyAuth {
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
login: async (callbacks) => {
|
||||||
|
const key = await callbacks.prompt({ type: "secret", message: `Enter ${name}` });
|
||||||
|
return { type: "api-key", key };
|
||||||
|
},
|
||||||
|
resolve: async ({ ctx, credential }) => {
|
||||||
|
if (credential?.key) return { auth: { apiKey: credential.key }, source: "stored credential" };
|
||||||
|
for (const envVar of envVars) {
|
||||||
|
const value = await ctx.env(envVar);
|
||||||
|
if (value) return { auth: { apiKey: value }, source: envVar };
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a dynamically imported `OAuthAuth` so provider definitions can
|
||||||
|
* advertise OAuth without importing the implementation. The flow loads on
|
||||||
|
* first `login`/`refresh`/`toAuth` call; callers keep Node-only flow code out
|
||||||
|
* of bundles by loading through a bundler-opaque dynamic import (variable
|
||||||
|
* specifier, see the bedrock lazy wrapper).
|
||||||
|
*/
|
||||||
|
export function lazyOAuth(input: { name: string; load: () => Promise<OAuthAuth> }): OAuthAuth {
|
||||||
|
let promise: Promise<OAuthAuth> | undefined;
|
||||||
|
const loaded = () => {
|
||||||
|
promise ??= input.load();
|
||||||
|
return promise;
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
name: input.name,
|
||||||
|
login: async (callbacks) => (await loaded()).login(callbacks),
|
||||||
|
refresh: async (credential) => (await loaded()).refresh(credential),
|
||||||
|
toAuth: async (credential) => (await loaded()).toAuth(credential),
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ export type { OpenAIResponsesOptions } from "./api/openai-responses.ts";
|
|||||||
export * from "./api-registry.ts";
|
export * from "./api-registry.ts";
|
||||||
export * from "./auth/context.ts";
|
export * from "./auth/context.ts";
|
||||||
export * from "./auth/credential-store.ts";
|
export * from "./auth/credential-store.ts";
|
||||||
|
export * from "./auth/helpers.ts";
|
||||||
export * from "./auth/types.ts";
|
export * from "./auth/types.ts";
|
||||||
export * from "./env-api-keys.ts";
|
export * from "./env-api-keys.ts";
|
||||||
export * from "./image-models.ts";
|
export * from "./image-models.ts";
|
||||||
|
|||||||
+70
-16969
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,7 @@ import type {
|
|||||||
KnownProvider,
|
KnownProvider,
|
||||||
Model,
|
Model,
|
||||||
ModelThinkingLevel,
|
ModelThinkingLevel,
|
||||||
|
ProviderStreams,
|
||||||
SimpleStreamOptions,
|
SimpleStreamOptions,
|
||||||
StreamOptions,
|
StreamOptions,
|
||||||
Usage,
|
Usage,
|
||||||
@@ -351,6 +352,61 @@ export function createModels(options?: CreateModelsOptions): MutableModels {
|
|||||||
return new ModelsImpl(options);
|
return new ModelsImpl(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CreateProviderOptions<TApi extends Api = Api> {
|
||||||
|
id: string;
|
||||||
|
/** Display name. Default: `id`. */
|
||||||
|
name?: string;
|
||||||
|
baseUrl?: string;
|
||||||
|
headers?: Record<string, string>;
|
||||||
|
/** Required — every provider has auth semantics, even ambient/keyless ones. */
|
||||||
|
auth: ProviderAuth;
|
||||||
|
models:
|
||||||
|
| readonly Model<TApi>[]
|
||||||
|
| ((options?: { forceRefresh?: boolean }) => Promise<readonly Model<TApi>[]> | readonly Model<TApi>[]);
|
||||||
|
/** Single implementation, or map keyed by `model.api` for mixed-API providers. */
|
||||||
|
api: ProviderStreams | Partial<Record<TApi, ProviderStreams>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a provider from parts. Built-in provider factories and models.json
|
||||||
|
* custom providers both go through this. A single `api` streams all models;
|
||||||
|
* an `api` map dispatches on `model.api`, and a model whose api has no entry
|
||||||
|
* produces a stream error.
|
||||||
|
*/
|
||||||
|
export function createProvider<TApi extends Api = Api>(input: CreateProviderOptions<TApi>): Provider<TApi> {
|
||||||
|
const { models } = input;
|
||||||
|
const single =
|
||||||
|
typeof (input.api as ProviderStreams).stream === "function" ? (input.api as ProviderStreams) : undefined;
|
||||||
|
const byApi = single ? undefined : (input.api as Partial<Record<string, ProviderStreams>>);
|
||||||
|
|
||||||
|
const apiFor = (model: Model<Api>): ProviderStreams | undefined => single ?? byApi?.[model.api];
|
||||||
|
|
||||||
|
const dispatch = (
|
||||||
|
model: Model<Api>,
|
||||||
|
run: (streams: ProviderStreams) => AssistantMessageEventStream,
|
||||||
|
): AssistantMessageEventStream => {
|
||||||
|
const streams = apiFor(model);
|
||||||
|
if (!streams) {
|
||||||
|
return lazyStream(model, async () => {
|
||||||
|
throw new ModelsError("stream", `Provider ${input.id} has no API implementation for "${model.api}"`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return run(streams);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: input.id,
|
||||||
|
name: input.name ?? input.id,
|
||||||
|
baseUrl: input.baseUrl,
|
||||||
|
headers: input.headers,
|
||||||
|
auth: input.auth,
|
||||||
|
getModels: typeof models === "function" ? (options) => models(options) : () => models,
|
||||||
|
stream: (model, context, options) => dispatch(model, (streams) => streams.stream(model, context, options)),
|
||||||
|
streamSimple: (model, context, options) =>
|
||||||
|
dispatch(model, (streams) => streams.streamSimple(model, context, options)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runtime-checked narrowing for dynamically looked-up models:
|
* Runtime-checked narrowing for dynamically looked-up models:
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import { type CreateModelsOptions, createModels, type MutableModels, type Provider } from "../models.ts";
|
||||||
|
import { amazonBedrockProvider } from "./amazon-bedrock.ts";
|
||||||
|
import { antLingProvider } from "./ant-ling.ts";
|
||||||
|
import { anthropicProvider } from "./anthropic.ts";
|
||||||
|
import { azureOpenAIResponsesProvider } from "./azure-openai-responses.ts";
|
||||||
|
import { cerebrasProvider } from "./cerebras.ts";
|
||||||
|
import { cloudflareAIGatewayProvider } from "./cloudflare-ai-gateway.ts";
|
||||||
|
import { cloudflareWorkersAIProvider } from "./cloudflare-workers-ai.ts";
|
||||||
|
import { deepseekProvider } from "./deepseek.ts";
|
||||||
|
import { fireworksProvider } from "./fireworks.ts";
|
||||||
|
import { githubCopilotProvider } from "./github-copilot.ts";
|
||||||
|
import { googleProvider } from "./google.ts";
|
||||||
|
import { googleVertexProvider } from "./google-vertex.ts";
|
||||||
|
import { groqProvider } from "./groq.ts";
|
||||||
|
import { huggingfaceProvider } from "./huggingface.ts";
|
||||||
|
import { kimiCodingProvider } from "./kimi-coding.ts";
|
||||||
|
import { minimaxProvider } from "./minimax.ts";
|
||||||
|
import { minimaxCnProvider } from "./minimax-cn.ts";
|
||||||
|
import { mistralProvider } from "./mistral.ts";
|
||||||
|
import { moonshotaiProvider } from "./moonshotai.ts";
|
||||||
|
import { moonshotaiCnProvider } from "./moonshotai-cn.ts";
|
||||||
|
import { nvidiaProvider } from "./nvidia.ts";
|
||||||
|
import { openaiProvider } from "./openai.ts";
|
||||||
|
import { openaiCodexProvider } from "./openai-codex.ts";
|
||||||
|
import { opencodeProvider } from "./opencode.ts";
|
||||||
|
import { opencodeGoProvider } from "./opencode-go.ts";
|
||||||
|
import { openrouterProvider } from "./openrouter.ts";
|
||||||
|
import { togetherProvider } from "./together.ts";
|
||||||
|
import { vercelAIGatewayProvider } from "./vercel-ai-gateway.ts";
|
||||||
|
import { xaiProvider } from "./xai.ts";
|
||||||
|
import { xiaomiProvider } from "./xiaomi.ts";
|
||||||
|
import { xiaomiTokenPlanAmsProvider } from "./xiaomi-token-plan-ams.ts";
|
||||||
|
import { xiaomiTokenPlanCnProvider } from "./xiaomi-token-plan-cn.ts";
|
||||||
|
import { xiaomiTokenPlanSgpProvider } from "./xiaomi-token-plan-sgp.ts";
|
||||||
|
import { zaiProvider } from "./zai.ts";
|
||||||
|
import { zaiCodingCnProvider } from "./zai-coding-cn.ts";
|
||||||
|
|
||||||
|
export {
|
||||||
|
getModel as getBuiltinModel,
|
||||||
|
getModels as getBuiltinModels,
|
||||||
|
getProviders as getBuiltinProviders,
|
||||||
|
} from "../models.ts";
|
||||||
|
|
||||||
|
/** All built-in providers, freshly constructed. */
|
||||||
|
export function builtinProviders(): Provider[] {
|
||||||
|
return [
|
||||||
|
amazonBedrockProvider(),
|
||||||
|
antLingProvider(),
|
||||||
|
anthropicProvider(),
|
||||||
|
azureOpenAIResponsesProvider(),
|
||||||
|
cerebrasProvider(),
|
||||||
|
cloudflareAIGatewayProvider(),
|
||||||
|
cloudflareWorkersAIProvider(),
|
||||||
|
deepseekProvider(),
|
||||||
|
fireworksProvider(),
|
||||||
|
githubCopilotProvider(),
|
||||||
|
googleProvider(),
|
||||||
|
googleVertexProvider(),
|
||||||
|
groqProvider(),
|
||||||
|
huggingfaceProvider(),
|
||||||
|
kimiCodingProvider(),
|
||||||
|
minimaxProvider(),
|
||||||
|
minimaxCnProvider(),
|
||||||
|
mistralProvider(),
|
||||||
|
moonshotaiProvider(),
|
||||||
|
moonshotaiCnProvider(),
|
||||||
|
nvidiaProvider(),
|
||||||
|
openaiProvider(),
|
||||||
|
openaiCodexProvider(),
|
||||||
|
opencodeProvider(),
|
||||||
|
opencodeGoProvider(),
|
||||||
|
openrouterProvider(),
|
||||||
|
togetherProvider(),
|
||||||
|
vercelAIGatewayProvider(),
|
||||||
|
xaiProvider(),
|
||||||
|
xiaomiProvider(),
|
||||||
|
xiaomiTokenPlanAmsProvider(),
|
||||||
|
xiaomiTokenPlanCnProvider(),
|
||||||
|
xiaomiTokenPlanSgpProvider(),
|
||||||
|
zaiProvider(),
|
||||||
|
zaiCodingCnProvider(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A `Models` collection with every built-in provider registered. */
|
||||||
|
export function builtinModels(options?: CreateModelsOptions): MutableModels {
|
||||||
|
const models = createModels(options);
|
||||||
|
for (const provider of builtinProviders()) {
|
||||||
|
models.setProvider(provider);
|
||||||
|
}
|
||||||
|
return models;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,35 @@
|
|||||||
|
import { bedrockConverseStreamApi } from "../api/bedrock-converse-stream.lazy.ts";
|
||||||
|
import type { ApiKeyAuth } from "../auth/types.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { AMAZON_BEDROCK_MODELS } from "./amazon-bedrock.models.ts";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bedrock auth is ambient: the AWS SDK's default credential chain handles the
|
||||||
|
* actual signing, so `resolve` only reports whether the provider is
|
||||||
|
* configured. A stored credential key is surfaced as the bearer token.
|
||||||
|
*/
|
||||||
|
const bedrockAuth: ApiKeyAuth = {
|
||||||
|
name: "AWS credentials",
|
||||||
|
resolve: async ({ ctx, credential }) => {
|
||||||
|
if (credential?.key) return { auth: { apiKey: credential.key }, source: "stored credential" };
|
||||||
|
if (await ctx.env("AWS_BEARER_TOKEN_BEDROCK")) return { auth: {}, source: "AWS_BEARER_TOKEN_BEDROCK" };
|
||||||
|
if (await ctx.env("AWS_PROFILE")) return { auth: {}, source: "AWS_PROFILE" };
|
||||||
|
if ((await ctx.env("AWS_ACCESS_KEY_ID")) && (await ctx.env("AWS_SECRET_ACCESS_KEY"))) {
|
||||||
|
return { auth: {}, source: "AWS access keys" };
|
||||||
|
}
|
||||||
|
if (await ctx.env("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI")) return { auth: {}, source: "ECS task role" };
|
||||||
|
if (await ctx.env("AWS_CONTAINER_CREDENTIALS_FULL_URI")) return { auth: {}, source: "ECS task role" };
|
||||||
|
if (await ctx.env("AWS_WEB_IDENTITY_TOKEN_FILE")) return { auth: {}, source: "web identity token" };
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function amazonBedrockProvider(): Provider<"bedrock-converse-stream"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "amazon-bedrock",
|
||||||
|
name: "Amazon Bedrock",
|
||||||
|
auth: { apiKey: bedrockAuth },
|
||||||
|
models: Object.values(AMAZON_BEDROCK_MODELS),
|
||||||
|
api: bedrockConverseStreamApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const ANT_LING_MODELS = {
|
||||||
|
"Ling-2.6-1T": {
|
||||||
|
id: "Ling-2.6-1T",
|
||||||
|
name: "Ling 2.6 1T",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "ant-ling",
|
||||||
|
baseUrl: "https://api.ant-ling.com/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsLongCacheRetention":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.06,
|
||||||
|
output: 0.25,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"Ling-2.6-flash": {
|
||||||
|
id: "Ling-2.6-flash",
|
||||||
|
name: "Ling 2.6 Flash",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "ant-ling",
|
||||||
|
baseUrl: "https://api.ant-ling.com/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsLongCacheRetention":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.01,
|
||||||
|
output: 0.02,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"Ring-2.6-1T": {
|
||||||
|
id: "Ring-2.6-1T",
|
||||||
|
name: "Ring 2.6 1T",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "ant-ling",
|
||||||
|
baseUrl: "https://api.ant-ling.com/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsLongCacheRetention":false,"thinkingFormat":"ant-ling"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"xhigh"},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.06,
|
||||||
|
output: 0.25,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { ANT_LING_MODELS } from "./ant-ling.models.ts";
|
||||||
|
|
||||||
|
export function antLingProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "ant-ling",
|
||||||
|
name: "Ant Ling",
|
||||||
|
baseUrl: "https://api.ant-ling.com/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Ant Ling API key", ["ANT_LING_API_KEY"]) },
|
||||||
|
models: Object.values(ANT_LING_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,441 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const ANTHROPIC_MODELS = {
|
||||||
|
"claude-3-5-haiku-20241022": {
|
||||||
|
id: "claude-3-5-haiku-20241022",
|
||||||
|
name: "Claude Haiku 3.5",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.8,
|
||||||
|
output: 4,
|
||||||
|
cacheRead: 0.08,
|
||||||
|
cacheWrite: 1,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-3-5-haiku-latest": {
|
||||||
|
id: "claude-3-5-haiku-latest",
|
||||||
|
name: "Claude Haiku 3.5 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.8,
|
||||||
|
output: 4,
|
||||||
|
cacheRead: 0.08,
|
||||||
|
cacheWrite: 1,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-3-5-sonnet-20240620": {
|
||||||
|
id: "claude-3-5-sonnet-20240620",
|
||||||
|
name: "Claude Sonnet 3.5",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-3-5-sonnet-20241022": {
|
||||||
|
id: "claude-3-5-sonnet-20241022",
|
||||||
|
name: "Claude Sonnet 3.5 v2",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-3-7-sonnet-20250219": {
|
||||||
|
id: "claude-3-7-sonnet-20250219",
|
||||||
|
name: "Claude Sonnet 3.7",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-3-haiku-20240307": {
|
||||||
|
id: "claude-3-haiku-20240307",
|
||||||
|
name: "Claude Haiku 3",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 1.25,
|
||||||
|
cacheRead: 0.03,
|
||||||
|
cacheWrite: 0.3,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-3-opus-20240229": {
|
||||||
|
id: "claude-3-opus-20240229",
|
||||||
|
name: "Claude Opus 3",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 15,
|
||||||
|
output: 75,
|
||||||
|
cacheRead: 1.5,
|
||||||
|
cacheWrite: 18.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-3-sonnet-20240229": {
|
||||||
|
id: "claude-3-sonnet-20240229",
|
||||||
|
name: "Claude Sonnet 3",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 0.3,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-fable-5": {
|
||||||
|
id: "claude-fable-5",
|
||||||
|
name: "Claude Fable 5",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
compat: {"forceAdaptiveThinking":true},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 10,
|
||||||
|
output: 50,
|
||||||
|
cacheRead: 1,
|
||||||
|
cacheWrite: 12.5,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-haiku-4-5": {
|
||||||
|
id: "claude-haiku-4-5",
|
||||||
|
name: "Claude Haiku 4.5 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 5,
|
||||||
|
cacheRead: 0.1,
|
||||||
|
cacheWrite: 1.25,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-haiku-4-5-20251001": {
|
||||||
|
id: "claude-haiku-4-5-20251001",
|
||||||
|
name: "Claude Haiku 4.5",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 5,
|
||||||
|
cacheRead: 0.1,
|
||||||
|
cacheWrite: 1.25,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-0": {
|
||||||
|
id: "claude-opus-4-0",
|
||||||
|
name: "Claude Opus 4 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 15,
|
||||||
|
output: 75,
|
||||||
|
cacheRead: 1.5,
|
||||||
|
cacheWrite: 18.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-1": {
|
||||||
|
id: "claude-opus-4-1",
|
||||||
|
name: "Claude Opus 4.1 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 15,
|
||||||
|
output: 75,
|
||||||
|
cacheRead: 1.5,
|
||||||
|
cacheWrite: 18.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-1-20250805": {
|
||||||
|
id: "claude-opus-4-1-20250805",
|
||||||
|
name: "Claude Opus 4.1",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 15,
|
||||||
|
output: 75,
|
||||||
|
cacheRead: 1.5,
|
||||||
|
cacheWrite: 18.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-20250514": {
|
||||||
|
id: "claude-opus-4-20250514",
|
||||||
|
name: "Claude Opus 4",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 15,
|
||||||
|
output: 75,
|
||||||
|
cacheRead: 1.5,
|
||||||
|
cacheWrite: 18.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-5": {
|
||||||
|
id: "claude-opus-4-5",
|
||||||
|
name: "Claude Opus 4.5 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-5-20251101": {
|
||||||
|
id: "claude-opus-4-5-20251101",
|
||||||
|
name: "Claude Opus 4.5",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-6": {
|
||||||
|
id: "claude-opus-4-6",
|
||||||
|
name: "Claude Opus 4.6",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
compat: {"forceAdaptiveThinking":true},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"max"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-7": {
|
||||||
|
id: "claude-opus-4-7",
|
||||||
|
name: "Claude Opus 4.7",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
compat: {"forceAdaptiveThinking":true,"supportsTemperature":false},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-8": {
|
||||||
|
id: "claude-opus-4-8",
|
||||||
|
name: "Claude Opus 4.8",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
compat: {"forceAdaptiveThinking":true,"supportsTemperature":false},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-sonnet-4-0": {
|
||||||
|
id: "claude-sonnet-4-0",
|
||||||
|
name: "Claude Sonnet 4 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-sonnet-4-20250514": {
|
||||||
|
id: "claude-sonnet-4-20250514",
|
||||||
|
name: "Claude Sonnet 4",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-sonnet-4-5": {
|
||||||
|
id: "claude-sonnet-4-5",
|
||||||
|
name: "Claude Sonnet 4.5 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-sonnet-4-5-20250929": {
|
||||||
|
id: "claude-sonnet-4-5-20250929",
|
||||||
|
name: "Claude Sonnet 4.5",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-sonnet-4-6": {
|
||||||
|
id: "claude-sonnet-4-6",
|
||||||
|
name: "Claude Sonnet 4.6",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
compat: {"forceAdaptiveThinking":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { anthropicMessagesApi } from "../api/anthropic-messages.lazy.ts";
|
||||||
|
import { envApiKeyAuth, lazyOAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { loadAnthropicOAuth } from "../utils/oauth/load.ts";
|
||||||
|
import { ANTHROPIC_MODELS } from "./anthropic.models.ts";
|
||||||
|
|
||||||
|
export function anthropicProvider(): Provider<"anthropic-messages"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "anthropic",
|
||||||
|
name: "Anthropic",
|
||||||
|
baseUrl: "https://api.anthropic.com",
|
||||||
|
auth: {
|
||||||
|
// ANTHROPIC_OAUTH_TOKEN takes precedence over ANTHROPIC_API_KEY
|
||||||
|
apiKey: envApiKeyAuth("Anthropic API key", ["ANTHROPIC_OAUTH_TOKEN", "ANTHROPIC_API_KEY"]),
|
||||||
|
oauth: lazyOAuth({ name: "Anthropic (Claude Pro/Max)", load: loadAnthropicOAuth }),
|
||||||
|
},
|
||||||
|
models: Object.values(ANTHROPIC_MODELS),
|
||||||
|
api: anthropicMessagesApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,745 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const AZURE_OPENAI_RESPONSES_MODELS = {
|
||||||
|
"gpt-4": {
|
||||||
|
id: "gpt-4",
|
||||||
|
name: "GPT-4",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 30,
|
||||||
|
output: 60,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 8192,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-4-turbo": {
|
||||||
|
id: "gpt-4-turbo",
|
||||||
|
name: "GPT-4 Turbo",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 10,
|
||||||
|
output: 30,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-4.1": {
|
||||||
|
id: "gpt-4.1",
|
||||||
|
name: "GPT-4.1",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 8,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1047576,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-4.1-mini": {
|
||||||
|
id: "gpt-4.1-mini",
|
||||||
|
name: "GPT-4.1 mini",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 1.6,
|
||||||
|
cacheRead: 0.1,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1047576,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-4.1-nano": {
|
||||||
|
id: "gpt-4.1-nano",
|
||||||
|
name: "GPT-4.1 nano",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.4,
|
||||||
|
cacheRead: 0.025,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1047576,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-4o": {
|
||||||
|
id: "gpt-4o",
|
||||||
|
name: "GPT-4o",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 1.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-4o-2024-05-13": {
|
||||||
|
id: "gpt-4o-2024-05-13",
|
||||||
|
name: "GPT-4o (2024-05-13)",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-4o-2024-08-06": {
|
||||||
|
id: "gpt-4o-2024-08-06",
|
||||||
|
name: "GPT-4o (2024-08-06)",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 1.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-4o-2024-11-20": {
|
||||||
|
id: "gpt-4o-2024-11-20",
|
||||||
|
name: "GPT-4o (2024-11-20)",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 1.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-4o-mini": {
|
||||||
|
id: "gpt-4o-mini",
|
||||||
|
name: "GPT-4o mini",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.15,
|
||||||
|
output: 0.6,
|
||||||
|
cacheRead: 0.075,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5": {
|
||||||
|
id: "gpt-5",
|
||||||
|
name: "GPT-5",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5-chat-latest": {
|
||||||
|
id: "gpt-5-chat-latest",
|
||||||
|
name: "GPT-5 Chat Latest",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: false,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5-codex": {
|
||||||
|
id: "gpt-5-codex",
|
||||||
|
name: "GPT-5-Codex",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5-mini": {
|
||||||
|
id: "gpt-5-mini",
|
||||||
|
name: "GPT-5 Mini",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.025,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5-nano": {
|
||||||
|
id: "gpt-5-nano",
|
||||||
|
name: "GPT-5 Nano",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.05,
|
||||||
|
output: 0.4,
|
||||||
|
cacheRead: 0.005,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5-pro": {
|
||||||
|
id: "gpt-5-pro",
|
||||||
|
name: "GPT-5 Pro",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 15,
|
||||||
|
output: 120,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.1": {
|
||||||
|
id: "gpt-5.1",
|
||||||
|
name: "GPT-5.1",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.1-chat-latest": {
|
||||||
|
id: "gpt-5.1-chat-latest",
|
||||||
|
name: "GPT-5.1 Chat",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.1-codex": {
|
||||||
|
id: "gpt-5.1-codex",
|
||||||
|
name: "GPT-5.1 Codex",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.1-codex-max": {
|
||||||
|
id: "gpt-5.1-codex-max",
|
||||||
|
name: "GPT-5.1 Codex Max",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.1-codex-mini": {
|
||||||
|
id: "gpt-5.1-codex-mini",
|
||||||
|
name: "GPT-5.1 Codex mini",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.025,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.2": {
|
||||||
|
id: "gpt-5.2",
|
||||||
|
name: "GPT-5.2",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.2-chat-latest": {
|
||||||
|
id: "gpt-5.2-chat-latest",
|
||||||
|
name: "GPT-5.2 Chat",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.2-codex": {
|
||||||
|
id: "gpt-5.2-codex",
|
||||||
|
name: "GPT-5.2 Codex",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.2-pro": {
|
||||||
|
id: "gpt-5.2-pro",
|
||||||
|
name: "GPT-5.2 Pro",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 21,
|
||||||
|
output: 168,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.3-chat-latest": {
|
||||||
|
id: "gpt-5.3-chat-latest",
|
||||||
|
name: "GPT-5.3 Chat (latest)",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: false,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.3-codex": {
|
||||||
|
id: "gpt-5.3-codex",
|
||||||
|
name: "GPT-5.3 Codex",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.3-codex-spark": {
|
||||||
|
id: "gpt-5.3-codex-spark",
|
||||||
|
name: "GPT-5.3 Codex Spark",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.4": {
|
||||||
|
id: "gpt-5.4",
|
||||||
|
name: "GPT-5.4",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1050000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.4-mini": {
|
||||||
|
id: "gpt-5.4-mini",
|
||||||
|
name: "GPT-5.4 mini",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.75,
|
||||||
|
output: 4.5,
|
||||||
|
cacheRead: 0.075,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.4-nano": {
|
||||||
|
id: "gpt-5.4-nano",
|
||||||
|
name: "GPT-5.4 nano",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.2,
|
||||||
|
output: 1.25,
|
||||||
|
cacheRead: 0.02,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.4-pro": {
|
||||||
|
id: "gpt-5.4-pro",
|
||||||
|
name: "GPT-5.4 Pro",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 30,
|
||||||
|
output: 180,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1050000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.5": {
|
||||||
|
id: "gpt-5.5",
|
||||||
|
name: "GPT-5.5",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 30,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1050000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"gpt-5.5-pro": {
|
||||||
|
id: "gpt-5.5-pro",
|
||||||
|
name: "GPT-5.5 Pro",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh","minimal":null,"low":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 30,
|
||||||
|
output: 180,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1050000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"o1": {
|
||||||
|
id: "o1",
|
||||||
|
name: "o1",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 15,
|
||||||
|
output: 60,
|
||||||
|
cacheRead: 7.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"o1-pro": {
|
||||||
|
id: "o1-pro",
|
||||||
|
name: "o1-pro",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 150,
|
||||||
|
output: 600,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"o3": {
|
||||||
|
id: "o3",
|
||||||
|
name: "o3",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 8,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"o3-deep-research": {
|
||||||
|
id: "o3-deep-research",
|
||||||
|
name: "o3-deep-research",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 10,
|
||||||
|
output: 40,
|
||||||
|
cacheRead: 2.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"o3-mini": {
|
||||||
|
id: "o3-mini",
|
||||||
|
name: "o3-mini",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.1,
|
||||||
|
output: 4.4,
|
||||||
|
cacheRead: 0.55,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"o3-pro": {
|
||||||
|
id: "o3-pro",
|
||||||
|
name: "o3-pro",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 20,
|
||||||
|
output: 80,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"o4-mini": {
|
||||||
|
id: "o4-mini",
|
||||||
|
name: "o4-mini",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.1,
|
||||||
|
output: 4.4,
|
||||||
|
cacheRead: 0.275,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
"o4-mini-deep-research": {
|
||||||
|
id: "o4-mini-deep-research",
|
||||||
|
name: "o4-mini-deep-research",
|
||||||
|
api: "azure-openai-responses",
|
||||||
|
provider: "azure-openai-responses",
|
||||||
|
baseUrl: "",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 8,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"azure-openai-responses">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { azureOpenAIResponsesApi } from "../api/azure-openai-responses.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { AZURE_OPENAI_RESPONSES_MODELS } from "./azure-openai-responses.models.ts";
|
||||||
|
|
||||||
|
export function azureOpenAIResponsesProvider(): Provider<"azure-openai-responses"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "azure-openai-responses",
|
||||||
|
name: "Azure OpenAI",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Azure OpenAI API key", ["AZURE_OPENAI_API_KEY"]) },
|
||||||
|
models: Object.values(AZURE_OPENAI_RESPONSES_MODELS),
|
||||||
|
api: azureOpenAIResponsesApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const CEREBRAS_MODELS = {
|
||||||
|
"gpt-oss-120b": {
|
||||||
|
id: "gpt-oss-120b",
|
||||||
|
name: "GPT OSS 120B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cerebras",
|
||||||
|
baseUrl: "https://api.cerebras.ai/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 0.69,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"llama3.1-8b": {
|
||||||
|
id: "llama3.1-8b",
|
||||||
|
name: "Llama 3.1 8B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cerebras",
|
||||||
|
baseUrl: "https://api.cerebras.ai/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.1,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 32000,
|
||||||
|
maxTokens: 8000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"zai-glm-4.7": {
|
||||||
|
id: "zai-glm-4.7",
|
||||||
|
name: "Z.AI GLM-4.7",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cerebras",
|
||||||
|
baseUrl: "https://api.cerebras.ai/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 2.25,
|
||||||
|
output: 2.75,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 40000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { CEREBRAS_MODELS } from "./cerebras.models.ts";
|
||||||
|
|
||||||
|
export function cerebrasProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "cerebras",
|
||||||
|
name: "Cerebras",
|
||||||
|
baseUrl: "https://api.cerebras.ai/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Cerebras API key", ["CEREBRAS_API_KEY"]) },
|
||||||
|
models: Object.values(CEREBRAS_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,656 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const CLOUDFLARE_AI_GATEWAY_MODELS = {
|
||||||
|
"claude-3-5-haiku": {
|
||||||
|
id: "claude-3-5-haiku",
|
||||||
|
name: "Claude Haiku 3.5 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.8,
|
||||||
|
output: 4,
|
||||||
|
cacheRead: 0.08,
|
||||||
|
cacheWrite: 1,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-3-haiku": {
|
||||||
|
id: "claude-3-haiku",
|
||||||
|
name: "Claude Haiku 3",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 1.25,
|
||||||
|
cacheRead: 0.03,
|
||||||
|
cacheWrite: 0.3,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-3-opus": {
|
||||||
|
id: "claude-3-opus",
|
||||||
|
name: "Claude Opus 3",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 15,
|
||||||
|
output: 75,
|
||||||
|
cacheRead: 1.5,
|
||||||
|
cacheWrite: 18.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-3-sonnet": {
|
||||||
|
id: "claude-3-sonnet",
|
||||||
|
name: "Claude Sonnet 3",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 0.3,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-3.5-haiku": {
|
||||||
|
id: "claude-3.5-haiku",
|
||||||
|
name: "Claude Haiku 3.5 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.8,
|
||||||
|
output: 4,
|
||||||
|
cacheRead: 0.08,
|
||||||
|
cacheWrite: 1,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-3.5-sonnet": {
|
||||||
|
id: "claude-3.5-sonnet",
|
||||||
|
name: "Claude Sonnet 3.5 v2",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-fable-5": {
|
||||||
|
id: "claude-fable-5",
|
||||||
|
name: "Claude Fable 5",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
compat: {"forceAdaptiveThinking":true},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 10,
|
||||||
|
output: 50,
|
||||||
|
cacheRead: 1,
|
||||||
|
cacheWrite: 12.5,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-haiku-4-5": {
|
||||||
|
id: "claude-haiku-4-5",
|
||||||
|
name: "Claude Haiku 4.5 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 5,
|
||||||
|
cacheRead: 0.1,
|
||||||
|
cacheWrite: 1.25,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4": {
|
||||||
|
id: "claude-opus-4",
|
||||||
|
name: "Claude Opus 4 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 15,
|
||||||
|
output: 75,
|
||||||
|
cacheRead: 1.5,
|
||||||
|
cacheWrite: 18.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-1": {
|
||||||
|
id: "claude-opus-4-1",
|
||||||
|
name: "Claude Opus 4.1 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 15,
|
||||||
|
output: 75,
|
||||||
|
cacheRead: 1.5,
|
||||||
|
cacheWrite: 18.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-5": {
|
||||||
|
id: "claude-opus-4-5",
|
||||||
|
name: "Claude Opus 4.5 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-6": {
|
||||||
|
id: "claude-opus-4-6",
|
||||||
|
name: "Claude Opus 4.6 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
compat: {"forceAdaptiveThinking":true},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"max"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-7": {
|
||||||
|
id: "claude-opus-4-7",
|
||||||
|
name: "Claude Opus 4.7",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
compat: {"forceAdaptiveThinking":true,"supportsTemperature":false},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-8": {
|
||||||
|
id: "claude-opus-4-8",
|
||||||
|
name: "Claude Opus 4.8",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
compat: {"forceAdaptiveThinking":true,"supportsTemperature":false},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-sonnet-4": {
|
||||||
|
id: "claude-sonnet-4",
|
||||||
|
name: "Claude Sonnet 4 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-sonnet-4-5": {
|
||||||
|
id: "claude-sonnet-4-5",
|
||||||
|
name: "Claude Sonnet 4.5 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-sonnet-4-6": {
|
||||||
|
id: "claude-sonnet-4-6",
|
||||||
|
name: "Claude Sonnet 4.6",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/anthropic",
|
||||||
|
compat: {"forceAdaptiveThinking":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"gpt-4": {
|
||||||
|
id: "gpt-4",
|
||||||
|
name: "GPT-4",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 30,
|
||||||
|
output: 60,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 8192,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-4-turbo": {
|
||||||
|
id: "gpt-4-turbo",
|
||||||
|
name: "GPT-4 Turbo",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 10,
|
||||||
|
output: 30,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-4o": {
|
||||||
|
id: "gpt-4o",
|
||||||
|
name: "GPT-4o",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 1.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-4o-mini": {
|
||||||
|
id: "gpt-4o-mini",
|
||||||
|
name: "GPT-4o mini",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.15,
|
||||||
|
output: 0.6,
|
||||||
|
cacheRead: 0.08,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.1": {
|
||||||
|
id: "gpt-5.1",
|
||||||
|
name: "GPT-5.1",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.13,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.1-codex": {
|
||||||
|
id: "gpt-5.1-codex",
|
||||||
|
name: "GPT-5.1 Codex",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.2": {
|
||||||
|
id: "gpt-5.2",
|
||||||
|
name: "GPT-5.2",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.2-codex": {
|
||||||
|
id: "gpt-5.2-codex",
|
||||||
|
name: "GPT-5.2 Codex",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.3-codex": {
|
||||||
|
id: "gpt-5.3-codex",
|
||||||
|
name: "GPT-5.3 Codex",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.4": {
|
||||||
|
id: "gpt-5.4",
|
||||||
|
name: "GPT-5.4",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1050000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.5": {
|
||||||
|
id: "gpt-5.5",
|
||||||
|
name: "GPT-5.5",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 30,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1050000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"o1": {
|
||||||
|
id: "o1",
|
||||||
|
name: "o1",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 15,
|
||||||
|
output: 60,
|
||||||
|
cacheRead: 7.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"o3": {
|
||||||
|
id: "o3",
|
||||||
|
name: "o3",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 8,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"o3-mini": {
|
||||||
|
id: "o3-mini",
|
||||||
|
name: "o3-mini",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.1,
|
||||||
|
output: 4.4,
|
||||||
|
cacheRead: 0.55,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"o3-pro": {
|
||||||
|
id: "o3-pro",
|
||||||
|
name: "o3-pro",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 20,
|
||||||
|
output: 80,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"o4-mini": {
|
||||||
|
id: "o4-mini",
|
||||||
|
name: "o4-mini",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/openai",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.1,
|
||||||
|
output: 4.4,
|
||||||
|
cacheRead: 0.28,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"workers-ai/@cf/moonshotai/kimi-k2.5": {
|
||||||
|
id: "workers-ai/@cf/moonshotai/kimi-k2.5",
|
||||||
|
name: "Kimi K2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/compat",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.1,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 256000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"workers-ai/@cf/moonshotai/kimi-k2.6": {
|
||||||
|
id: "workers-ai/@cf/moonshotai/kimi-k2.6",
|
||||||
|
name: "Kimi K2.6",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/compat",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.95,
|
||||||
|
output: 4,
|
||||||
|
cacheRead: 0.16,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 256000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"workers-ai/@cf/nvidia/nemotron-3-120b-a12b": {
|
||||||
|
id: "workers-ai/@cf/nvidia/nemotron-3-120b-a12b",
|
||||||
|
name: "Nemotron 3 Super 120B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/compat",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 1.5,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 256000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"workers-ai/@cf/zai-org/glm-4.7-flash": {
|
||||||
|
id: "workers-ai/@cf/zai-org/glm-4.7-flash",
|
||||||
|
name: "GLM-4.7-Flash",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-ai-gateway",
|
||||||
|
baseUrl: "https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/compat",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.06,
|
||||||
|
output: 0.4,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { anthropicMessagesApi } from "../api/anthropic-messages.lazy.ts";
|
||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { openAIResponsesApi } from "../api/openai-responses.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { CLOUDFLARE_AI_GATEWAY_MODELS } from "./cloudflare-ai-gateway.models.ts";
|
||||||
|
|
||||||
|
export function cloudflareAIGatewayProvider(): Provider<
|
||||||
|
"anthropic-messages" | "openai-completions" | "openai-responses"
|
||||||
|
> {
|
||||||
|
return createProvider({
|
||||||
|
id: "cloudflare-ai-gateway",
|
||||||
|
name: "Cloudflare AI Gateway",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Cloudflare API key", ["CLOUDFLARE_API_KEY"]) },
|
||||||
|
models: Object.values(CLOUDFLARE_AI_GATEWAY_MODELS),
|
||||||
|
api: {
|
||||||
|
"anthropic-messages": anthropicMessagesApi(),
|
||||||
|
"openai-completions": openAICompletionsApi(),
|
||||||
|
"openai-responses": openAIResponsesApi(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,205 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const CLOUDFLARE_WORKERS_AI_MODELS = {
|
||||||
|
"@cf/google/gemma-4-26b-a4b-it": {
|
||||||
|
id: "@cf/google/gemma-4-26b-a4b-it",
|
||||||
|
name: "Gemma 4 26B A4B IT",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-workers-ai",
|
||||||
|
baseUrl: "https://api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai/v1",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.3,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"@cf/ibm-granite/granite-4.0-h-micro": {
|
||||||
|
id: "@cf/ibm-granite/granite-4.0-h-micro",
|
||||||
|
name: "Granite 4.0 H Micro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-workers-ai",
|
||||||
|
baseUrl: "https://api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai/v1",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.017,
|
||||||
|
output: 0.112,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131000,
|
||||||
|
maxTokens: 131000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"@cf/meta/llama-3.3-70b-instruct-fp8-fast": {
|
||||||
|
id: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
||||||
|
name: "Llama 3.3 70B Instruct fp8 Fast",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-workers-ai",
|
||||||
|
baseUrl: "https://api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai/v1",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.293,
|
||||||
|
output: 2.253,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 24000,
|
||||||
|
maxTokens: 24000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"@cf/meta/llama-4-scout-17b-16e-instruct": {
|
||||||
|
id: "@cf/meta/llama-4-scout-17b-16e-instruct",
|
||||||
|
name: "Llama 4 Scout 17B 16E Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-workers-ai",
|
||||||
|
baseUrl: "https://api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai/v1",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.27,
|
||||||
|
output: 0.85,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"@cf/mistralai/mistral-small-3.1-24b-instruct": {
|
||||||
|
id: "@cf/mistralai/mistral-small-3.1-24b-instruct",
|
||||||
|
name: "Mistral Small 3.1 24B Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-workers-ai",
|
||||||
|
baseUrl: "https://api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai/v1",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.351,
|
||||||
|
output: 0.555,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"@cf/moonshotai/kimi-k2.6": {
|
||||||
|
id: "@cf/moonshotai/kimi-k2.6",
|
||||||
|
name: "Kimi K2.6",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-workers-ai",
|
||||||
|
baseUrl: "https://api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai/v1",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.95,
|
||||||
|
output: 4,
|
||||||
|
cacheRead: 0.16,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 256000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"@cf/nvidia/nemotron-3-120b-a12b": {
|
||||||
|
id: "@cf/nvidia/nemotron-3-120b-a12b",
|
||||||
|
name: "Nemotron 3 Super 120B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-workers-ai",
|
||||||
|
baseUrl: "https://api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai/v1",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 1.5,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 256000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"@cf/openai/gpt-oss-120b": {
|
||||||
|
id: "@cf/openai/gpt-oss-120b",
|
||||||
|
name: "GPT OSS 120B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-workers-ai",
|
||||||
|
baseUrl: "https://api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai/v1",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.35,
|
||||||
|
output: 0.75,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"@cf/openai/gpt-oss-20b": {
|
||||||
|
id: "@cf/openai/gpt-oss-20b",
|
||||||
|
name: "GPT OSS 20B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-workers-ai",
|
||||||
|
baseUrl: "https://api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai/v1",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.2,
|
||||||
|
output: 0.3,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"@cf/qwen/qwen3-30b-a3b-fp8": {
|
||||||
|
id: "@cf/qwen/qwen3-30b-a3b-fp8",
|
||||||
|
name: "Qwen3 30B A3b fp8",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-workers-ai",
|
||||||
|
baseUrl: "https://api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai/v1",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.0509,
|
||||||
|
output: 0.335,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 32768,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"@cf/zai-org/glm-4.7-flash": {
|
||||||
|
id: "@cf/zai-org/glm-4.7-flash",
|
||||||
|
name: "GLM-4.7-Flash",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "cloudflare-workers-ai",
|
||||||
|
baseUrl: "https://api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai/v1",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.0605,
|
||||||
|
output: 0.4,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { CLOUDFLARE_WORKERS_AI_MODELS } from "./cloudflare-workers-ai.models.ts";
|
||||||
|
|
||||||
|
export function cloudflareWorkersAIProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "cloudflare-workers-ai",
|
||||||
|
name: "Cloudflare Workers AI",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Cloudflare API key", ["CLOUDFLARE_API_KEY"]) },
|
||||||
|
models: Object.values(CLOUDFLARE_WORKERS_AI_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const DEEPSEEK_MODELS = {
|
||||||
|
"deepseek-v4-flash": {
|
||||||
|
id: "deepseek-v4-flash",
|
||||||
|
name: "DeepSeek V4 Flash",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "deepseek",
|
||||||
|
baseUrl: "https://api.deepseek.com",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max"},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.14,
|
||||||
|
output: 0.28,
|
||||||
|
cacheRead: 0.0028,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 384000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"deepseek-v4-pro": {
|
||||||
|
id: "deepseek-v4-pro",
|
||||||
|
name: "DeepSeek V4 Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "deepseek",
|
||||||
|
baseUrl: "https://api.deepseek.com",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max"},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.435,
|
||||||
|
output: 0.87,
|
||||||
|
cacheRead: 0.003625,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 384000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { DEEPSEEK_MODELS } from "./deepseek.models.ts";
|
||||||
|
|
||||||
|
export function deepseekProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "deepseek",
|
||||||
|
name: "DeepSeek",
|
||||||
|
baseUrl: "https://api.deepseek.com",
|
||||||
|
auth: { apiKey: envApiKeyAuth("DeepSeek API key", ["DEEPSEEK_API_KEY"]) },
|
||||||
|
models: Object.values(DEEPSEEK_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { registerApiProvider, unregisterApiProviders } from "../api-registry.ts";
|
import { registerApiProvider, unregisterApiProviders } from "../api-registry.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
import type {
|
import type {
|
||||||
AssistantMessage,
|
AssistantMessage,
|
||||||
AssistantMessageEventStream,
|
AssistantMessageEventStream,
|
||||||
@@ -125,6 +126,18 @@ export interface FauxProviderRegistration {
|
|||||||
unregister: () => void;
|
unregister: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FauxProviderHandle {
|
||||||
|
provider: Provider;
|
||||||
|
api: string;
|
||||||
|
models: [Model<string>, ...Model<string>[]];
|
||||||
|
getModel(): Model<string>;
|
||||||
|
getModel(modelId: string): Model<string> | undefined;
|
||||||
|
state: { callCount: number };
|
||||||
|
setResponses: (responses: FauxResponseStep[]) => void;
|
||||||
|
appendResponses: (responses: FauxResponseStep[]) => void;
|
||||||
|
getPendingResponseCount: () => number;
|
||||||
|
}
|
||||||
|
|
||||||
function estimateTokens(text: string): number {
|
function estimateTokens(text: string): number {
|
||||||
return Math.ceil(text.length / 4);
|
return Math.ceil(text.length / 4);
|
||||||
}
|
}
|
||||||
@@ -388,10 +401,9 @@ async function streamWithDeltas(
|
|||||||
stream.end(message);
|
stream.end(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function registerFauxProvider(options: RegisterFauxProviderOptions = {}): FauxProviderRegistration {
|
function createFauxCore(options: RegisterFauxProviderOptions) {
|
||||||
const api = options.api ?? randomId(DEFAULT_API);
|
const api = options.api ?? randomId(DEFAULT_API);
|
||||||
const provider = options.provider ?? DEFAULT_PROVIDER;
|
const provider = options.provider ?? DEFAULT_PROVIDER;
|
||||||
const sourceId = randomId("faux-provider");
|
|
||||||
const minTokenSize = Math.max(
|
const minTokenSize = Math.max(
|
||||||
1,
|
1,
|
||||||
Math.min(options.tokenSize?.min ?? DEFAULT_MIN_TOKEN_SIZE, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE),
|
Math.min(options.tokenSize?.min ?? DEFAULT_MIN_TOKEN_SIZE, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE),
|
||||||
@@ -467,8 +479,6 @@ export function registerFauxProvider(options: RegisterFauxProviderOptions = {}):
|
|||||||
const streamSimple: StreamFunction<string, SimpleStreamOptions> = (streamModel, context, streamOptions) =>
|
const streamSimple: StreamFunction<string, SimpleStreamOptions> = (streamModel, context, streamOptions) =>
|
||||||
stream(streamModel, context, streamOptions);
|
stream(streamModel, context, streamOptions);
|
||||||
|
|
||||||
registerApiProvider({ api, stream, streamSimple }, sourceId);
|
|
||||||
|
|
||||||
function getModel(): Model<string>;
|
function getModel(): Model<string>;
|
||||||
function getModel(requestedModelId: string): Model<string> | undefined;
|
function getModel(requestedModelId: string): Model<string> | undefined;
|
||||||
function getModel(requestedModelId?: string): Model<string> | undefined {
|
function getModel(requestedModelId?: string): Model<string> | undefined {
|
||||||
@@ -480,20 +490,69 @@ export function registerFauxProvider(options: RegisterFauxProviderOptions = {}):
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
api,
|
api,
|
||||||
|
provider,
|
||||||
models,
|
models,
|
||||||
|
stream,
|
||||||
|
streamSimple,
|
||||||
getModel,
|
getModel,
|
||||||
state,
|
state,
|
||||||
setResponses(responses) {
|
setResponses(responses: FauxResponseStep[]) {
|
||||||
pendingResponses = [...responses];
|
pendingResponses = [...responses];
|
||||||
},
|
},
|
||||||
appendResponses(responses) {
|
appendResponses(responses: FauxResponseStep[]) {
|
||||||
pendingResponses.push(...responses);
|
pendingResponses.push(...responses);
|
||||||
},
|
},
|
||||||
getPendingResponseCount() {
|
getPendingResponseCount() {
|
||||||
return pendingResponses.length;
|
return pendingResponses.length;
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Registers the faux api into the legacy global api-registry. */
|
||||||
|
export function registerFauxProvider(options: RegisterFauxProviderOptions = {}): FauxProviderRegistration {
|
||||||
|
const core = createFauxCore(options);
|
||||||
|
const sourceId = randomId("faux-provider");
|
||||||
|
registerApiProvider({ api: core.api, stream: core.stream, streamSimple: core.streamSimple }, sourceId);
|
||||||
|
return {
|
||||||
|
api: core.api,
|
||||||
|
models: core.models,
|
||||||
|
getModel: core.getModel,
|
||||||
|
state: core.state,
|
||||||
|
setResponses: core.setResponses,
|
||||||
|
appendResponses: core.appendResponses,
|
||||||
|
getPendingResponseCount: core.getPendingResponseCount,
|
||||||
unregister() {
|
unregister() {
|
||||||
unregisterApiProviders(sourceId);
|
unregisterApiProviders(sourceId);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Faux provider for tests built on explicit `Models` collections:
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const faux = fauxProvider();
|
||||||
|
* const models = createModels();
|
||||||
|
* models.setProvider(faux.provider);
|
||||||
|
* faux.setResponses([fauxAssistantMessage("hi")]);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export function fauxProvider(options: RegisterFauxProviderOptions = {}): FauxProviderHandle {
|
||||||
|
const core = createFauxCore(options);
|
||||||
|
const provider = createProvider({
|
||||||
|
id: core.provider,
|
||||||
|
auth: { apiKey: { name: "Faux", resolve: async () => ({ auth: {} }) } },
|
||||||
|
models: core.models,
|
||||||
|
api: { stream: core.stream, streamSimple: core.streamSimple },
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
provider,
|
||||||
|
api: core.api,
|
||||||
|
models: core.models,
|
||||||
|
getModel: core.getModel,
|
||||||
|
state: core.state,
|
||||||
|
setResponses: core.setResponses,
|
||||||
|
appendResponses: core.appendResponses,
|
||||||
|
getPendingResponseCount: core.getPendingResponseCount,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,241 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const FIREWORKS_MODELS = {
|
||||||
|
"accounts/fireworks/models/deepseek-v4-flash": {
|
||||||
|
id: "accounts/fireworks/models/deepseek-v4-flash",
|
||||||
|
name: "DeepSeek V4 Flash",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "fireworks",
|
||||||
|
baseUrl: "https://api.fireworks.ai/inference",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true,"supportsEagerToolInputStreaming":false,"supportsCacheControlOnTools":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.14,
|
||||||
|
output: 0.28,
|
||||||
|
cacheRead: 0.03,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 384000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"accounts/fireworks/models/deepseek-v4-pro": {
|
||||||
|
id: "accounts/fireworks/models/deepseek-v4-pro",
|
||||||
|
name: "DeepSeek V4 Pro",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "fireworks",
|
||||||
|
baseUrl: "https://api.fireworks.ai/inference",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true,"supportsEagerToolInputStreaming":false,"supportsCacheControlOnTools":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.74,
|
||||||
|
output: 3.48,
|
||||||
|
cacheRead: 0.145,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 384000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"accounts/fireworks/models/glm-5p1": {
|
||||||
|
id: "accounts/fireworks/models/glm-5p1",
|
||||||
|
name: "GLM 5.1",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "fireworks",
|
||||||
|
baseUrl: "https://api.fireworks.ai/inference",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true,"supportsEagerToolInputStreaming":false,"supportsCacheControlOnTools":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.4,
|
||||||
|
output: 4.4,
|
||||||
|
cacheRead: 0.26,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 202800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"accounts/fireworks/models/gpt-oss-120b": {
|
||||||
|
id: "accounts/fireworks/models/gpt-oss-120b",
|
||||||
|
name: "GPT OSS 120B",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "fireworks",
|
||||||
|
baseUrl: "https://api.fireworks.ai/inference",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true,"supportsEagerToolInputStreaming":false,"supportsCacheControlOnTools":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.15,
|
||||||
|
output: 0.6,
|
||||||
|
cacheRead: 0.015,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"accounts/fireworks/models/gpt-oss-20b": {
|
||||||
|
id: "accounts/fireworks/models/gpt-oss-20b",
|
||||||
|
name: "GPT OSS 20B",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "fireworks",
|
||||||
|
baseUrl: "https://api.fireworks.ai/inference",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true,"supportsEagerToolInputStreaming":false,"supportsCacheControlOnTools":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.07,
|
||||||
|
output: 0.3,
|
||||||
|
cacheRead: 0.035,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"accounts/fireworks/models/kimi-k2p5": {
|
||||||
|
id: "accounts/fireworks/models/kimi-k2p5",
|
||||||
|
name: "Kimi K2.5",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "fireworks",
|
||||||
|
baseUrl: "https://api.fireworks.ai/inference",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true,"supportsEagerToolInputStreaming":false,"supportsCacheControlOnTools":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.1,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 256000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"accounts/fireworks/models/kimi-k2p6": {
|
||||||
|
id: "accounts/fireworks/models/kimi-k2p6",
|
||||||
|
name: "Kimi K2.6",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "fireworks",
|
||||||
|
baseUrl: "https://api.fireworks.ai/inference",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true,"supportsEagerToolInputStreaming":false,"supportsCacheControlOnTools":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.95,
|
||||||
|
output: 4,
|
||||||
|
cacheRead: 0.16,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262000,
|
||||||
|
maxTokens: 262000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"accounts/fireworks/models/minimax-m2p5": {
|
||||||
|
id: "accounts/fireworks/models/minimax-m2p5",
|
||||||
|
name: "MiniMax-M2.5",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "fireworks",
|
||||||
|
baseUrl: "https://api.fireworks.ai/inference",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true,"supportsEagerToolInputStreaming":false,"supportsCacheControlOnTools":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0.03,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 196608,
|
||||||
|
maxTokens: 196608,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"accounts/fireworks/models/minimax-m2p7": {
|
||||||
|
id: "accounts/fireworks/models/minimax-m2p7",
|
||||||
|
name: "MiniMax-M2.7",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "fireworks",
|
||||||
|
baseUrl: "https://api.fireworks.ai/inference",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true,"supportsEagerToolInputStreaming":false,"supportsCacheControlOnTools":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0.06,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 196608,
|
||||||
|
maxTokens: 196608,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"accounts/fireworks/models/qwen3p6-plus": {
|
||||||
|
id: "accounts/fireworks/models/qwen3p6-plus",
|
||||||
|
name: "Qwen 3.6 Plus",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "fireworks",
|
||||||
|
baseUrl: "https://api.fireworks.ai/inference",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true,"supportsEagerToolInputStreaming":false,"supportsCacheControlOnTools":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.1,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"accounts/fireworks/routers/glm-5p1-fast": {
|
||||||
|
id: "accounts/fireworks/routers/glm-5p1-fast",
|
||||||
|
name: "GLM 5.1 Fast",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "fireworks",
|
||||||
|
baseUrl: "https://api.fireworks.ai/inference",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true,"supportsEagerToolInputStreaming":false,"supportsCacheControlOnTools":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 2.8,
|
||||||
|
output: 8.8,
|
||||||
|
cacheRead: 0.52,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 202800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"accounts/fireworks/routers/kimi-k2p6-fast": {
|
||||||
|
id: "accounts/fireworks/routers/kimi-k2p6-fast",
|
||||||
|
name: "Kimi K2.6 Fast",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "fireworks",
|
||||||
|
baseUrl: "https://api.fireworks.ai/inference",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true,"supportsEagerToolInputStreaming":false,"supportsCacheControlOnTools":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 8,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262000,
|
||||||
|
maxTokens: 262000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"accounts/fireworks/routers/kimi-k2p6-turbo": {
|
||||||
|
id: "accounts/fireworks/routers/kimi-k2p6-turbo",
|
||||||
|
name: "Kimi K2.6 Turbo",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "fireworks",
|
||||||
|
baseUrl: "https://api.fireworks.ai/inference",
|
||||||
|
compat: {"sendSessionAffinityHeaders":true,"supportsEagerToolInputStreaming":false,"supportsCacheControlOnTools":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 8,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262000,
|
||||||
|
maxTokens: 262000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { anthropicMessagesApi } from "../api/anthropic-messages.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { FIREWORKS_MODELS } from "./fireworks.models.ts";
|
||||||
|
|
||||||
|
export function fireworksProvider(): Provider<"anthropic-messages"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "fireworks",
|
||||||
|
name: "Fireworks",
|
||||||
|
baseUrl: "https://api.fireworks.ai/inference",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Fireworks API key", ["FIREWORKS_API_KEY"]) },
|
||||||
|
models: Object.values(FIREWORKS_MODELS),
|
||||||
|
api: anthropicMessagesApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,427 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const GITHUB_COPILOT_MODELS = {
|
||||||
|
"claude-haiku-4.5": {
|
||||||
|
id: "claude-haiku-4.5",
|
||||||
|
name: "Claude Haiku 4.5 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
compat: {"supportsEagerToolInputStreaming":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 5,
|
||||||
|
cacheRead: 0.1,
|
||||||
|
cacheWrite: 1.25,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4.5": {
|
||||||
|
id: "claude-opus-4.5",
|
||||||
|
name: "Claude Opus 4.5 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4.6": {
|
||||||
|
id: "claude-opus-4.6",
|
||||||
|
name: "Claude Opus 4.6",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
compat: {"forceAdaptiveThinking":true},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"max"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4.7": {
|
||||||
|
id: "claude-opus-4.7",
|
||||||
|
name: "Claude Opus 4.7",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
compat: {"forceAdaptiveThinking":true,"supportsTemperature":false},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4.8": {
|
||||||
|
id: "claude-opus-4.8",
|
||||||
|
name: "Claude Opus 4.8",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
compat: {"forceAdaptiveThinking":true,"supportsTemperature":false},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-sonnet-4": {
|
||||||
|
id: "claude-sonnet-4",
|
||||||
|
name: "Claude Sonnet 4 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
compat: {"supportsEagerToolInputStreaming":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 216000,
|
||||||
|
maxTokens: 16000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-sonnet-4.5": {
|
||||||
|
id: "claude-sonnet-4.5",
|
||||||
|
name: "Claude Sonnet 4.5 (latest)",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
compat: {"supportsEagerToolInputStreaming":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-sonnet-4.6": {
|
||||||
|
id: "claude-sonnet-4.6",
|
||||||
|
name: "Claude Sonnet 4.6",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
compat: {"forceAdaptiveThinking":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"gemini-2.5-pro": {
|
||||||
|
id: "gemini-2.5-pro",
|
||||||
|
name: "Gemini 2.5 Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"gemini-3-flash-preview": {
|
||||||
|
id: "gemini-3-flash-preview",
|
||||||
|
name: "Gemini 3 Flash Preview",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.05,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"gemini-3.1-pro-preview": {
|
||||||
|
id: "gemini-3.1-pro-preview",
|
||||||
|
name: "Gemini 3.1 Pro Preview",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 12,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"gemini-3.5-flash": {
|
||||||
|
id: "gemini-3.5-flash",
|
||||||
|
name: "Gemini 3.5 Flash",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.5,
|
||||||
|
output: 9,
|
||||||
|
cacheRead: 0.15,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"gpt-4.1": {
|
||||||
|
id: "gpt-4.1",
|
||||||
|
name: "GPT-4.1",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 8,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"gpt-5-mini": {
|
||||||
|
id: "gpt-5-mini",
|
||||||
|
name: "GPT-5 Mini",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":"low"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.025,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 264000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.2": {
|
||||||
|
id: "gpt-5.2",
|
||||||
|
name: "GPT-5.2",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":"low","xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.2-codex": {
|
||||||
|
id: "gpt-5.2-codex",
|
||||||
|
name: "GPT-5.2 Codex",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":"low","xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.3-codex": {
|
||||||
|
id: "gpt-5.3-codex",
|
||||||
|
name: "GPT-5.3 Codex",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":"low","xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.4": {
|
||||||
|
id: "gpt-5.4",
|
||||||
|
name: "GPT-5.4",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":"low","xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.4-mini": {
|
||||||
|
id: "gpt-5.4-mini",
|
||||||
|
name: "GPT-5.4 mini",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":"low","xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.75,
|
||||||
|
output: 4.5,
|
||||||
|
cacheRead: 0.075,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.4-nano": {
|
||||||
|
id: "gpt-5.4-nano",
|
||||||
|
name: "GPT-5.4 nano",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":"low","xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.2,
|
||||||
|
output: 1.25,
|
||||||
|
cacheRead: 0.02,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.5": {
|
||||||
|
id: "gpt-5.5",
|
||||||
|
name: "GPT-5.5",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":"low","xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 30,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"raptor-mini": {
|
||||||
|
id: "raptor-mini",
|
||||||
|
name: "Raptor mini",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "github-copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.025,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { anthropicMessagesApi } from "../api/anthropic-messages.lazy.ts";
|
||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { openAIResponsesApi } from "../api/openai-responses.lazy.ts";
|
||||||
|
import { envApiKeyAuth, lazyOAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { loadGitHubCopilotOAuth } from "../utils/oauth/load.ts";
|
||||||
|
import { GITHUB_COPILOT_MODELS } from "./github-copilot.models.ts";
|
||||||
|
|
||||||
|
export function githubCopilotProvider(): Provider<"anthropic-messages" | "openai-completions" | "openai-responses"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "github-copilot",
|
||||||
|
name: "GitHub Copilot",
|
||||||
|
baseUrl: "https://api.individual.githubcopilot.com",
|
||||||
|
auth: {
|
||||||
|
apiKey: envApiKeyAuth("GitHub Copilot token", ["COPILOT_GITHUB_TOKEN"]),
|
||||||
|
oauth: lazyOAuth({ name: "GitHub Copilot", load: loadGitHubCopilotOAuth }),
|
||||||
|
},
|
||||||
|
models: Object.values(GITHUB_COPILOT_MODELS),
|
||||||
|
api: {
|
||||||
|
"anthropic-messages": anthropicMessagesApi(),
|
||||||
|
"openai-completions": openAICompletionsApi(),
|
||||||
|
"openai-responses": openAIResponsesApi(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,232 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const GOOGLE_VERTEX_MODELS = {
|
||||||
|
"gemini-1.5-flash": {
|
||||||
|
id: "gemini-1.5-flash",
|
||||||
|
name: "Gemini 1.5 Flash (Vertex)",
|
||||||
|
api: "google-vertex",
|
||||||
|
provider: "google-vertex",
|
||||||
|
baseUrl: "https://{location}-aiplatform.googleapis.com",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.075,
|
||||||
|
output: 0.3,
|
||||||
|
cacheRead: 0.01875,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"google-vertex">,
|
||||||
|
"gemini-1.5-flash-8b": {
|
||||||
|
id: "gemini-1.5-flash-8b",
|
||||||
|
name: "Gemini 1.5 Flash-8B (Vertex)",
|
||||||
|
api: "google-vertex",
|
||||||
|
provider: "google-vertex",
|
||||||
|
baseUrl: "https://{location}-aiplatform.googleapis.com",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.0375,
|
||||||
|
output: 0.15,
|
||||||
|
cacheRead: 0.01,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"google-vertex">,
|
||||||
|
"gemini-1.5-pro": {
|
||||||
|
id: "gemini-1.5-pro",
|
||||||
|
name: "Gemini 1.5 Pro (Vertex)",
|
||||||
|
api: "google-vertex",
|
||||||
|
provider: "google-vertex",
|
||||||
|
baseUrl: "https://{location}-aiplatform.googleapis.com",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 5,
|
||||||
|
cacheRead: 0.3125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"google-vertex">,
|
||||||
|
"gemini-2.0-flash": {
|
||||||
|
id: "gemini-2.0-flash",
|
||||||
|
name: "Gemini 2.0 Flash (Vertex)",
|
||||||
|
api: "google-vertex",
|
||||||
|
provider: "google-vertex",
|
||||||
|
baseUrl: "https://{location}-aiplatform.googleapis.com",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.15,
|
||||||
|
output: 0.6,
|
||||||
|
cacheRead: 0.0375,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"google-vertex">,
|
||||||
|
"gemini-2.0-flash-lite": {
|
||||||
|
id: "gemini-2.0-flash-lite",
|
||||||
|
name: "Gemini 2.0 Flash Lite (Vertex)",
|
||||||
|
api: "google-vertex",
|
||||||
|
provider: "google-vertex",
|
||||||
|
baseUrl: "https://{location}-aiplatform.googleapis.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.075,
|
||||||
|
output: 0.3,
|
||||||
|
cacheRead: 0.01875,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-vertex">,
|
||||||
|
"gemini-2.5-flash": {
|
||||||
|
id: "gemini-2.5-flash",
|
||||||
|
name: "Gemini 2.5 Flash (Vertex)",
|
||||||
|
api: "google-vertex",
|
||||||
|
provider: "google-vertex",
|
||||||
|
baseUrl: "https://{location}-aiplatform.googleapis.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 2.5,
|
||||||
|
cacheRead: 0.03,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-vertex">,
|
||||||
|
"gemini-2.5-flash-lite": {
|
||||||
|
id: "gemini-2.5-flash-lite",
|
||||||
|
name: "Gemini 2.5 Flash Lite (Vertex)",
|
||||||
|
api: "google-vertex",
|
||||||
|
provider: "google-vertex",
|
||||||
|
baseUrl: "https://{location}-aiplatform.googleapis.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.4,
|
||||||
|
cacheRead: 0.01,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-vertex">,
|
||||||
|
"gemini-2.5-flash-lite-preview-09-2025": {
|
||||||
|
id: "gemini-2.5-flash-lite-preview-09-2025",
|
||||||
|
name: "Gemini 2.5 Flash Lite Preview 09-25 (Vertex)",
|
||||||
|
api: "google-vertex",
|
||||||
|
provider: "google-vertex",
|
||||||
|
baseUrl: "https://{location}-aiplatform.googleapis.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.4,
|
||||||
|
cacheRead: 0.01,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-vertex">,
|
||||||
|
"gemini-2.5-pro": {
|
||||||
|
id: "gemini-2.5-pro",
|
||||||
|
name: "Gemini 2.5 Pro (Vertex)",
|
||||||
|
api: "google-vertex",
|
||||||
|
provider: "google-vertex",
|
||||||
|
baseUrl: "https://{location}-aiplatform.googleapis.com",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-vertex">,
|
||||||
|
"gemini-3-flash-preview": {
|
||||||
|
id: "gemini-3-flash-preview",
|
||||||
|
name: "Gemini 3 Flash Preview (Vertex)",
|
||||||
|
api: "google-vertex",
|
||||||
|
provider: "google-vertex",
|
||||||
|
baseUrl: "https://{location}-aiplatform.googleapis.com",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.05,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-vertex">,
|
||||||
|
"gemini-3-pro-preview": {
|
||||||
|
id: "gemini-3-pro-preview",
|
||||||
|
name: "Gemini 3 Pro Preview (Vertex)",
|
||||||
|
api: "google-vertex",
|
||||||
|
provider: "google-vertex",
|
||||||
|
baseUrl: "https://{location}-aiplatform.googleapis.com",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":null,"low":"LOW","medium":null,"high":"HIGH"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 12,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"google-vertex">,
|
||||||
|
"gemini-3.1-pro-preview": {
|
||||||
|
id: "gemini-3.1-pro-preview",
|
||||||
|
name: "Gemini 3.1 Pro Preview (Vertex)",
|
||||||
|
api: "google-vertex",
|
||||||
|
provider: "google-vertex",
|
||||||
|
baseUrl: "https://{location}-aiplatform.googleapis.com",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":null,"low":"LOW","medium":null,"high":"HIGH"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 12,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-vertex">,
|
||||||
|
"gemini-3.1-pro-preview-customtools": {
|
||||||
|
id: "gemini-3.1-pro-preview-customtools",
|
||||||
|
name: "Gemini 3.1 Pro Preview Custom Tools (Vertex)",
|
||||||
|
api: "google-vertex",
|
||||||
|
provider: "google-vertex",
|
||||||
|
baseUrl: "https://{location}-aiplatform.googleapis.com",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":null,"low":"LOW","medium":null,"high":"HIGH"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 12,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-vertex">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import { googleVertexApi } from "../api/google-vertex.lazy.ts";
|
||||||
|
import type { ApiKeyAuth } from "../auth/types.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { GOOGLE_VERTEX_MODELS } from "./google-vertex.models.ts";
|
||||||
|
|
||||||
|
const VERTEX_ADC_PATH = "~/.config/gcloud/application_default_credentials.json";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vertex accepts an explicit API key or Application Default Credentials
|
||||||
|
* (`gcloud auth application-default login`). ADC additionally requires
|
||||||
|
* project and location env vars, which the implementation reads itself.
|
||||||
|
*/
|
||||||
|
const vertexAuth: ApiKeyAuth = {
|
||||||
|
name: "Google Cloud credentials",
|
||||||
|
resolve: async ({ ctx, credential }) => {
|
||||||
|
const key = credential?.key ?? (await ctx.env("GOOGLE_CLOUD_API_KEY"));
|
||||||
|
if (key) return { auth: { apiKey: key }, source: credential?.key ? "stored credential" : "GOOGLE_CLOUD_API_KEY" };
|
||||||
|
|
||||||
|
const adcPath = await ctx.env("GOOGLE_APPLICATION_CREDENTIALS");
|
||||||
|
const hasCredentials = await ctx.fileExists(adcPath ?? VERTEX_ADC_PATH);
|
||||||
|
const hasProject = Boolean((await ctx.env("GOOGLE_CLOUD_PROJECT")) ?? (await ctx.env("GCLOUD_PROJECT")));
|
||||||
|
const hasLocation = Boolean(await ctx.env("GOOGLE_CLOUD_LOCATION"));
|
||||||
|
if (hasCredentials && hasProject && hasLocation) {
|
||||||
|
return { auth: {}, source: "gcloud application default credentials" };
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function googleVertexProvider(): Provider<"google-vertex"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "google-vertex",
|
||||||
|
name: "Google Vertex AI",
|
||||||
|
auth: { apiKey: vertexAuth },
|
||||||
|
models: Object.values(GOOGLE_VERTEX_MODELS),
|
||||||
|
api: googleVertexApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,288 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const GOOGLE_MODELS = {
|
||||||
|
"gemini-2.0-flash": {
|
||||||
|
id: "gemini-2.0-flash",
|
||||||
|
name: "Gemini 2.0 Flash",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.4,
|
||||||
|
cacheRead: 0.025,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-2.0-flash-lite": {
|
||||||
|
id: "gemini-2.0-flash-lite",
|
||||||
|
name: "Gemini 2.0 Flash-Lite",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.075,
|
||||||
|
output: 0.3,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-2.5-flash": {
|
||||||
|
id: "gemini-2.5-flash",
|
||||||
|
name: "Gemini 2.5 Flash",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 2.5,
|
||||||
|
cacheRead: 0.03,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-2.5-flash-lite": {
|
||||||
|
id: "gemini-2.5-flash-lite",
|
||||||
|
name: "Gemini 2.5 Flash-Lite",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.4,
|
||||||
|
cacheRead: 0.01,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-2.5-pro": {
|
||||||
|
id: "gemini-2.5-pro",
|
||||||
|
name: "Gemini 2.5 Pro",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-3-flash-preview": {
|
||||||
|
id: "gemini-3-flash-preview",
|
||||||
|
name: "Gemini 3 Flash Preview",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.05,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-3-pro-preview": {
|
||||||
|
id: "gemini-3-pro-preview",
|
||||||
|
name: "Gemini 3 Pro Preview",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":null,"low":"LOW","medium":null,"high":"HIGH"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 12,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-3.1-flash-lite": {
|
||||||
|
id: "gemini-3.1-flash-lite",
|
||||||
|
name: "Gemini 3.1 Flash Lite",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 1.5,
|
||||||
|
cacheRead: 0.025,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-3.1-flash-lite-preview": {
|
||||||
|
id: "gemini-3.1-flash-lite-preview",
|
||||||
|
name: "Gemini 3.1 Flash Lite Preview",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 1.5,
|
||||||
|
cacheRead: 0.025,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-3.1-pro-preview": {
|
||||||
|
id: "gemini-3.1-pro-preview",
|
||||||
|
name: "Gemini 3.1 Pro Preview",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":null,"low":"LOW","medium":null,"high":"HIGH"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 12,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-3.1-pro-preview-customtools": {
|
||||||
|
id: "gemini-3.1-pro-preview-customtools",
|
||||||
|
name: "Gemini 3.1 Pro Preview Custom Tools",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":null,"low":"LOW","medium":null,"high":"HIGH"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 12,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-3.5-flash": {
|
||||||
|
id: "gemini-3.5-flash",
|
||||||
|
name: "Gemini 3.5 Flash",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.5,
|
||||||
|
output: 9,
|
||||||
|
cacheRead: 0.15,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-flash-latest": {
|
||||||
|
id: "gemini-flash-latest",
|
||||||
|
name: "Gemini Flash Latest",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 2.5,
|
||||||
|
cacheRead: 0.075,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-flash-lite-latest": {
|
||||||
|
id: "gemini-flash-lite-latest",
|
||||||
|
name: "Gemini Flash-Lite Latest",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.4,
|
||||||
|
cacheRead: 0.025,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemma-4-26b-a4b-it": {
|
||||||
|
id: "gemma-4-26b-a4b-it",
|
||||||
|
name: "Gemma 4 26B A4B IT",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":"MINIMAL","low":null,"medium":null,"high":"HIGH"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemma-4-31b-it": {
|
||||||
|
id: "gemma-4-31b-it",
|
||||||
|
name: "Gemma 4 31B IT",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":"MINIMAL","low":null,"medium":null,"high":"HIGH"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { googleGenerativeAIApi } from "../api/google-generative-ai.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { GOOGLE_MODELS } from "./google.models.ts";
|
||||||
|
|
||||||
|
export function googleProvider(): Provider<"google-generative-ai"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "google",
|
||||||
|
name: "Google",
|
||||||
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Gemini API key", ["GEMINI_API_KEY"]) },
|
||||||
|
models: Object.values(GOOGLE_MODELS),
|
||||||
|
api: googleGenerativeAIApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const GROQ_MODELS = {
|
||||||
|
"llama-3.1-8b-instant": {
|
||||||
|
id: "llama-3.1-8b-instant",
|
||||||
|
name: "Llama 3.1 8B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "groq",
|
||||||
|
baseUrl: "https://api.groq.com/openai/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.05,
|
||||||
|
output: 0.08,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"llama-3.3-70b-versatile": {
|
||||||
|
id: "llama-3.3-70b-versatile",
|
||||||
|
name: "Llama 3.3 70B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "groq",
|
||||||
|
baseUrl: "https://api.groq.com/openai/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.59,
|
||||||
|
output: 0.79,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"meta-llama/llama-4-scout-17b-16e-instruct": {
|
||||||
|
id: "meta-llama/llama-4-scout-17b-16e-instruct",
|
||||||
|
name: "Llama 4 Scout 17B 16E",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "groq",
|
||||||
|
baseUrl: "https://api.groq.com/openai/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.11,
|
||||||
|
output: 0.34,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"openai/gpt-oss-120b": {
|
||||||
|
id: "openai/gpt-oss-120b",
|
||||||
|
name: "GPT OSS 120B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "groq",
|
||||||
|
baseUrl: "https://api.groq.com/openai/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.15,
|
||||||
|
output: 0.6,
|
||||||
|
cacheRead: 0.075,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"openai/gpt-oss-20b": {
|
||||||
|
id: "openai/gpt-oss-20b",
|
||||||
|
name: "GPT OSS 20B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "groq",
|
||||||
|
baseUrl: "https://api.groq.com/openai/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.075,
|
||||||
|
output: 0.3,
|
||||||
|
cacheRead: 0.0375,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"openai/gpt-oss-safeguard-20b": {
|
||||||
|
id: "openai/gpt-oss-safeguard-20b",
|
||||||
|
name: "Safety GPT OSS 20B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "groq",
|
||||||
|
baseUrl: "https://api.groq.com/openai/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.075,
|
||||||
|
output: 0.3,
|
||||||
|
cacheRead: 0.037,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"qwen/qwen3-32b": {
|
||||||
|
id: "qwen/qwen3-32b",
|
||||||
|
name: "Qwen3-32B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "groq",
|
||||||
|
baseUrl: "https://api.groq.com/openai/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"default"},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.29,
|
||||||
|
output: 0.59,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 40960,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { GROQ_MODELS } from "./groq.models.ts";
|
||||||
|
|
||||||
|
export function groqProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "groq",
|
||||||
|
name: "Groq",
|
||||||
|
baseUrl: "https://api.groq.com/openai/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Groq API key", ["GROQ_API_KEY"]) },
|
||||||
|
models: Object.values(GROQ_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,403 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const HUGGINGFACE_MODELS = {
|
||||||
|
"MiniMaxAI/MiniMax-M2.1": {
|
||||||
|
id: "MiniMaxAI/MiniMax-M2.1",
|
||||||
|
name: "MiniMax-M2.1",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"MiniMaxAI/MiniMax-M2.5": {
|
||||||
|
id: "MiniMaxAI/MiniMax-M2.5",
|
||||||
|
name: "MiniMax-M2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0.03,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"MiniMaxAI/MiniMax-M2.7": {
|
||||||
|
id: "MiniMaxAI/MiniMax-M2.7",
|
||||||
|
name: "MiniMax-M2.7",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0.06,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"Qwen/Qwen3-235B-A22B-Thinking-2507": {
|
||||||
|
id: "Qwen/Qwen3-235B-A22B-Thinking-2507",
|
||||||
|
name: "Qwen3-235B-A22B-Thinking-2507",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"Qwen/Qwen3-Coder-480B-A35B-Instruct": {
|
||||||
|
id: "Qwen/Qwen3-Coder-480B-A35B-Instruct",
|
||||||
|
name: "Qwen3-Coder-480B-A35B-Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 66536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"Qwen/Qwen3-Coder-Next": {
|
||||||
|
id: "Qwen/Qwen3-Coder-Next",
|
||||||
|
name: "Qwen3-Coder-Next",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.2,
|
||||||
|
output: 1.5,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"Qwen/Qwen3-Next-80B-A3B-Instruct": {
|
||||||
|
id: "Qwen/Qwen3-Next-80B-A3B-Instruct",
|
||||||
|
name: "Qwen3-Next-80B-A3B-Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 1,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 66536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"Qwen/Qwen3-Next-80B-A3B-Thinking": {
|
||||||
|
id: "Qwen/Qwen3-Next-80B-A3B-Thinking",
|
||||||
|
name: "Qwen3-Next-80B-A3B-Thinking",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"Qwen/Qwen3.5-397B-A17B": {
|
||||||
|
id: "Qwen/Qwen3.5-397B-A17B",
|
||||||
|
name: "Qwen3.5-397B-A17B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 3.6,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"XiaomiMiMo/MiMo-V2-Flash": {
|
||||||
|
id: "XiaomiMiMo/MiMo-V2-Flash",
|
||||||
|
name: "MiMo-V2-Flash",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.3,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"deepseek-ai/DeepSeek-R1-0528": {
|
||||||
|
id: "deepseek-ai/DeepSeek-R1-0528",
|
||||||
|
name: "DeepSeek-R1-0528",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 5,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 163840,
|
||||||
|
maxTokens: 163840,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"deepseek-ai/DeepSeek-V3.2": {
|
||||||
|
id: "deepseek-ai/DeepSeek-V3.2",
|
||||||
|
name: "DeepSeek-V3.2",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.28,
|
||||||
|
output: 0.4,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 163840,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"deepseek-ai/DeepSeek-V4-Pro": {
|
||||||
|
id: "deepseek-ai/DeepSeek-V4-Pro",
|
||||||
|
name: "DeepSeek V4 Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.435,
|
||||||
|
output: 0.87,
|
||||||
|
cacheRead: 0.003625,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 393216,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"moonshotai/Kimi-K2-Instruct": {
|
||||||
|
id: "moonshotai/Kimi-K2-Instruct",
|
||||||
|
name: "Kimi-K2-Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"moonshotai/Kimi-K2-Instruct-0905": {
|
||||||
|
id: "moonshotai/Kimi-K2-Instruct-0905",
|
||||||
|
name: "Kimi-K2-Instruct-0905",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"moonshotai/Kimi-K2-Thinking": {
|
||||||
|
id: "moonshotai/Kimi-K2-Thinking",
|
||||||
|
name: "Kimi-K2-Thinking",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 2.5,
|
||||||
|
cacheRead: 0.15,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"moonshotai/Kimi-K2.5": {
|
||||||
|
id: "moonshotai/Kimi-K2.5",
|
||||||
|
name: "Kimi-K2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.1,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"moonshotai/Kimi-K2.6": {
|
||||||
|
id: "moonshotai/Kimi-K2.6",
|
||||||
|
name: "Kimi-K2.6",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.95,
|
||||||
|
output: 4,
|
||||||
|
cacheRead: 0.16,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"zai-org/GLM-4.7": {
|
||||||
|
id: "zai-org/GLM-4.7",
|
||||||
|
name: "GLM-4.7",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 2.2,
|
||||||
|
cacheRead: 0.11,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"zai-org/GLM-4.7-Flash": {
|
||||||
|
id: "zai-org/GLM-4.7-Flash",
|
||||||
|
name: "GLM-4.7-Flash",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"zai-org/GLM-5": {
|
||||||
|
id: "zai-org/GLM-5",
|
||||||
|
name: "GLM-5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 3.2,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 202752,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"zai-org/GLM-5.1": {
|
||||||
|
id: "zai-org/GLM-5.1",
|
||||||
|
name: "GLM-5.1",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "huggingface",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
compat: {"supportsDeveloperRole":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 3.2,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 202752,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { HUGGINGFACE_MODELS } from "./huggingface.models.ts";
|
||||||
|
|
||||||
|
export function huggingfaceProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "huggingface",
|
||||||
|
name: "Hugging Face",
|
||||||
|
baseUrl: "https://router.huggingface.co/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Hugging Face token", ["HF_TOKEN"]) },
|
||||||
|
models: Object.values(HUGGINGFACE_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const KIMI_CODING_MODELS = {
|
||||||
|
"kimi-for-coding": {
|
||||||
|
id: "kimi-for-coding",
|
||||||
|
name: "Kimi For Coding",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "kimi-coding",
|
||||||
|
baseUrl: "https://api.kimi.com/coding",
|
||||||
|
headers: {"User-Agent":"KimiCLI/1.5"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"kimi-k2-thinking": {
|
||||||
|
id: "kimi-k2-thinking",
|
||||||
|
name: "Kimi K2 Thinking",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "kimi-coding",
|
||||||
|
baseUrl: "https://api.kimi.com/coding",
|
||||||
|
headers: {"User-Agent":"KimiCLI/1.5"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { anthropicMessagesApi } from "../api/anthropic-messages.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { KIMI_CODING_MODELS } from "./kimi-coding.models.ts";
|
||||||
|
|
||||||
|
export function kimiCodingProvider(): Provider<"anthropic-messages"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "kimi-coding",
|
||||||
|
name: "Kimi For Coding",
|
||||||
|
baseUrl: "https://api.kimi.com/coding",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Kimi API key", ["KIMI_API_KEY"]) },
|
||||||
|
models: Object.values(KIMI_CODING_MODELS),
|
||||||
|
api: anthropicMessagesApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const MINIMAX_CN_MODELS = {
|
||||||
|
"MiniMax-M2.7": {
|
||||||
|
id: "MiniMax-M2.7",
|
||||||
|
name: "MiniMax-M2.7",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "minimax-cn",
|
||||||
|
baseUrl: "https://api.minimaxi.com/anthropic",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0.06,
|
||||||
|
cacheWrite: 0.375,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"MiniMax-M2.7-highspeed": {
|
||||||
|
id: "MiniMax-M2.7-highspeed",
|
||||||
|
name: "MiniMax-M2.7-highspeed",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "minimax-cn",
|
||||||
|
baseUrl: "https://api.minimaxi.com/anthropic",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 2.4,
|
||||||
|
cacheRead: 0.06,
|
||||||
|
cacheWrite: 0.375,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"MiniMax-M3": {
|
||||||
|
id: "MiniMax-M3",
|
||||||
|
name: "MiniMax-M3",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "minimax-cn",
|
||||||
|
baseUrl: "https://api.minimaxi.com/anthropic",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 2.4,
|
||||||
|
cacheRead: 0.12,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 512000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { anthropicMessagesApi } from "../api/anthropic-messages.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { MINIMAX_CN_MODELS } from "./minimax-cn.models.ts";
|
||||||
|
|
||||||
|
export function minimaxCnProvider(): Provider<"anthropic-messages"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "minimax-cn",
|
||||||
|
name: "MiniMax CN",
|
||||||
|
baseUrl: "https://api.minimaxi.com/anthropic",
|
||||||
|
auth: { apiKey: envApiKeyAuth("MiniMax CN API key", ["MINIMAX_CN_API_KEY"]) },
|
||||||
|
models: Object.values(MINIMAX_CN_MODELS),
|
||||||
|
api: anthropicMessagesApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const MINIMAX_MODELS = {
|
||||||
|
"MiniMax-M2.7": {
|
||||||
|
id: "MiniMax-M2.7",
|
||||||
|
name: "MiniMax-M2.7",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "minimax",
|
||||||
|
baseUrl: "https://api.minimax.io/anthropic",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0.06,
|
||||||
|
cacheWrite: 0.375,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"MiniMax-M2.7-highspeed": {
|
||||||
|
id: "MiniMax-M2.7-highspeed",
|
||||||
|
name: "MiniMax-M2.7-highspeed",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "minimax",
|
||||||
|
baseUrl: "https://api.minimax.io/anthropic",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 2.4,
|
||||||
|
cacheRead: 0.06,
|
||||||
|
cacheWrite: 0.375,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"MiniMax-M3": {
|
||||||
|
id: "MiniMax-M3",
|
||||||
|
name: "MiniMax-M3",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "minimax",
|
||||||
|
baseUrl: "https://api.minimax.io/anthropic",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 2.4,
|
||||||
|
cacheRead: 0.12,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 512000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { anthropicMessagesApi } from "../api/anthropic-messages.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { MINIMAX_MODELS } from "./minimax.models.ts";
|
||||||
|
|
||||||
|
export function minimaxProvider(): Provider<"anthropic-messages"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "minimax",
|
||||||
|
name: "MiniMax",
|
||||||
|
baseUrl: "https://api.minimax.io/anthropic",
|
||||||
|
auth: { apiKey: envApiKeyAuth("MiniMax API key", ["MINIMAX_API_KEY"]) },
|
||||||
|
models: Object.values(MINIMAX_MODELS),
|
||||||
|
api: anthropicMessagesApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,517 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const MISTRAL_MODELS = {
|
||||||
|
"codestral-latest": {
|
||||||
|
id: "codestral-latest",
|
||||||
|
name: "Codestral (latest)",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 0.9,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"devstral-2512": {
|
||||||
|
id: "devstral-2512",
|
||||||
|
name: "Devstral 2",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"devstral-latest": {
|
||||||
|
id: "devstral-latest",
|
||||||
|
name: "Devstral 2",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"devstral-medium-2507": {
|
||||||
|
id: "devstral-medium-2507",
|
||||||
|
name: "Devstral Medium",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"devstral-medium-latest": {
|
||||||
|
id: "devstral-medium-latest",
|
||||||
|
name: "Devstral 2 (latest)",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"devstral-small-2505": {
|
||||||
|
id: "devstral-small-2505",
|
||||||
|
name: "Devstral Small 2505",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.3,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"devstral-small-2507": {
|
||||||
|
id: "devstral-small-2507",
|
||||||
|
name: "Devstral Small",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.3,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"labs-devstral-small-2512": {
|
||||||
|
id: "labs-devstral-small-2512",
|
||||||
|
name: "Devstral Small 2",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 256000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"magistral-medium-latest": {
|
||||||
|
id: "magistral-medium-latest",
|
||||||
|
name: "Magistral Medium (latest)",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 5,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"magistral-small": {
|
||||||
|
id: "magistral-small",
|
||||||
|
name: "Magistral Small",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 1.5,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"ministral-3b-latest": {
|
||||||
|
id: "ministral-3b-latest",
|
||||||
|
name: "Ministral 3B (latest)",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.04,
|
||||||
|
output: 0.04,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"ministral-8b-latest": {
|
||||||
|
id: "ministral-8b-latest",
|
||||||
|
name: "Ministral 8B (latest)",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.1,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"mistral-large-2411": {
|
||||||
|
id: "mistral-large-2411",
|
||||||
|
name: "Mistral Large 2.1",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 6,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"mistral-large-2512": {
|
||||||
|
id: "mistral-large-2512",
|
||||||
|
name: "Mistral Large 3",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 1.5,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"mistral-large-latest": {
|
||||||
|
id: "mistral-large-latest",
|
||||||
|
name: "Mistral Large (latest)",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 1.5,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"mistral-medium-2505": {
|
||||||
|
id: "mistral-medium-2505",
|
||||||
|
name: "Mistral Medium 3",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"mistral-medium-2508": {
|
||||||
|
id: "mistral-medium-2508",
|
||||||
|
name: "Mistral Medium 3.1",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"mistral-medium-2604": {
|
||||||
|
id: "mistral-medium-2604",
|
||||||
|
name: "Mistral Medium 3.5",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.5,
|
||||||
|
output: 7.5,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"mistral-medium-3.5": {
|
||||||
|
id: "mistral-medium-3.5",
|
||||||
|
name: "Mistral Medium 3.5",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.5,
|
||||||
|
output: 7.5,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"mistral-medium-latest": {
|
||||||
|
id: "mistral-medium-latest",
|
||||||
|
name: "Mistral Medium (latest)",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"mistral-nemo": {
|
||||||
|
id: "mistral-nemo",
|
||||||
|
name: "Mistral Nemo",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.15,
|
||||||
|
output: 0.15,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"mistral-small-2506": {
|
||||||
|
id: "mistral-small-2506",
|
||||||
|
name: "Mistral Small 3.2",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.3,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"mistral-small-2603": {
|
||||||
|
id: "mistral-small-2603",
|
||||||
|
name: "Mistral Small 4",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.15,
|
||||||
|
output: 0.6,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 256000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"mistral-small-latest": {
|
||||||
|
id: "mistral-small-latest",
|
||||||
|
name: "Mistral Small (latest)",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.15,
|
||||||
|
output: 0.6,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 256000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"open-mistral-7b": {
|
||||||
|
id: "open-mistral-7b",
|
||||||
|
name: "Mistral 7B",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 0.25,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 8000,
|
||||||
|
maxTokens: 8000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"open-mistral-nemo": {
|
||||||
|
id: "open-mistral-nemo",
|
||||||
|
name: "Open Mistral Nemo",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.15,
|
||||||
|
output: 0.15,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"open-mixtral-8x22b": {
|
||||||
|
id: "open-mixtral-8x22b",
|
||||||
|
name: "Mixtral 8x22B",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 6,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 64000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"open-mixtral-8x7b": {
|
||||||
|
id: "open-mixtral-8x7b",
|
||||||
|
name: "Mixtral 8x7B",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.7,
|
||||||
|
output: 0.7,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 32000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"pixtral-12b": {
|
||||||
|
id: "pixtral-12b",
|
||||||
|
name: "Pixtral 12B",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.15,
|
||||||
|
output: 0.15,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
"pixtral-large-latest": {
|
||||||
|
id: "pixtral-large-latest",
|
||||||
|
name: "Pixtral Large (latest)",
|
||||||
|
api: "mistral-conversations",
|
||||||
|
provider: "mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 6,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"mistral-conversations">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { mistralConversationsApi } from "../api/mistral-conversations.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { MISTRAL_MODELS } from "./mistral.models.ts";
|
||||||
|
|
||||||
|
export function mistralProvider(): Provider<"mistral-conversations"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "mistral",
|
||||||
|
name: "Mistral",
|
||||||
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Mistral API key", ["MISTRAL_API_KEY"]) },
|
||||||
|
models: Object.values(MISTRAL_MODELS),
|
||||||
|
api: mistralConversationsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const MOONSHOTAI_CN_MODELS = {
|
||||||
|
"kimi-k2-0711-preview": {
|
||||||
|
id: "kimi-k2-0711-preview",
|
||||||
|
name: "Kimi K2 0711",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "moonshotai-cn",
|
||||||
|
baseUrl: "https://api.moonshot.cn/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 2.5,
|
||||||
|
cacheRead: 0.15,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2-0905-preview": {
|
||||||
|
id: "kimi-k2-0905-preview",
|
||||||
|
name: "Kimi K2 0905",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "moonshotai-cn",
|
||||||
|
baseUrl: "https://api.moonshot.cn/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 2.5,
|
||||||
|
cacheRead: 0.15,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2-thinking": {
|
||||||
|
id: "kimi-k2-thinking",
|
||||||
|
name: "Kimi K2 Thinking",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "moonshotai-cn",
|
||||||
|
baseUrl: "https://api.moonshot.cn/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 2.5,
|
||||||
|
cacheRead: 0.15,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2-thinking-turbo": {
|
||||||
|
id: "kimi-k2-thinking-turbo",
|
||||||
|
name: "Kimi K2 Thinking Turbo",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "moonshotai-cn",
|
||||||
|
baseUrl: "https://api.moonshot.cn/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.15,
|
||||||
|
output: 8,
|
||||||
|
cacheRead: 0.15,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2-turbo-preview": {
|
||||||
|
id: "kimi-k2-turbo-preview",
|
||||||
|
name: "Kimi K2 Turbo",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "moonshotai-cn",
|
||||||
|
baseUrl: "https://api.moonshot.cn/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 2.4,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.6,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2.5": {
|
||||||
|
id: "kimi-k2.5",
|
||||||
|
name: "Kimi K2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "moonshotai-cn",
|
||||||
|
baseUrl: "https://api.moonshot.cn/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.1,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2.6": {
|
||||||
|
id: "kimi-k2.6",
|
||||||
|
name: "Kimi K2.6",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "moonshotai-cn",
|
||||||
|
baseUrl: "https://api.moonshot.cn/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.95,
|
||||||
|
output: 4,
|
||||||
|
cacheRead: 0.16,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { MOONSHOTAI_CN_MODELS } from "./moonshotai-cn.models.ts";
|
||||||
|
|
||||||
|
export function moonshotaiCnProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "moonshotai-cn",
|
||||||
|
name: "Moonshot AI CN",
|
||||||
|
baseUrl: "https://api.moonshot.cn/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Moonshot AI API key", ["MOONSHOT_API_KEY"]) },
|
||||||
|
models: Object.values(MOONSHOTAI_CN_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const MOONSHOTAI_MODELS = {
|
||||||
|
"kimi-k2-0711-preview": {
|
||||||
|
id: "kimi-k2-0711-preview",
|
||||||
|
name: "Kimi K2 0711",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "moonshotai",
|
||||||
|
baseUrl: "https://api.moonshot.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 2.5,
|
||||||
|
cacheRead: 0.15,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2-0905-preview": {
|
||||||
|
id: "kimi-k2-0905-preview",
|
||||||
|
name: "Kimi K2 0905",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "moonshotai",
|
||||||
|
baseUrl: "https://api.moonshot.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 2.5,
|
||||||
|
cacheRead: 0.15,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2-thinking": {
|
||||||
|
id: "kimi-k2-thinking",
|
||||||
|
name: "Kimi K2 Thinking",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "moonshotai",
|
||||||
|
baseUrl: "https://api.moonshot.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 2.5,
|
||||||
|
cacheRead: 0.15,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2-thinking-turbo": {
|
||||||
|
id: "kimi-k2-thinking-turbo",
|
||||||
|
name: "Kimi K2 Thinking Turbo",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "moonshotai",
|
||||||
|
baseUrl: "https://api.moonshot.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.15,
|
||||||
|
output: 8,
|
||||||
|
cacheRead: 0.15,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2-turbo-preview": {
|
||||||
|
id: "kimi-k2-turbo-preview",
|
||||||
|
name: "Kimi K2 Turbo",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "moonshotai",
|
||||||
|
baseUrl: "https://api.moonshot.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 2.4,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.6,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2.5": {
|
||||||
|
id: "kimi-k2.5",
|
||||||
|
name: "Kimi K2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "moonshotai",
|
||||||
|
baseUrl: "https://api.moonshot.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.1,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2.6": {
|
||||||
|
id: "kimi-k2.6",
|
||||||
|
name: "Kimi K2.6",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "moonshotai",
|
||||||
|
baseUrl: "https://api.moonshot.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.95,
|
||||||
|
output: 4,
|
||||||
|
cacheRead: 0.16,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { MOONSHOTAI_MODELS } from "./moonshotai.models.ts";
|
||||||
|
|
||||||
|
export function moonshotaiProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "moonshotai",
|
||||||
|
name: "Moonshot AI",
|
||||||
|
baseUrl: "https://api.moonshot.ai/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Moonshot AI API key", ["MOONSHOT_API_KEY"]) },
|
||||||
|
models: Object.values(MOONSHOTAI_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,387 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const NVIDIA_MODELS = {
|
||||||
|
"meta/llama-3.1-70b-instruct": {
|
||||||
|
id: "meta/llama-3.1-70b-instruct",
|
||||||
|
name: "Llama 3.1 70b Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"meta/llama-3.1-8b-instruct": {
|
||||||
|
id: "meta/llama-3.1-8b-instruct",
|
||||||
|
name: "Llama 3.1 8B Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 16000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"meta/llama-3.2-11b-vision-instruct": {
|
||||||
|
id: "meta/llama-3.2-11b-vision-instruct",
|
||||||
|
name: "Llama 3.2 11b Vision Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"meta/llama-3.2-90b-vision-instruct": {
|
||||||
|
id: "meta/llama-3.2-90b-vision-instruct",
|
||||||
|
name: "Llama-3.2-90B-Vision-Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"meta/llama-3.3-70b-instruct": {
|
||||||
|
id: "meta/llama-3.3-70b-instruct",
|
||||||
|
name: "Llama 3.3 70b Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mistralai/mistral-large-3-675b-instruct-2512": {
|
||||||
|
id: "mistralai/mistral-large-3-675b-instruct-2512",
|
||||||
|
name: "Mistral Large 3 675B Instruct 2512",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mistralai/mistral-small-4-119b-2603": {
|
||||||
|
id: "mistralai/mistral-small-4-119b-2603",
|
||||||
|
name: "mistral-small-4-119b-2603",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"moonshotai/kimi-k2.6": {
|
||||||
|
id: "moonshotai/kimi-k2.6",
|
||||||
|
name: "Kimi K2.6",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"nvidia/nemotron-3-nano-30b-a3b": {
|
||||||
|
id: "nvidia/nemotron-3-nano-30b-a3b",
|
||||||
|
name: "nemotron-3-nano-30b-a3b",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning": {
|
||||||
|
id: "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning",
|
||||||
|
name: "Nemotron 3 Nano Omni",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"nvidia/nemotron-3-super-120b-a12b": {
|
||||||
|
id: "nvidia/nemotron-3-super-120b-a12b",
|
||||||
|
name: "Nemotron 3 Super",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.2,
|
||||||
|
output: 0.8,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"nvidia/nemotron-3-ultra-550b-a55b": {
|
||||||
|
id: "nvidia/nemotron-3-ultra-550b-a55b",
|
||||||
|
name: "Nemotron 3 Ultra 550B A55B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 2.5,
|
||||||
|
cacheRead: 0.15,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"nvidia/nvidia-nemotron-nano-9b-v2": {
|
||||||
|
id: "nvidia/nvidia-nemotron-nano-9b-v2",
|
||||||
|
name: "nvidia-nemotron-nano-9b-v2",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"openai/gpt-oss-120b": {
|
||||||
|
id: "openai/gpt-oss-120b",
|
||||||
|
name: "GPT-OSS-120B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"openai/gpt-oss-20b": {
|
||||||
|
id: "openai/gpt-oss-20b",
|
||||||
|
name: "GPT OSS 20B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"qwen/qwen3-coder-480b-a35b-instruct": {
|
||||||
|
id: "qwen/qwen3-coder-480b-a35b-instruct",
|
||||||
|
name: "Qwen3 Coder 480B A35B Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 66536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"qwen/qwen3.5-122b-a10b": {
|
||||||
|
id: "qwen/qwen3.5-122b-a10b",
|
||||||
|
name: "Qwen3.5 122B-A10B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"stepfun-ai/step-3.5-flash": {
|
||||||
|
id: "stepfun-ai/step-3.5-flash",
|
||||||
|
name: "Step 3.5 Flash",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"stepfun-ai/step-3.7-flash": {
|
||||||
|
id: "stepfun-ai/step-3.7-flash",
|
||||||
|
name: "Step 3.7 Flash",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"z-ai/glm-5.1": {
|
||||||
|
id: "z-ai/glm-5.1",
|
||||||
|
name: "GLM-5.1",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "nvidia",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
headers: {"NVCF-POLL-SECONDS":"3600"},
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { NVIDIA_MODELS } from "./nvidia.models.ts";
|
||||||
|
|
||||||
|
export function nvidiaProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "nvidia",
|
||||||
|
name: "NVIDIA",
|
||||||
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("NVIDIA API key", ["NVIDIA_API_KEY"]) },
|
||||||
|
models: Object.values(NVIDIA_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const OPENAI_CODEX_MODELS = {
|
||||||
|
"gpt-5.3-codex-spark": {
|
||||||
|
id: "gpt-5.3-codex-spark",
|
||||||
|
name: "GPT-5.3 Codex Spark",
|
||||||
|
api: "openai-codex-responses",
|
||||||
|
provider: "openai-codex",
|
||||||
|
baseUrl: "https://chatgpt.com/backend-api",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-codex-responses">,
|
||||||
|
"gpt-5.4": {
|
||||||
|
id: "gpt-5.4",
|
||||||
|
name: "GPT-5.4",
|
||||||
|
api: "openai-codex-responses",
|
||||||
|
provider: "openai-codex",
|
||||||
|
baseUrl: "https://chatgpt.com/backend-api",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 272000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-codex-responses">,
|
||||||
|
"gpt-5.4-mini": {
|
||||||
|
id: "gpt-5.4-mini",
|
||||||
|
name: "GPT-5.4 mini",
|
||||||
|
api: "openai-codex-responses",
|
||||||
|
provider: "openai-codex",
|
||||||
|
baseUrl: "https://chatgpt.com/backend-api",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.75,
|
||||||
|
output: 4.5,
|
||||||
|
cacheRead: 0.075,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 272000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-codex-responses">,
|
||||||
|
"gpt-5.5": {
|
||||||
|
id: "gpt-5.5",
|
||||||
|
name: "GPT-5.5",
|
||||||
|
api: "openai-codex-responses",
|
||||||
|
provider: "openai-codex",
|
||||||
|
baseUrl: "https://chatgpt.com/backend-api",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 30,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 272000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-codex-responses">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { openAICodexResponsesApi } from "../api/openai-codex-responses.lazy.ts";
|
||||||
|
import { lazyOAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { loadOpenAICodexOAuth } from "../utils/oauth/load.ts";
|
||||||
|
import { OPENAI_CODEX_MODELS } from "./openai-codex.models.ts";
|
||||||
|
|
||||||
|
export function openaiCodexProvider(): Provider<"openai-codex-responses"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "openai-codex",
|
||||||
|
name: "OpenAI Codex",
|
||||||
|
baseUrl: "https://chatgpt.com/backend-api",
|
||||||
|
auth: {
|
||||||
|
oauth: lazyOAuth({ name: "OpenAI (ChatGPT Plus/Pro)", load: loadOpenAICodexOAuth }),
|
||||||
|
},
|
||||||
|
models: Object.values(OPENAI_CODEX_MODELS),
|
||||||
|
api: openAICodexResponsesApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,745 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const OPENAI_MODELS = {
|
||||||
|
"gpt-4": {
|
||||||
|
id: "gpt-4",
|
||||||
|
name: "GPT-4",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 30,
|
||||||
|
output: 60,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 8192,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-4-turbo": {
|
||||||
|
id: "gpt-4-turbo",
|
||||||
|
name: "GPT-4 Turbo",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 10,
|
||||||
|
output: 30,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-4.1": {
|
||||||
|
id: "gpt-4.1",
|
||||||
|
name: "GPT-4.1",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 8,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1047576,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-4.1-mini": {
|
||||||
|
id: "gpt-4.1-mini",
|
||||||
|
name: "GPT-4.1 mini",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 1.6,
|
||||||
|
cacheRead: 0.1,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1047576,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-4.1-nano": {
|
||||||
|
id: "gpt-4.1-nano",
|
||||||
|
name: "GPT-4.1 nano",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.4,
|
||||||
|
cacheRead: 0.025,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1047576,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-4o": {
|
||||||
|
id: "gpt-4o",
|
||||||
|
name: "GPT-4o",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 1.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-4o-2024-05-13": {
|
||||||
|
id: "gpt-4o-2024-05-13",
|
||||||
|
name: "GPT-4o (2024-05-13)",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-4o-2024-08-06": {
|
||||||
|
id: "gpt-4o-2024-08-06",
|
||||||
|
name: "GPT-4o (2024-08-06)",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 1.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-4o-2024-11-20": {
|
||||||
|
id: "gpt-4o-2024-11-20",
|
||||||
|
name: "GPT-4o (2024-11-20)",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 1.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-4o-mini": {
|
||||||
|
id: "gpt-4o-mini",
|
||||||
|
name: "GPT-4o mini",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.15,
|
||||||
|
output: 0.6,
|
||||||
|
cacheRead: 0.075,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5": {
|
||||||
|
id: "gpt-5",
|
||||||
|
name: "GPT-5",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5-chat-latest": {
|
||||||
|
id: "gpt-5-chat-latest",
|
||||||
|
name: "GPT-5 Chat Latest",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: false,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5-codex": {
|
||||||
|
id: "gpt-5-codex",
|
||||||
|
name: "GPT-5-Codex",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5-mini": {
|
||||||
|
id: "gpt-5-mini",
|
||||||
|
name: "GPT-5 Mini",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.025,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5-nano": {
|
||||||
|
id: "gpt-5-nano",
|
||||||
|
name: "GPT-5 Nano",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.05,
|
||||||
|
output: 0.4,
|
||||||
|
cacheRead: 0.005,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5-pro": {
|
||||||
|
id: "gpt-5-pro",
|
||||||
|
name: "GPT-5 Pro",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 15,
|
||||||
|
output: 120,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.1": {
|
||||||
|
id: "gpt-5.1",
|
||||||
|
name: "GPT-5.1",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":"none"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.1-chat-latest": {
|
||||||
|
id: "gpt-5.1-chat-latest",
|
||||||
|
name: "GPT-5.1 Chat",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.1-codex": {
|
||||||
|
id: "gpt-5.1-codex",
|
||||||
|
name: "GPT-5.1 Codex",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.1-codex-max": {
|
||||||
|
id: "gpt-5.1-codex-max",
|
||||||
|
name: "GPT-5.1 Codex Max",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.1-codex-mini": {
|
||||||
|
id: "gpt-5.1-codex-mini",
|
||||||
|
name: "GPT-5.1 Codex mini",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.025,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.2": {
|
||||||
|
id: "gpt-5.2",
|
||||||
|
name: "GPT-5.2",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":"none","xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.2-chat-latest": {
|
||||||
|
id: "gpt-5.2-chat-latest",
|
||||||
|
name: "GPT-5.2 Chat",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.2-codex": {
|
||||||
|
id: "gpt-5.2-codex",
|
||||||
|
name: "GPT-5.2 Codex",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.2-pro": {
|
||||||
|
id: "gpt-5.2-pro",
|
||||||
|
name: "GPT-5.2 Pro",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 21,
|
||||||
|
output: 168,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.3-chat-latest": {
|
||||||
|
id: "gpt-5.3-chat-latest",
|
||||||
|
name: "GPT-5.3 Chat (latest)",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: false,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 16384,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.3-codex": {
|
||||||
|
id: "gpt-5.3-codex",
|
||||||
|
name: "GPT-5.3 Codex",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":"none","xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.3-codex-spark": {
|
||||||
|
id: "gpt-5.3-codex-spark",
|
||||||
|
name: "GPT-5.3 Codex Spark",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 128000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.4": {
|
||||||
|
id: "gpt-5.4",
|
||||||
|
name: "GPT-5.4",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":"none","xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 272000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.4-mini": {
|
||||||
|
id: "gpt-5.4-mini",
|
||||||
|
name: "GPT-5.4 mini",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":"none","xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.75,
|
||||||
|
output: 4.5,
|
||||||
|
cacheRead: 0.075,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.4-nano": {
|
||||||
|
id: "gpt-5.4-nano",
|
||||||
|
name: "GPT-5.4 nano",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":"none","xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.2,
|
||||||
|
output: 1.25,
|
||||||
|
cacheRead: 0.02,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.4-pro": {
|
||||||
|
id: "gpt-5.4-pro",
|
||||||
|
name: "GPT-5.4 Pro",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 30,
|
||||||
|
output: 180,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1050000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.5": {
|
||||||
|
id: "gpt-5.5",
|
||||||
|
name: "GPT-5.5",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":"none","xhigh":"xhigh","minimal":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 30,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 272000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.5-pro": {
|
||||||
|
id: "gpt-5.5-pro",
|
||||||
|
name: "GPT-5.5 Pro",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh","minimal":null,"low":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 30,
|
||||||
|
output: 180,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1050000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"o1": {
|
||||||
|
id: "o1",
|
||||||
|
name: "o1",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 15,
|
||||||
|
output: 60,
|
||||||
|
cacheRead: 7.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"o1-pro": {
|
||||||
|
id: "o1-pro",
|
||||||
|
name: "o1-pro",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 150,
|
||||||
|
output: 600,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"o3": {
|
||||||
|
id: "o3",
|
||||||
|
name: "o3",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 8,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"o3-deep-research": {
|
||||||
|
id: "o3-deep-research",
|
||||||
|
name: "o3-deep-research",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 10,
|
||||||
|
output: 40,
|
||||||
|
cacheRead: 2.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"o3-mini": {
|
||||||
|
id: "o3-mini",
|
||||||
|
name: "o3-mini",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.1,
|
||||||
|
output: 4.4,
|
||||||
|
cacheRead: 0.55,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"o3-pro": {
|
||||||
|
id: "o3-pro",
|
||||||
|
name: "o3-pro",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 20,
|
||||||
|
output: 80,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"o4-mini": {
|
||||||
|
id: "o4-mini",
|
||||||
|
name: "o4-mini",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.1,
|
||||||
|
output: 4.4,
|
||||||
|
cacheRead: 0.275,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"o4-mini-deep-research": {
|
||||||
|
id: "o4-mini-deep-research",
|
||||||
|
name: "o4-mini-deep-research",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "openai",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 8,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 100000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAIResponsesApi } from "../api/openai-responses.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { OPENAI_MODELS } from "./openai.models.ts";
|
||||||
|
|
||||||
|
export function openaiProvider(): Provider<"openai-responses"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "openai",
|
||||||
|
name: "OpenAI",
|
||||||
|
baseUrl: "https://api.openai.com/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("OpenAI API key", ["OPENAI_API_KEY"]) },
|
||||||
|
models: Object.values(OPENAI_MODELS),
|
||||||
|
api: openAIResponsesApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const OPENCODE_GO_MODELS = {
|
||||||
|
"deepseek-v4-flash": {
|
||||||
|
id: "deepseek-v4-flash",
|
||||||
|
name: "DeepSeek V4 Flash",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode-go",
|
||||||
|
baseUrl: "https://opencode.ai/zen/go/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max"},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.14,
|
||||||
|
output: 0.28,
|
||||||
|
cacheRead: 0.0028,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 384000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"deepseek-v4-pro": {
|
||||||
|
id: "deepseek-v4-pro",
|
||||||
|
name: "DeepSeek V4 Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode-go",
|
||||||
|
baseUrl: "https://opencode.ai/zen/go/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max"},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.74,
|
||||||
|
output: 3.48,
|
||||||
|
cacheRead: 0.0145,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 384000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"glm-5": {
|
||||||
|
id: "glm-5",
|
||||||
|
name: "GLM-5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode-go",
|
||||||
|
baseUrl: "https://opencode.ai/zen/go/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 3.2,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 202752,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"glm-5.1": {
|
||||||
|
id: "glm-5.1",
|
||||||
|
name: "GLM-5.1",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode-go",
|
||||||
|
baseUrl: "https://opencode.ai/zen/go/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.4,
|
||||||
|
output: 4.4,
|
||||||
|
cacheRead: 0.26,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 202752,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2.5": {
|
||||||
|
id: "kimi-k2.5",
|
||||||
|
name: "Kimi K2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode-go",
|
||||||
|
baseUrl: "https://opencode.ai/zen/go/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.1,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2.6": {
|
||||||
|
id: "kimi-k2.6",
|
||||||
|
name: "Kimi K2.6",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode-go",
|
||||||
|
baseUrl: "https://opencode.ai/zen/go/v1",
|
||||||
|
compat: {"thinkingFormat":"deepseek","supportsReasoningEffort":false,"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.95,
|
||||||
|
output: 4,
|
||||||
|
cacheRead: 0.16,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5": {
|
||||||
|
id: "mimo-v2.5",
|
||||||
|
name: "MiMo V2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode-go",
|
||||||
|
baseUrl: "https://opencode.ai/zen/go/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.14,
|
||||||
|
output: 0.28,
|
||||||
|
cacheRead: 0.0028,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5-pro": {
|
||||||
|
id: "mimo-v2.5-pro",
|
||||||
|
name: "MiMo V2.5 Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode-go",
|
||||||
|
baseUrl: "https://opencode.ai/zen/go/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.74,
|
||||||
|
output: 3.48,
|
||||||
|
cacheRead: 0.0145,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"minimax-m2.5": {
|
||||||
|
id: "minimax-m2.5",
|
||||||
|
name: "MiniMax M2.5",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode-go",
|
||||||
|
baseUrl: "https://opencode.ai/zen/go",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0.03,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"minimax-m2.7": {
|
||||||
|
id: "minimax-m2.7",
|
||||||
|
name: "MiniMax M2.7",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode-go",
|
||||||
|
baseUrl: "https://opencode.ai/zen/go/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0.06,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"minimax-m3": {
|
||||||
|
id: "minimax-m3",
|
||||||
|
name: "MiniMax M3",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode-go",
|
||||||
|
baseUrl: "https://opencode.ai/zen/go",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0.06,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 512000,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"qwen3.6-plus": {
|
||||||
|
id: "qwen3.6-plus",
|
||||||
|
name: "Qwen3.6 Plus",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode-go",
|
||||||
|
baseUrl: "https://opencode.ai/zen/go/v1",
|
||||||
|
compat: {"thinkingFormat":"qwen","maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.05,
|
||||||
|
cacheWrite: 0.625,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"qwen3.7-max": {
|
||||||
|
id: "qwen3.7-max",
|
||||||
|
name: "Qwen3.7 Max",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode-go",
|
||||||
|
baseUrl: "https://opencode.ai/zen/go",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 7.5,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 3.125,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"qwen3.7-plus": {
|
||||||
|
id: "qwen3.7-plus",
|
||||||
|
name: "Qwen3.7 Plus",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode-go",
|
||||||
|
baseUrl: "https://opencode.ai/zen/go",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 1.6,
|
||||||
|
cacheRead: 0.04,
|
||||||
|
cacheWrite: 0.5,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { anthropicMessagesApi } from "../api/anthropic-messages.lazy.ts";
|
||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { OPENCODE_GO_MODELS } from "./opencode-go.models.ts";
|
||||||
|
|
||||||
|
export function opencodeGoProvider(): Provider<"anthropic-messages" | "openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "opencode-go",
|
||||||
|
name: "OpenCode Zen Go",
|
||||||
|
auth: { apiKey: envApiKeyAuth("OpenCode API key", ["OPENCODE_API_KEY"]) },
|
||||||
|
models: Object.values(OPENCODE_GO_MODELS),
|
||||||
|
api: {
|
||||||
|
"anthropic-messages": anthropicMessagesApi(),
|
||||||
|
"openai-completions": openAICompletionsApi(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,818 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const OPENCODE_MODELS = {
|
||||||
|
"big-pickle": {
|
||||||
|
id: "big-pickle",
|
||||||
|
name: "Big Pickle",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"claude-fable-5": {
|
||||||
|
id: "claude-fable-5",
|
||||||
|
name: "Claude Fable 5",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen",
|
||||||
|
compat: {"forceAdaptiveThinking":true},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 10,
|
||||||
|
output: 50,
|
||||||
|
cacheRead: 1,
|
||||||
|
cacheWrite: 12.5,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-haiku-4-5": {
|
||||||
|
id: "claude-haiku-4-5",
|
||||||
|
name: "Claude Haiku 4.5",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 5,
|
||||||
|
cacheRead: 0.1,
|
||||||
|
cacheWrite: 1.25,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-1": {
|
||||||
|
id: "claude-opus-4-1",
|
||||||
|
name: "Claude Opus 4.1",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 15,
|
||||||
|
output: 75,
|
||||||
|
cacheRead: 1.5,
|
||||||
|
cacheWrite: 18.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-5": {
|
||||||
|
id: "claude-opus-4-5",
|
||||||
|
name: "Claude Opus 4.5",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-6": {
|
||||||
|
id: "claude-opus-4-6",
|
||||||
|
name: "Claude Opus 4.6",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen",
|
||||||
|
compat: {"forceAdaptiveThinking":true},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"max"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-7": {
|
||||||
|
id: "claude-opus-4-7",
|
||||||
|
name: "Claude Opus 4.7",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen",
|
||||||
|
compat: {"forceAdaptiveThinking":true,"supportsTemperature":false},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-opus-4-8": {
|
||||||
|
id: "claude-opus-4-8",
|
||||||
|
name: "Claude Opus 4.8",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen",
|
||||||
|
compat: {"forceAdaptiveThinking":true,"supportsTemperature":false},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 6.25,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-sonnet-4": {
|
||||||
|
id: "claude-sonnet-4",
|
||||||
|
name: "Claude Sonnet 4",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-sonnet-4-5": {
|
||||||
|
id: "claude-sonnet-4-5",
|
||||||
|
name: "Claude Sonnet 4.5",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"claude-sonnet-4-6": {
|
||||||
|
id: "claude-sonnet-4-6",
|
||||||
|
name: "Claude Sonnet 4.6",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen",
|
||||||
|
compat: {"forceAdaptiveThinking":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.3,
|
||||||
|
cacheWrite: 3.75,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"deepseek-v4-flash": {
|
||||||
|
id: "deepseek-v4-flash",
|
||||||
|
name: "DeepSeek V4 Flash",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max"},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.14,
|
||||||
|
output: 0.28,
|
||||||
|
cacheRead: 0.028,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 384000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"deepseek-v4-flash-free": {
|
||||||
|
id: "deepseek-v4-flash-free",
|
||||||
|
name: "DeepSeek V4 Flash Free",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max"},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"deepseek-v4-pro": {
|
||||||
|
id: "deepseek-v4-pro",
|
||||||
|
name: "DeepSeek V4 Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":"max"},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.74,
|
||||||
|
output: 3.84,
|
||||||
|
cacheRead: 0.145,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 384000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"gemini-3-flash": {
|
||||||
|
id: "gemini-3-flash",
|
||||||
|
name: "Gemini 3 Flash",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.05,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-3.1-pro": {
|
||||||
|
id: "gemini-3.1-pro",
|
||||||
|
name: "Gemini 3.1 Pro Preview",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":null,"low":"LOW","medium":null,"high":"HIGH"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 12,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"gemini-3.5-flash": {
|
||||||
|
id: "gemini-3.5-flash",
|
||||||
|
name: "Gemini 3.5 Flash",
|
||||||
|
api: "google-generative-ai",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.5,
|
||||||
|
output: 9,
|
||||||
|
cacheRead: 0.15,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"google-generative-ai">,
|
||||||
|
"glm-5": {
|
||||||
|
id: "glm-5",
|
||||||
|
name: "GLM-5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 3.2,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"glm-5.1": {
|
||||||
|
id: "glm-5.1",
|
||||||
|
name: "GLM-5.1",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.4,
|
||||||
|
output: 4.4,
|
||||||
|
cacheRead: 0.26,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"gpt-5": {
|
||||||
|
id: "gpt-5",
|
||||||
|
name: "GPT-5",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.07,
|
||||||
|
output: 8.5,
|
||||||
|
cacheRead: 0.107,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5-codex": {
|
||||||
|
id: "gpt-5-codex",
|
||||||
|
name: "GPT-5 Codex",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.07,
|
||||||
|
output: 8.5,
|
||||||
|
cacheRead: 0.107,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5-nano": {
|
||||||
|
id: "gpt-5-nano",
|
||||||
|
name: "GPT-5 Nano",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.05,
|
||||||
|
output: 0.4,
|
||||||
|
cacheRead: 0.005,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.1": {
|
||||||
|
id: "gpt-5.1",
|
||||||
|
name: "GPT-5.1",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.07,
|
||||||
|
output: 8.5,
|
||||||
|
cacheRead: 0.107,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.1-codex": {
|
||||||
|
id: "gpt-5.1-codex",
|
||||||
|
name: "GPT-5.1 Codex",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.07,
|
||||||
|
output: 8.5,
|
||||||
|
cacheRead: 0.107,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.1-codex-max": {
|
||||||
|
id: "gpt-5.1-codex-max",
|
||||||
|
name: "GPT-5.1 Codex Max",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 10,
|
||||||
|
cacheRead: 0.125,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.1-codex-mini": {
|
||||||
|
id: "gpt-5.1-codex-mini",
|
||||||
|
name: "GPT-5.1 Codex Mini",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.025,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.2": {
|
||||||
|
id: "gpt-5.2",
|
||||||
|
name: "GPT-5.2",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.2-codex": {
|
||||||
|
id: "gpt-5.2-codex",
|
||||||
|
name: "GPT-5.2 Codex",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.3-codex": {
|
||||||
|
id: "gpt-5.3-codex",
|
||||||
|
name: "GPT-5.3 Codex",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.75,
|
||||||
|
output: 14,
|
||||||
|
cacheRead: 0.175,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.4": {
|
||||||
|
id: "gpt-5.4",
|
||||||
|
name: "GPT-5.4",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 272000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.4-mini": {
|
||||||
|
id: "gpt-5.4-mini",
|
||||||
|
name: "GPT-5.4 Mini",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.75,
|
||||||
|
output: 4.5,
|
||||||
|
cacheRead: 0.075,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.4-nano": {
|
||||||
|
id: "gpt-5.4-nano",
|
||||||
|
name: "GPT-5.4 Nano",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.2,
|
||||||
|
output: 1.25,
|
||||||
|
cacheRead: 0.02,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 400000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.4-pro": {
|
||||||
|
id: "gpt-5.4-pro",
|
||||||
|
name: "GPT-5.4 Pro",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 30,
|
||||||
|
output: 180,
|
||||||
|
cacheRead: 30,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1050000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.5": {
|
||||||
|
id: "gpt-5.5",
|
||||||
|
name: "GPT-5.5",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh"},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 30,
|
||||||
|
cacheRead: 0.5,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1050000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"gpt-5.5-pro": {
|
||||||
|
id: "gpt-5.5-pro",
|
||||||
|
name: "GPT-5.5 Pro",
|
||||||
|
api: "openai-responses",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"xhigh":"xhigh","minimal":null,"low":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 30,
|
||||||
|
output: 180,
|
||||||
|
cacheRead: 30,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1050000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-responses">,
|
||||||
|
"grok-build-0.1": {
|
||||||
|
id: "grok-build-0.1",
|
||||||
|
name: "Grok Build 0.1",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
compat: {"supportsReasoningEffort":false,"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 256000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2.5": {
|
||||||
|
id: "kimi-k2.5",
|
||||||
|
name: "Kimi K2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.08,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"kimi-k2.6": {
|
||||||
|
id: "kimi-k2.6",
|
||||||
|
name: "Kimi K2.6",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
compat: {"thinkingFormat":"deepseek","supportsReasoningEffort":false,"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.95,
|
||||||
|
output: 4,
|
||||||
|
cacheRead: 0.16,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5-free": {
|
||||||
|
id: "mimo-v2.5-free",
|
||||||
|
name: "MiMo V2.5 Free",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 32000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"minimax-m2.5": {
|
||||||
|
id: "minimax-m2.5",
|
||||||
|
name: "MiniMax M2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0.06,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"minimax-m2.7": {
|
||||||
|
id: "minimax-m2.7",
|
||||||
|
name: "MiniMax M2.7",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0.06,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"nemotron-3-ultra-free": {
|
||||||
|
id: "nemotron-3-ultra-free",
|
||||||
|
name: "Nemotron 3 Ultra Free",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 128000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"north-mini-code-free": {
|
||||||
|
id: "north-mini-code-free",
|
||||||
|
name: "North Mini Code Free",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
compat: {"maxTokensField":"max_tokens"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 64000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"qwen3.5-plus": {
|
||||||
|
id: "qwen3.5-plus",
|
||||||
|
name: "Qwen3.5 Plus",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.2,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0.02,
|
||||||
|
cacheWrite: 0.25,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"qwen3.6-plus": {
|
||||||
|
id: "qwen3.6-plus",
|
||||||
|
name: "Qwen3.6 Plus",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.05,
|
||||||
|
cacheWrite: 0.625,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { anthropicMessagesApi } from "../api/anthropic-messages.lazy.ts";
|
||||||
|
import { googleGenerativeAIApi } from "../api/google-generative-ai.lazy.ts";
|
||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { openAIResponsesApi } from "../api/openai-responses.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { OPENCODE_MODELS } from "./opencode.models.ts";
|
||||||
|
|
||||||
|
export function opencodeProvider(): Provider<
|
||||||
|
"anthropic-messages" | "google-generative-ai" | "openai-completions" | "openai-responses"
|
||||||
|
> {
|
||||||
|
return createProvider({
|
||||||
|
id: "opencode",
|
||||||
|
name: "OpenCode Zen",
|
||||||
|
auth: { apiKey: envApiKeyAuth("OpenCode API key", ["OPENCODE_API_KEY"]) },
|
||||||
|
models: Object.values(OPENCODE_MODELS),
|
||||||
|
api: {
|
||||||
|
"anthropic-messages": anthropicMessagesApi(),
|
||||||
|
"google-generative-ai": googleGenerativeAIApi(),
|
||||||
|
"openai-completions": openAICompletionsApi(),
|
||||||
|
"openai-responses": openAIResponsesApi(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { OPENROUTER_MODELS } from "./openrouter.models.ts";
|
||||||
|
|
||||||
|
export function openrouterProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "openrouter",
|
||||||
|
name: "OpenRouter",
|
||||||
|
baseUrl: "https://openrouter.ai/api/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("OpenRouter API key", ["OPENROUTER_API_KEY"]) },
|
||||||
|
models: Object.values(OPENROUTER_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,365 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const TOGETHER_MODELS = {
|
||||||
|
"MiniMaxAI/MiniMax-M2.5": {
|
||||||
|
id: "MiniMaxAI/MiniMax-M2.5",
|
||||||
|
name: "MiniMax-M2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0.06,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"MiniMaxAI/MiniMax-M2.7": {
|
||||||
|
id: "MiniMaxAI/MiniMax-M2.7",
|
||||||
|
name: "MiniMax-M2.7",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.3,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0.06,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 202752,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"Qwen/Qwen3-235B-A22B-Instruct-2507-tput": {
|
||||||
|
id: "Qwen/Qwen3-235B-A22B-Instruct-2507-tput",
|
||||||
|
name: "Qwen3 235B A22B Instruct 2507 FP8",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.2,
|
||||||
|
output: 0.6,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8": {
|
||||||
|
id: "Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8",
|
||||||
|
name: "Qwen3 Coder 480B A35B Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"Qwen/Qwen3-Coder-Next-FP8": {
|
||||||
|
id: "Qwen/Qwen3-Coder-Next-FP8",
|
||||||
|
name: "Qwen3 Coder Next FP8",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 1.2,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"Qwen/Qwen3.5-397B-A17B": {
|
||||||
|
id: "Qwen/Qwen3.5-397B-A17B",
|
||||||
|
name: "Qwen3.5 397B A17B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 3.6,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 130000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"Qwen/Qwen3.6-Plus": {
|
||||||
|
id: "Qwen/Qwen3.6-Plus",
|
||||||
|
name: "Qwen3.6 Plus",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 500000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"Qwen/Qwen3.7-Max": {
|
||||||
|
id: "Qwen/Qwen3.7-Max",
|
||||||
|
name: "Qwen3.7 Max",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 2.5,
|
||||||
|
output: 7.5,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 500000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"deepseek-ai/DeepSeek-V3": {
|
||||||
|
id: "deepseek-ai/DeepSeek-V3",
|
||||||
|
name: "DeepSeek-V3",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 1.25,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"deepseek-ai/DeepSeek-V3-1": {
|
||||||
|
id: "deepseek-ai/DeepSeek-V3-1",
|
||||||
|
name: "DeepSeek V3.1",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 1.7,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"deepseek-ai/DeepSeek-V4-Pro": {
|
||||||
|
id: "deepseek-ai/DeepSeek-V4-Pro",
|
||||||
|
name: "DeepSeek V4 Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":true,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null,"high":"high","xhigh":null},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 2.1,
|
||||||
|
output: 4.4,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 512000,
|
||||||
|
maxTokens: 384000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"essentialai/Rnj-1-Instruct": {
|
||||||
|
id: "essentialai/Rnj-1-Instruct",
|
||||||
|
name: "Rnj-1 Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.15,
|
||||||
|
output: 0.15,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 32768,
|
||||||
|
maxTokens: 32768,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"google/gemma-4-31B-it": {
|
||||||
|
id: "google/gemma-4-31B-it",
|
||||||
|
name: "Gemma 4 31B Instruct",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.2,
|
||||||
|
output: 0.5,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"meta-llama/Llama-3.3-70B-Instruct-Turbo": {
|
||||||
|
id: "meta-llama/Llama-3.3-70B-Instruct-Turbo",
|
||||||
|
name: "Llama 3.3 70B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false},
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.88,
|
||||||
|
output: 0.88,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"moonshotai/Kimi-K2.5": {
|
||||||
|
id: "moonshotai/Kimi-K2.5",
|
||||||
|
name: "Kimi K2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.5,
|
||||||
|
output: 2.8,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 262144,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"moonshotai/Kimi-K2.6": {
|
||||||
|
id: "moonshotai/Kimi-K2.6",
|
||||||
|
name: "Kimi K2.6",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.2,
|
||||||
|
output: 4.5,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 131000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"nvidia/nemotron-3-ultra-550b-a55b": {
|
||||||
|
id: "nvidia/nemotron-3-ultra-550b-a55b",
|
||||||
|
name: "Nemotron 3 Ultra 550B A55B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.6,
|
||||||
|
output: 3.6,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 512300,
|
||||||
|
maxTokens: 512300,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"openai/gpt-oss-120b": {
|
||||||
|
id: "openai/gpt-oss-120b",
|
||||||
|
name: "GPT OSS 120B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":true,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"openai"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"off":null,"minimal":null},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.15,
|
||||||
|
output: 0.6,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"zai-org/GLM-5.1": {
|
||||||
|
id: "zai-org/GLM-5.1",
|
||||||
|
name: "GLM-5.1",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
compat: {"supportsStore":false,"supportsDeveloperRole":false,"supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsStrictMode":false,"supportsLongCacheRetention":false,"thinkingFormat":"together"},
|
||||||
|
reasoning: true,
|
||||||
|
thinkingLevelMap: {"minimal":null,"low":null,"medium":null},
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.4,
|
||||||
|
output: 4.4,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 202752,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { TOGETHER_MODELS } from "./together.models.ts";
|
||||||
|
|
||||||
|
export function togetherProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "together",
|
||||||
|
name: "Together",
|
||||||
|
baseUrl: "https://api.together.ai/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Together API key", ["TOGETHER_API_KEY"]) },
|
||||||
|
models: Object.values(TOGETHER_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
|||||||
|
import { anthropicMessagesApi } from "../api/anthropic-messages.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { VERCEL_AI_GATEWAY_MODELS } from "./vercel-ai-gateway.models.ts";
|
||||||
|
|
||||||
|
export function vercelAIGatewayProvider(): Provider<"anthropic-messages"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "vercel-ai-gateway",
|
||||||
|
name: "Vercel AI Gateway",
|
||||||
|
baseUrl: "https://ai-gateway.vercel.sh",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Vercel AI Gateway API key", ["AI_GATEWAY_API_KEY"]) },
|
||||||
|
models: Object.values(VERCEL_AI_GATEWAY_MODELS),
|
||||||
|
api: anthropicMessagesApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const XAI_MODELS = {
|
||||||
|
"grok-3": {
|
||||||
|
id: "grok-3",
|
||||||
|
name: "Grok 3",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xai",
|
||||||
|
baseUrl: "https://api.x.ai/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 3,
|
||||||
|
output: 15,
|
||||||
|
cacheRead: 0.75,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"grok-3-fast": {
|
||||||
|
id: "grok-3-fast",
|
||||||
|
name: "Grok 3 Fast",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xai",
|
||||||
|
baseUrl: "https://api.x.ai/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 5,
|
||||||
|
output: 25,
|
||||||
|
cacheRead: 1.25,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"grok-4.20-0309-non-reasoning": {
|
||||||
|
id: "grok-4.20-0309-non-reasoning",
|
||||||
|
name: "Grok 4.20 (Non-Reasoning)",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xai",
|
||||||
|
baseUrl: "https://api.x.ai/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 2.5,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 30000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"grok-4.20-0309-reasoning": {
|
||||||
|
id: "grok-4.20-0309-reasoning",
|
||||||
|
name: "Grok 4.20 (Reasoning)",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xai",
|
||||||
|
baseUrl: "https://api.x.ai/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 2.5,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 30000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"grok-4.3": {
|
||||||
|
id: "grok-4.3",
|
||||||
|
name: "Grok 4.3",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xai",
|
||||||
|
baseUrl: "https://api.x.ai/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1.25,
|
||||||
|
output: 2.5,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1000000,
|
||||||
|
maxTokens: 30000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"grok-build-0.1": {
|
||||||
|
id: "grok-build-0.1",
|
||||||
|
name: "Grok Build 0.1",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xai",
|
||||||
|
baseUrl: "https://api.x.ai/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 256000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"grok-code-fast-1": {
|
||||||
|
id: "grok-code-fast-1",
|
||||||
|
name: "Grok Code Fast 1",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xai",
|
||||||
|
baseUrl: "https://api.x.ai/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.2,
|
||||||
|
output: 1.5,
|
||||||
|
cacheRead: 0.02,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 32768,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { XAI_MODELS } from "./xai.models.ts";
|
||||||
|
|
||||||
|
export function xaiProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "xai",
|
||||||
|
name: "xAI",
|
||||||
|
baseUrl: "https://api.x.ai/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("xAI API key", ["XAI_API_KEY"]) },
|
||||||
|
models: Object.values(XAI_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const XIAOMI_TOKEN_PLAN_AMS_MODELS = {
|
||||||
|
"mimo-v2-omni": {
|
||||||
|
id: "mimo-v2-omni",
|
||||||
|
name: "MiMo-V2-Omni",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-ams",
|
||||||
|
baseUrl: "https://token-plan-ams.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.08,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2-pro": {
|
||||||
|
id: "mimo-v2-pro",
|
||||||
|
name: "MiMo-V2-Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-ams",
|
||||||
|
baseUrl: "https://token-plan-ams.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5": {
|
||||||
|
id: "mimo-v2.5",
|
||||||
|
name: "MiMo-V2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-ams",
|
||||||
|
baseUrl: "https://token-plan-ams.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.08,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5-pro": {
|
||||||
|
id: "mimo-v2.5-pro",
|
||||||
|
name: "MiMo-V2.5-Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-ams",
|
||||||
|
baseUrl: "https://token-plan-ams.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5-pro-ultraspeed": {
|
||||||
|
id: "mimo-v2.5-pro-ultraspeed",
|
||||||
|
name: "MiMo-V2.5-Pro-UltraSpeed",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-ams",
|
||||||
|
baseUrl: "https://token-plan-ams.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.305,
|
||||||
|
output: 2.61,
|
||||||
|
cacheRead: 0.0108,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { XIAOMI_TOKEN_PLAN_AMS_MODELS } from "./xiaomi-token-plan-ams.models.ts";
|
||||||
|
|
||||||
|
export function xiaomiTokenPlanAmsProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "xiaomi-token-plan-ams",
|
||||||
|
name: "Xiaomi Token Plan AMS",
|
||||||
|
baseUrl: "https://token-plan-ams.xiaomimimo.com/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Xiaomi Token Plan AMS API key", ["XIAOMI_TOKEN_PLAN_AMS_API_KEY"]) },
|
||||||
|
models: Object.values(XIAOMI_TOKEN_PLAN_AMS_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const XIAOMI_TOKEN_PLAN_CN_MODELS = {
|
||||||
|
"mimo-v2-omni": {
|
||||||
|
id: "mimo-v2-omni",
|
||||||
|
name: "MiMo-V2-Omni",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-cn",
|
||||||
|
baseUrl: "https://token-plan-cn.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.08,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2-pro": {
|
||||||
|
id: "mimo-v2-pro",
|
||||||
|
name: "MiMo-V2-Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-cn",
|
||||||
|
baseUrl: "https://token-plan-cn.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5": {
|
||||||
|
id: "mimo-v2.5",
|
||||||
|
name: "MiMo-V2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-cn",
|
||||||
|
baseUrl: "https://token-plan-cn.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.08,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5-pro": {
|
||||||
|
id: "mimo-v2.5-pro",
|
||||||
|
name: "MiMo-V2.5-Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-cn",
|
||||||
|
baseUrl: "https://token-plan-cn.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5-pro-ultraspeed": {
|
||||||
|
id: "mimo-v2.5-pro-ultraspeed",
|
||||||
|
name: "MiMo-V2.5-Pro-UltraSpeed",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-cn",
|
||||||
|
baseUrl: "https://token-plan-cn.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.305,
|
||||||
|
output: 2.61,
|
||||||
|
cacheRead: 0.0108,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { XIAOMI_TOKEN_PLAN_CN_MODELS } from "./xiaomi-token-plan-cn.models.ts";
|
||||||
|
|
||||||
|
export function xiaomiTokenPlanCnProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "xiaomi-token-plan-cn",
|
||||||
|
name: "Xiaomi Token Plan CN",
|
||||||
|
baseUrl: "https://token-plan-cn.xiaomimimo.com/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Xiaomi Token Plan CN API key", ["XIAOMI_TOKEN_PLAN_CN_API_KEY"]) },
|
||||||
|
models: Object.values(XIAOMI_TOKEN_PLAN_CN_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const XIAOMI_TOKEN_PLAN_SGP_MODELS = {
|
||||||
|
"mimo-v2-omni": {
|
||||||
|
id: "mimo-v2-omni",
|
||||||
|
name: "MiMo-V2-Omni",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-sgp",
|
||||||
|
baseUrl: "https://token-plan-sgp.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.08,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2-pro": {
|
||||||
|
id: "mimo-v2-pro",
|
||||||
|
name: "MiMo-V2-Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-sgp",
|
||||||
|
baseUrl: "https://token-plan-sgp.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5": {
|
||||||
|
id: "mimo-v2.5",
|
||||||
|
name: "MiMo-V2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-sgp",
|
||||||
|
baseUrl: "https://token-plan-sgp.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.08,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5-pro": {
|
||||||
|
id: "mimo-v2.5-pro",
|
||||||
|
name: "MiMo-V2.5-Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-sgp",
|
||||||
|
baseUrl: "https://token-plan-sgp.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5-pro-ultraspeed": {
|
||||||
|
id: "mimo-v2.5-pro-ultraspeed",
|
||||||
|
name: "MiMo-V2.5-Pro-UltraSpeed",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi-token-plan-sgp",
|
||||||
|
baseUrl: "https://token-plan-sgp.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.305,
|
||||||
|
output: 2.61,
|
||||||
|
cacheRead: 0.0108,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { XIAOMI_TOKEN_PLAN_SGP_MODELS } from "./xiaomi-token-plan-sgp.models.ts";
|
||||||
|
|
||||||
|
export function xiaomiTokenPlanSgpProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "xiaomi-token-plan-sgp",
|
||||||
|
name: "Xiaomi Token Plan SGP",
|
||||||
|
baseUrl: "https://token-plan-sgp.xiaomimimo.com/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Xiaomi Token Plan SGP API key", ["XIAOMI_TOKEN_PLAN_SGP_API_KEY"]) },
|
||||||
|
models: Object.values(XIAOMI_TOKEN_PLAN_SGP_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const XIAOMI_MODELS = {
|
||||||
|
"mimo-v2-flash": {
|
||||||
|
id: "mimo-v2-flash",
|
||||||
|
name: "MiMo-V2-Flash",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi",
|
||||||
|
baseUrl: "https://api.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.1,
|
||||||
|
output: 0.3,
|
||||||
|
cacheRead: 0.01,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2-omni": {
|
||||||
|
id: "mimo-v2-omni",
|
||||||
|
name: "MiMo-V2-Omni",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi",
|
||||||
|
baseUrl: "https://api.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.08,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2-pro": {
|
||||||
|
id: "mimo-v2-pro",
|
||||||
|
name: "MiMo-V2-Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi",
|
||||||
|
baseUrl: "https://api.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5": {
|
||||||
|
id: "mimo-v2.5",
|
||||||
|
name: "MiMo-V2.5",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi",
|
||||||
|
baseUrl: "https://api.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0.08,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5-pro": {
|
||||||
|
id: "mimo-v2.5-pro",
|
||||||
|
name: "MiMo-V2.5-Pro",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi",
|
||||||
|
baseUrl: "https://api.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1,
|
||||||
|
output: 3,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2.5-pro-ultraspeed": {
|
||||||
|
id: "mimo-v2.5-pro-ultraspeed",
|
||||||
|
name: "MiMo-V2.5-Pro-UltraSpeed",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xiaomi",
|
||||||
|
baseUrl: "https://api.xiaomimimo.com/v1",
|
||||||
|
compat: {"requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 1.305,
|
||||||
|
output: 2.61,
|
||||||
|
cacheRead: 0.0108,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 1048576,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { XIAOMI_MODELS } from "./xiaomi.models.ts";
|
||||||
|
|
||||||
|
export function xiaomiProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "xiaomi",
|
||||||
|
name: "Xiaomi",
|
||||||
|
baseUrl: "https://api.xiaomimimo.com/v1",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Xiaomi API key", ["XIAOMI_API_KEY"]) },
|
||||||
|
models: Object.values(XIAOMI_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const ZAI_CODING_CN_MODELS = {
|
||||||
|
"glm-4.5-air": {
|
||||||
|
id: "glm-4.5-air",
|
||||||
|
name: "GLM-4.5-Air",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "zai-coding-cn",
|
||||||
|
baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4",
|
||||||
|
compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 98304,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"glm-4.7": {
|
||||||
|
id: "glm-4.7",
|
||||||
|
name: "GLM-4.7",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "zai-coding-cn",
|
||||||
|
baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4",
|
||||||
|
compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"glm-5-turbo": {
|
||||||
|
id: "glm-5-turbo",
|
||||||
|
name: "GLM-5-Turbo",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "zai-coding-cn",
|
||||||
|
baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4",
|
||||||
|
compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"glm-5.1": {
|
||||||
|
id: "glm-5.1",
|
||||||
|
name: "GLM-5.1",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "zai-coding-cn",
|
||||||
|
baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4",
|
||||||
|
compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"glm-5v-turbo": {
|
||||||
|
id: "glm-5v-turbo",
|
||||||
|
name: "GLM-5V-Turbo",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "zai-coding-cn",
|
||||||
|
baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4",
|
||||||
|
compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { ZAI_CODING_CN_MODELS } from "./zai-coding-cn.models.ts";
|
||||||
|
|
||||||
|
export function zaiCodingCnProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "zai-coding-cn",
|
||||||
|
name: "Z.AI Coding CN",
|
||||||
|
baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Z.AI Coding CN API key", ["ZAI_CODING_CN_API_KEY"]) },
|
||||||
|
models: Object.values(ZAI_CODING_CN_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
// This file is auto-generated by scripts/generate-models.ts
|
||||||
|
// Do not edit manually - run 'npm run generate-models' to update
|
||||||
|
|
||||||
|
import type { Model } from "../types.ts";
|
||||||
|
|
||||||
|
export const ZAI_MODELS = {
|
||||||
|
"glm-4.5-air": {
|
||||||
|
id: "glm-4.5-air",
|
||||||
|
name: "GLM-4.5-Air",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "zai",
|
||||||
|
baseUrl: "https://api.z.ai/api/coding/paas/v4",
|
||||||
|
compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai"},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 98304,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"glm-4.7": {
|
||||||
|
id: "glm-4.7",
|
||||||
|
name: "GLM-4.7",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "zai",
|
||||||
|
baseUrl: "https://api.z.ai/api/coding/paas/v4",
|
||||||
|
compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 204800,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"glm-5-turbo": {
|
||||||
|
id: "glm-5-turbo",
|
||||||
|
name: "GLM-5-Turbo",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "zai",
|
||||||
|
baseUrl: "https://api.z.ai/api/coding/paas/v4",
|
||||||
|
compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"glm-5.1": {
|
||||||
|
id: "glm-5.1",
|
||||||
|
name: "GLM-5.1",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "zai",
|
||||||
|
baseUrl: "https://api.z.ai/api/coding/paas/v4",
|
||||||
|
compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"glm-5v-turbo": {
|
||||||
|
id: "glm-5v-turbo",
|
||||||
|
name: "GLM-5V-Turbo",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "zai",
|
||||||
|
baseUrl: "https://api.z.ai/api/coding/paas/v4",
|
||||||
|
compat: {"supportsDeveloperRole":false,"thinkingFormat":"zai","zaiToolStream":true},
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { openAICompletionsApi } from "../api/openai-completions.lazy.ts";
|
||||||
|
import { envApiKeyAuth } from "../auth/helpers.ts";
|
||||||
|
import { createProvider, type Provider } from "../models.ts";
|
||||||
|
import { ZAI_MODELS } from "./zai.models.ts";
|
||||||
|
|
||||||
|
export function zaiProvider(): Provider<"openai-completions"> {
|
||||||
|
return createProvider({
|
||||||
|
id: "zai",
|
||||||
|
name: "Z.AI",
|
||||||
|
baseUrl: "https://api.z.ai/api/coding/paas/v4",
|
||||||
|
auth: { apiKey: envApiKeyAuth("Z.AI API key", ["ZAI_API_KEY"]) },
|
||||||
|
models: Object.values(ZAI_MODELS),
|
||||||
|
api: openAICompletionsApi(),
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import type { OAuthAuth } from "../../auth/types.ts";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads an OAuth flow module through a variable specifier so bundlers cannot
|
||||||
|
* follow the import into Node-only flow code (`node:http` callback servers,
|
||||||
|
* `node:crypto` PKCE). The `.ts`/`.js` rewrite keeps the trick working from
|
||||||
|
* both source and built output.
|
||||||
|
*/
|
||||||
|
const importOAuthModule = (specifier: string): Promise<unknown> => {
|
||||||
|
const runtimeSpecifier = import.meta.url.endsWith(".js") ? specifier.replace(/\.ts$/, ".js") : specifier;
|
||||||
|
return import(runtimeSpecifier);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const loadAnthropicOAuth = async (): Promise<OAuthAuth> =>
|
||||||
|
((await importOAuthModule("./anthropic.ts")) as { anthropicOAuth: OAuthAuth }).anthropicOAuth;
|
||||||
|
|
||||||
|
export const loadOpenAICodexOAuth = async (): Promise<OAuthAuth> =>
|
||||||
|
((await importOAuthModule("./openai-codex.ts")) as { openaiCodexOAuth: OAuthAuth }).openaiCodexOAuth;
|
||||||
|
|
||||||
|
export const loadGitHubCopilotOAuth = async (): Promise<OAuthAuth> =>
|
||||||
|
((await importOAuthModule("./github-copilot.ts")) as { githubCopilotOAuth: OAuthAuth }).githubCopilotOAuth;
|
||||||
@@ -5,6 +5,7 @@ import { describe, expect, it } from "vitest";
|
|||||||
|
|
||||||
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
const aiEntryUrl = new URL("../src/index.ts", import.meta.url).href;
|
const aiEntryUrl = new URL("../src/index.ts", import.meta.url).href;
|
||||||
|
const providersAllUrl = new URL("../src/providers/all.ts", import.meta.url).href;
|
||||||
|
|
||||||
const SDK_SPECIFIERS = [
|
const SDK_SPECIFIERS = [
|
||||||
"@anthropic-ai/sdk",
|
"@anthropic-ai/sdk",
|
||||||
@@ -66,6 +67,15 @@ describe("lazy provider module loading", () => {
|
|||||||
expect(result.loadedSpecifiers).toEqual([]);
|
expect(result.loadedSpecifiers).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not load provider SDKs when building all builtin providers", () => {
|
||||||
|
const result = runProbe(`
|
||||||
|
const all = await import(${JSON.stringify(providersAllUrl)});
|
||||||
|
const models = all.builtinModels();
|
||||||
|
await models.getModels();
|
||||||
|
`);
|
||||||
|
expect(result.loadedSpecifiers).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
it("loads only the Anthropic SDK when streaming through the lazy API wrapper", () => {
|
it("loads only the Anthropic SDK when streaming through the lazy API wrapper", () => {
|
||||||
const result = runProbe(`
|
const result = runProbe(`
|
||||||
const model = {
|
const model = {
|
||||||
|
|||||||
@@ -0,0 +1,208 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { envApiKeyAuth } from "../src/auth/helpers.ts";
|
||||||
|
import type { AuthContext } from "../src/auth/types.ts";
|
||||||
|
import { createModels, createProvider } from "../src/models.ts";
|
||||||
|
import { builtinModels, builtinProviders } from "../src/providers/all.ts";
|
||||||
|
import { amazonBedrockProvider } from "../src/providers/amazon-bedrock.ts";
|
||||||
|
import { anthropicProvider } from "../src/providers/anthropic.ts";
|
||||||
|
import { fauxAssistantMessage, fauxProvider } from "../src/providers/faux.ts";
|
||||||
|
import { googleVertexProvider } from "../src/providers/google-vertex.ts";
|
||||||
|
import type { Api, Context, Model, ProviderStreams } from "../src/types.ts";
|
||||||
|
import { AssistantMessageEventStream } from "../src/utils/event-stream.ts";
|
||||||
|
|
||||||
|
function fakeAuthContext(env: Record<string, string>, files: string[] = []): AuthContext {
|
||||||
|
return {
|
||||||
|
env: async (name) => env[name],
|
||||||
|
fileExists: async (path) => files.includes(path),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const context: Context = { messages: [{ role: "user", content: "hi", timestamp: Date.now() }] };
|
||||||
|
|
||||||
|
describe("builtin providers", () => {
|
||||||
|
it("builtinModels registers every builtin provider with models", async () => {
|
||||||
|
const models = builtinModels();
|
||||||
|
const providers = models.getProviders();
|
||||||
|
expect(providers.length).toBe(builtinProviders().length);
|
||||||
|
expect(providers.map((p) => p.id)).toContain("anthropic");
|
||||||
|
|
||||||
|
const anthropic = await models.getModel("anthropic", "claude-haiku-4-5");
|
||||||
|
expect(anthropic?.api).toBe("anthropic-messages");
|
||||||
|
|
||||||
|
const all = await models.getModels();
|
||||||
|
expect(all.length).toBeGreaterThan(500);
|
||||||
|
|
||||||
|
// every provider lists at least one model and owns its models
|
||||||
|
for (const provider of providers) {
|
||||||
|
const list = await models.getModels(provider.id);
|
||||||
|
expect(list.length).toBeGreaterThan(0);
|
||||||
|
expect(list.every((m) => m.provider === provider.id)).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("resolves anthropic auth from env with OAuth token precedence", async () => {
|
||||||
|
const models = createModels({
|
||||||
|
authContext: fakeAuthContext({ ANTHROPIC_API_KEY: "key", ANTHROPIC_OAUTH_TOKEN: "oauth-token" }),
|
||||||
|
});
|
||||||
|
models.setProvider(anthropicProvider());
|
||||||
|
const model = (await models.getModel("anthropic", "claude-haiku-4-5"))!;
|
||||||
|
|
||||||
|
const result = await models.getAuth(model);
|
||||||
|
expect(result?.auth.apiKey).toBe("oauth-token");
|
||||||
|
expect(result?.source).toBe("ANTHROPIC_OAUTH_TOKEN");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reports bedrock as configured from ambient AWS credentials without an api key", async () => {
|
||||||
|
const models = createModels({ authContext: fakeAuthContext({ AWS_PROFILE: "dev" }) });
|
||||||
|
models.setProvider(amazonBedrockProvider());
|
||||||
|
const model = (await models.getModels("amazon-bedrock"))[0];
|
||||||
|
|
||||||
|
const result = await models.getAuth(model);
|
||||||
|
expect(result?.auth).toEqual({});
|
||||||
|
expect(result?.source).toBe("AWS_PROFILE");
|
||||||
|
|
||||||
|
const unconfigured = createModels({ authContext: fakeAuthContext({}) });
|
||||||
|
unconfigured.setProvider(amazonBedrockProvider());
|
||||||
|
expect(await unconfigured.getAuth(model)).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("resolves vertex via ADC file plus project and location", async () => {
|
||||||
|
const adc = "~/.config/gcloud/application_default_credentials.json";
|
||||||
|
const configured = createModels({
|
||||||
|
authContext: fakeAuthContext({ GOOGLE_CLOUD_PROJECT: "proj", GOOGLE_CLOUD_LOCATION: "us-central1" }, [adc]),
|
||||||
|
});
|
||||||
|
configured.setProvider(googleVertexProvider());
|
||||||
|
const model = (await configured.getModels("google-vertex"))[0];
|
||||||
|
|
||||||
|
const result = await configured.getAuth(model);
|
||||||
|
expect(result?.auth).toEqual({});
|
||||||
|
expect(result?.source).toContain("application default");
|
||||||
|
|
||||||
|
// ADC without project/location is not configured
|
||||||
|
const partial = createModels({ authContext: fakeAuthContext({ GOOGLE_CLOUD_PROJECT: "proj" }, [adc]) });
|
||||||
|
partial.setProvider(googleVertexProvider());
|
||||||
|
expect(await partial.getAuth(model)).toBeUndefined();
|
||||||
|
|
||||||
|
// explicit key wins over ADC
|
||||||
|
const keyed = createModels({ authContext: fakeAuthContext({ GOOGLE_CLOUD_API_KEY: "vertex-key" }) });
|
||||||
|
keyed.setProvider(googleVertexProvider());
|
||||||
|
expect((await keyed.getAuth(model))?.auth.apiKey).toBe("vertex-key");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("envApiKeyAuth", () => {
|
||||||
|
it("prefers the stored credential key and falls back through env vars in order", async () => {
|
||||||
|
const auth = envApiKeyAuth("Test key", ["FIRST_KEY", "SECOND_KEY"]);
|
||||||
|
const model = { provider: "p1" } as Model<Api>;
|
||||||
|
|
||||||
|
const stored = await auth.resolve({
|
||||||
|
model,
|
||||||
|
ctx: fakeAuthContext({ FIRST_KEY: "env" }),
|
||||||
|
credential: { type: "api-key", key: "stored" },
|
||||||
|
});
|
||||||
|
expect(stored?.auth.apiKey).toBe("stored");
|
||||||
|
expect(stored?.source).toBe("stored credential");
|
||||||
|
|
||||||
|
const second = await auth.resolve({ model, ctx: fakeAuthContext({ SECOND_KEY: "second" }) });
|
||||||
|
expect(second?.auth.apiKey).toBe("second");
|
||||||
|
expect(second?.source).toBe("SECOND_KEY");
|
||||||
|
|
||||||
|
expect(await auth.resolve({ model, ctx: fakeAuthContext({}) })).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("login prompts for a secret and returns an api-key credential", async () => {
|
||||||
|
const auth = envApiKeyAuth("Test key", ["TEST_KEY"]);
|
||||||
|
const credential = await auth.login?.({
|
||||||
|
prompt: async (prompt) => {
|
||||||
|
expect(prompt.type).toBe("secret");
|
||||||
|
return "entered-key";
|
||||||
|
},
|
||||||
|
notify: () => {},
|
||||||
|
});
|
||||||
|
expect(credential).toEqual({ type: "api-key", key: "entered-key" });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("createProvider", () => {
|
||||||
|
function recordingStreams(label: string, calls: string[]): ProviderStreams {
|
||||||
|
const respond = (model: Model<Api>) => {
|
||||||
|
calls.push(`${label}:${model.id}`);
|
||||||
|
const stream = new AssistantMessageEventStream();
|
||||||
|
const message = fauxAssistantMessage("ok");
|
||||||
|
stream.push({ type: "start", partial: message });
|
||||||
|
stream.push({ type: "done", reason: "stop", message });
|
||||||
|
stream.end(message);
|
||||||
|
return stream;
|
||||||
|
};
|
||||||
|
return { stream: respond, streamSimple: respond };
|
||||||
|
}
|
||||||
|
|
||||||
|
function testModel(api: string, id: string): Model<Api> {
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
name: id,
|
||||||
|
api,
|
||||||
|
provider: "mixed",
|
||||||
|
baseUrl: "https://example.test/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||||
|
contextWindow: 10000,
|
||||||
|
maxTokens: 1000,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
it("dispatches on model.api for mixed-API providers", async () => {
|
||||||
|
const calls: string[] = [];
|
||||||
|
const provider = createProvider({
|
||||||
|
id: "mixed",
|
||||||
|
auth: { apiKey: { name: "Test", resolve: async () => ({ auth: {} }) } },
|
||||||
|
models: [testModel("api-a", "model-a"), testModel("api-b", "model-b")],
|
||||||
|
api: { "api-a": recordingStreams("a", calls), "api-b": recordingStreams("b", calls) },
|
||||||
|
});
|
||||||
|
const models = createModels();
|
||||||
|
models.setProvider(provider);
|
||||||
|
|
||||||
|
await models.completeSimple(testModel("api-a", "model-a"), context);
|
||||||
|
await models.completeSimple(testModel("api-b", "model-b"), context);
|
||||||
|
expect(calls).toEqual(["a:model-a", "b:model-b"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("produces a stream error for a model whose api has no implementation", async () => {
|
||||||
|
const provider = createProvider({
|
||||||
|
id: "mixed",
|
||||||
|
auth: { apiKey: { name: "Test", resolve: async () => ({ auth: {} }) } },
|
||||||
|
models: [testModel("api-a", "model-a")],
|
||||||
|
api: { "api-a": recordingStreams("a", []) },
|
||||||
|
});
|
||||||
|
const result = await provider.streamSimple(testModel("api-ghost", "model-x"), context).result();
|
||||||
|
expect(result.stopReason).toBe("error");
|
||||||
|
expect(result.errorMessage).toContain("no API implementation");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("supports async model listers", async () => {
|
||||||
|
const provider = createProvider({
|
||||||
|
id: "dynamic",
|
||||||
|
auth: { apiKey: { name: "Test", resolve: async () => ({ auth: {} }) } },
|
||||||
|
models: async () => [testModel("api-a", "listed")],
|
||||||
|
api: recordingStreams("a", []),
|
||||||
|
});
|
||||||
|
const models = await provider.getModels();
|
||||||
|
expect(models.map((m) => m.id)).toEqual(["listed"]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("fauxProvider", () => {
|
||||||
|
it("streams queued responses through a Models collection", async () => {
|
||||||
|
const faux = fauxProvider();
|
||||||
|
const models = createModels();
|
||||||
|
models.setProvider(faux.provider);
|
||||||
|
faux.setResponses([fauxAssistantMessage("hello from faux")]);
|
||||||
|
|
||||||
|
const model = (await models.getModels(faux.provider.id))[0];
|
||||||
|
const result = await models.completeSimple(model, context);
|
||||||
|
expect(result.stopReason).toBe("stop");
|
||||||
|
expect(result.content).toEqual([{ type: "text", text: "hello from faux" }]);
|
||||||
|
expect(faux.state.callCount).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -2,52 +2,20 @@
|
|||||||
// Run from packages/ai: node test/scratch.ts
|
// Run from packages/ai: node test/scratch.ts
|
||||||
// Requires ANTHROPIC_API_KEY.
|
// Requires ANTHROPIC_API_KEY.
|
||||||
|
|
||||||
import { anthropicMessagesApi } from "../src/api/anthropic-messages.lazy.ts";
|
import { createModels } from "../src/models.ts";
|
||||||
import { createModels, getModels, type Provider } from "../src/models.ts";
|
import { anthropicProvider } from "../src/providers/anthropic.ts";
|
||||||
import type { Context } from "../src/types.ts";
|
import type { Context } from "../src/types.ts";
|
||||||
|
|
||||||
const anthropicApi = anthropicMessagesApi();
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// 1. Define a provider. In the final design this comes from
|
// 1. Build a Models runtime and register a built-in provider factory.
|
||||||
// `@earendil-works/pi-ai/providers/anthropic` as `anthropicProvider()`;
|
// (Apps wanting everything use `builtinModels()` from providers/all.)
|
||||||
// until Phase 3 lands we wire it by hand from existing parts.
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const anthropic: Provider<"anthropic-messages"> = {
|
|
||||||
id: "anthropic",
|
|
||||||
name: "Anthropic",
|
|
||||||
baseUrl: "https://api.anthropic.com/v1",
|
|
||||||
|
|
||||||
auth: {
|
|
||||||
apiKey: {
|
|
||||||
name: "Anthropic API key",
|
|
||||||
resolve: async ({ ctx, credential }) => {
|
|
||||||
// stored credential (from a /login flow) wins, env is the ambient fallback
|
|
||||||
const key = credential?.key ?? (await ctx.env("ANTHROPIC_API_KEY"));
|
|
||||||
if (!key) return undefined;
|
|
||||||
return { auth: { apiKey: key }, source: credential ? "stored credential" : "ANTHROPIC_API_KEY" };
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// static catalog source; a dynamic provider would fetch here
|
|
||||||
getModels: async () => getModels("anthropic"),
|
|
||||||
|
|
||||||
// shared lazy API implementation (loads the SDK on first request)
|
|
||||||
stream: anthropicApi.stream,
|
|
||||||
streamSimple: anthropicApi.streamSimple,
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// 2. Build a Models runtime and register the provider.
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
const models = createModels();
|
const models = createModels();
|
||||||
models.setProvider(anthropic);
|
models.setProvider(anthropicProvider());
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// 3. Look up a model and check auth.
|
// 2. Look up a model and check auth.
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
const model = await models.getModel("anthropic", "claude-haiku-4-5");
|
const model = await models.getModel("anthropic", "claude-haiku-4-5");
|
||||||
@@ -64,14 +32,14 @@ const context: Context = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// 4. Simple completion (request-level auth resolution happens inside).
|
// 3. Simple completion (request-level auth resolution happens inside).
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
const message = await models.completeSimple(model, context);
|
const message = await models.completeSimple(model, context);
|
||||||
console.log(`completeSimple -> [${message.stopReason}]`, message.content);
|
console.log(`completeSimple -> [${message.stopReason}]`, message.content);
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// 5. Streaming with deltas.
|
// 4. Streaming with deltas.
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
context.messages.push(message, {
|
context.messages.push(message, {
|
||||||
|
|||||||
Reference in New Issue
Block a user