mirror of
https://github.com/HeyPuter/puter.git
synced 2026-10-16 16:49:38 +00:00
feat(ai-chat): overhaul provider model catalogs to match current APIs (#3586)
This commit is contained in:
1 parent
2c852bf6b3
commit
9604cc3f23
16 files changed
+568
-1071
No files matched your search
@@ -157,6 +157,91 @@ export const ALIBABA_MODELS: IChatModel[] = [
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
puterId: 'alibaba:qwen/qwen3.6-flash',
|
||||
id: 'qwen3.6-flash',
|
||||
modalities: { input: ['text', 'image', 'video'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
release_date: '2026-04-27',
|
||||
name: 'Qwen3.6 Flash',
|
||||
aliases: ['qwen/qwen3.6-flash'],
|
||||
context: 1_000_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 19,
|
||||
completion_tokens: 113,
|
||||
},
|
||||
max_tokens: 65_536,
|
||||
},
|
||||
{
|
||||
puterId: 'alibaba:qwen/qwen3.7-plus',
|
||||
id: 'qwen3.7-plus',
|
||||
modalities: { input: ['text', 'image', 'video'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
release_date: '2026-06-02',
|
||||
name: 'Qwen3.7 Plus',
|
||||
aliases: ['qwen/qwen3.7-plus'],
|
||||
context: 1_000_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 50,
|
||||
completion_tokens: 300,
|
||||
cached_tokens: 5,
|
||||
},
|
||||
max_tokens: 65_536,
|
||||
},
|
||||
{
|
||||
puterId: 'alibaba:qwen/qwen3.7-max',
|
||||
id: 'qwen3.7-max',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
release_date: '2026-05-21',
|
||||
name: 'Qwen3.7 Max',
|
||||
aliases: ['qwen/qwen3.7-max'],
|
||||
context: 1_000_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 250,
|
||||
completion_tokens: 750,
|
||||
cached_tokens: 50,
|
||||
},
|
||||
max_tokens: 65_536,
|
||||
},
|
||||
{
|
||||
puterId: 'alibaba:qwen/qwen3.8-max',
|
||||
id: 'qwen3.8-max',
|
||||
modalities: { input: ['text', 'image', 'video', 'pdf'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
release_date: '2026-08-03',
|
||||
name: 'Qwen3.8 Max',
|
||||
aliases: ['qwen/qwen3.8-max'],
|
||||
context: 1_000_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 200,
|
||||
completion_tokens: 600,
|
||||
cached_tokens: 25,
|
||||
},
|
||||
max_tokens: 131_072,
|
||||
},
|
||||
|
||||
|
||||
// -- Turbo / Flash tier -----------------------------------------
|
||||
{
|
||||
puterId: 'alibaba:qwen/qwen-turbo',
|
||||
@@ -270,29 +355,6 @@ export const ALIBABA_MODELS: IChatModel[] = [
|
||||
cached_tokens: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
puterId: 'alibaba:qwen/qwen3-coder-30b-a3b-instruct',
|
||||
id: 'qwen3-coder-30b-a3b-instruct',
|
||||
name: 'Qwen3-Coder 30B-A3B Instruct',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: true,
|
||||
knowledge: '2025-04',
|
||||
release_date: '2025-04',
|
||||
aliases: ['qwen/qwen3-coder-30b-a3b-instruct'],
|
||||
context: 262_144,
|
||||
max_tokens: 65_536,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 45,
|
||||
completion_tokens: 225,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
},
|
||||
|
||||
// -- Reasoning models -------------------------------------------
|
||||
{
|
||||
puterId: 'alibaba:qwen/qwq-plus',
|
||||
@@ -666,28 +728,6 @@ export const ALIBABA_MODELS: IChatModel[] = [
|
||||
cached_tokens: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
puterId: 'alibaba:qwen/qwen3-vl-30b-a3b',
|
||||
id: 'qwen3-vl-30b-a3b',
|
||||
name: 'Qwen3-VL 30B-A3B',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: true,
|
||||
knowledge: '2025-04',
|
||||
release_date: '2025-04',
|
||||
aliases: ['qwen/qwen3-vl-30b-a3b'],
|
||||
context: 131_072,
|
||||
max_tokens: 32_768,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 20,
|
||||
completion_tokens: 80,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
puterId: 'alibaba:qwen/qvq-max',
|
||||
id: 'qvq-max',
|
||||
|
||||
@@ -186,7 +186,7 @@ describe('AzureChatProvider model catalog', () => {
|
||||
expect(ids).toContain('openai/gpt-4o');
|
||||
expect(ids).toContain('x-ai/grok-4-20-non-reasoning');
|
||||
// Codex is Responses-only and must not be advertised here.
|
||||
expect(ids).not.toContain('gpt-5-codex');
|
||||
expect(ids).not.toContain('gpt-5.3-codex');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+3
-3
@@ -20,7 +20,7 @@
|
||||
/**
|
||||
* Integration test for the Azure AI Foundry Responses provider.
|
||||
*
|
||||
* Hits the real Azure endpoint with `gpt-5-codex` — a Responses-API-only
|
||||
* Hits the real Azure endpoint with `gpt-5.3-codex` — a Responses-API-only
|
||||
* (Codex) model that the Chat Completions endpoint rejects. This verifies
|
||||
* the completions/responses split actually routes Codex correctly. Codex is
|
||||
* a reasoning model, so we give it a generous `max_tokens` and low reasoning
|
||||
@@ -47,7 +47,7 @@ describe.skipIf(skipUnlessEnv(KEY_ENV) || skipUnlessEnv(URL_ENV))(
|
||||
'AzureResponsesProvider (integration)',
|
||||
() => {
|
||||
it(
|
||||
'returns a non-empty completion from gpt-5-codex',
|
||||
'returns a non-empty completion from gpt-5.3-codex',
|
||||
{ timeout: INTEGRATION_TEST_TIMEOUT_MS },
|
||||
async () => {
|
||||
const provider = new AzureResponsesProvider(
|
||||
@@ -65,7 +65,7 @@ describe.skipIf(skipUnlessEnv(KEY_ENV) || skipUnlessEnv(URL_ENV))(
|
||||
|
||||
const result = await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'gpt-5-codex',
|
||||
model: 'gpt-5.3-codex',
|
||||
messages: [
|
||||
{ role: 'user', content: 'Say hi in one word.' },
|
||||
],
|
||||
|
||||
@@ -156,15 +156,15 @@ describe('AzureResponsesProvider construction', () => {
|
||||
// -- Model catalog ---------------------------------------------------
|
||||
|
||||
describe('AzureResponsesProvider model catalog', () => {
|
||||
it('returns gpt-5-codex as the default model', () => {
|
||||
expect(makeProvider().getDefaultModel()).toBe('gpt-5-codex');
|
||||
it('returns gpt-5.3-codex as the default model', () => {
|
||||
expect(makeProvider().getDefaultModel()).toBe('gpt-5.3-codex');
|
||||
});
|
||||
|
||||
it('models() exposes only the responses_api_only slice of the Azure catalog', () => {
|
||||
const ids = makeProvider()
|
||||
.models()
|
||||
.map((m) => m.id);
|
||||
expect(ids).toContain('gpt-5-codex');
|
||||
expect(ids).toContain('gpt-5.3-codex');
|
||||
// Chat-Completions models belong to the sibling provider.
|
||||
expect(ids).not.toContain('gpt-4o');
|
||||
});
|
||||
@@ -173,15 +173,15 @@ describe('AzureResponsesProvider model catalog', () => {
|
||||
const ids = makeProvider()
|
||||
.models({ no_restrictions: true })
|
||||
.map((m) => m.id);
|
||||
expect(ids).toContain('gpt-5-codex');
|
||||
expect(ids).toContain('gpt-5.3-codex');
|
||||
expect(ids).toContain('gpt-4o');
|
||||
expect(ids).toHaveLength(AZURE_MODELS.length);
|
||||
});
|
||||
|
||||
it('list() flattens responses-only ids and their aliases', () => {
|
||||
const ids = makeProvider().list();
|
||||
expect(ids).toContain('gpt-5-codex');
|
||||
expect(ids).toContain('openai/gpt-5-codex');
|
||||
expect(ids).toContain('gpt-5.3-codex');
|
||||
expect(ids).toContain('openai/gpt-5.3-codex');
|
||||
expect(ids).not.toContain('gpt-4o');
|
||||
});
|
||||
});
|
||||
@@ -194,7 +194,7 @@ describe('AzureResponsesProvider.complete argument validation', () => {
|
||||
await expect(
|
||||
withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'gpt-5-codex',
|
||||
model: 'gpt-5.3-codex',
|
||||
messages: 'hello' as unknown as never,
|
||||
}),
|
||||
),
|
||||
@@ -212,7 +212,7 @@ describe('AzureResponsesProvider.complete request shape', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'gpt-5-codex',
|
||||
model: 'gpt-5.3-codex',
|
||||
messages: [{ role: 'user', content: 'hello' }],
|
||||
max_tokens: 256,
|
||||
temperature: 0.3,
|
||||
@@ -220,7 +220,7 @@ describe('AzureResponsesProvider.complete request shape', () => {
|
||||
);
|
||||
|
||||
const [args] = responsesCreateMock.mock.calls[0]!;
|
||||
expect(args.model).toBe('gpt-5-codex');
|
||||
expect(args.model).toBe('gpt-5.3-codex');
|
||||
expect(args.input).toEqual([{ role: 'user', content: 'hello' }]);
|
||||
expect(args.max_output_tokens).toBe(256);
|
||||
expect(args.temperature).toBe(0.3);
|
||||
@@ -233,12 +233,12 @@ describe('AzureResponsesProvider.complete request shape', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'openai/gpt-5-codex',
|
||||
model: 'openai/gpt-5.3-codex',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
}),
|
||||
);
|
||||
|
||||
expect(responsesCreateMock.mock.calls[0]![0].model).toBe('gpt-5-codex');
|
||||
expect(responsesCreateMock.mock.calls[0]![0].model).toBe('gpt-5.3-codex');
|
||||
});
|
||||
|
||||
it('falls back to the default model for an unknown id', async () => {
|
||||
@@ -252,7 +252,7 @@ describe('AzureResponsesProvider.complete request shape', () => {
|
||||
}),
|
||||
);
|
||||
|
||||
expect(responsesCreateMock.mock.calls[0]![0].model).toBe('gpt-5-codex');
|
||||
expect(responsesCreateMock.mock.calls[0]![0].model).toBe('gpt-5.3-codex');
|
||||
});
|
||||
|
||||
it('flattens chat-style function tools into the Responses shape', async () => {
|
||||
@@ -261,7 +261,7 @@ describe('AzureResponsesProvider.complete request shape', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'gpt-5-codex',
|
||||
model: 'gpt-5.3-codex',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
tools: [
|
||||
{
|
||||
@@ -299,7 +299,7 @@ describe('AzureResponsesProvider.complete request shape', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'gpt-5-codex',
|
||||
model: 'gpt-5.3-codex',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
}),
|
||||
);
|
||||
@@ -338,7 +338,7 @@ describe('AzureResponsesProvider.complete request shape', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'gpt-5-codex',
|
||||
model: 'gpt-5.3-codex',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
tool_choice: 'auto',
|
||||
parallel_tool_calls: false,
|
||||
@@ -380,7 +380,7 @@ describe('AzureResponsesProvider.complete request shape', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'gpt-5-codex',
|
||||
model: 'gpt-5.3-codex',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
compaction: { trigger_tokens: 120_000 },
|
||||
} as never),
|
||||
@@ -398,7 +398,7 @@ describe('AzureResponsesProvider.complete request shape', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'gpt-5-codex',
|
||||
model: 'gpt-5.3-codex',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
compaction: true,
|
||||
context_management: raw,
|
||||
@@ -416,7 +416,7 @@ describe('AzureResponsesProvider.complete request shape', () => {
|
||||
responsesCreateMock.mockResolvedValueOnce(okResponse);
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'gpt-5-codex',
|
||||
model: 'gpt-5.3-codex',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
reasoning: { effort: 'high' },
|
||||
verbosity: 'high',
|
||||
@@ -460,7 +460,7 @@ describe('AzureResponsesProvider usage accounting', () => {
|
||||
|
||||
const result = await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'gpt-5-codex',
|
||||
model: 'gpt-5.3-codex',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
}),
|
||||
);
|
||||
@@ -475,11 +475,11 @@ describe('AzureResponsesProvider usage accounting', () => {
|
||||
cached_tokens: 10,
|
||||
});
|
||||
|
||||
const codex = AZURE_MODELS.find((m) => m.id === 'gpt-5-codex')!;
|
||||
const codex = AZURE_MODELS.find((m) => m.id === 'gpt-5.3-codex')!;
|
||||
expect(recordSpy).toHaveBeenCalledTimes(1);
|
||||
const [usage, actor, prefix, overrides] = recordSpy.mock.calls[0]!;
|
||||
expect(actor).toBe(SYSTEM_ACTOR);
|
||||
expect(prefix).toBe('azure-openai:gpt-5-codex');
|
||||
expect(prefix).toBe('azure-openai:gpt-5.3-codex');
|
||||
expect(usage).toEqual({
|
||||
prompt_tokens: 90,
|
||||
completion_tokens: 50,
|
||||
@@ -502,7 +502,7 @@ describe('AzureResponsesProvider usage accounting', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'gpt-5-codex',
|
||||
model: 'gpt-5.3-codex',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
}),
|
||||
);
|
||||
@@ -539,7 +539,7 @@ describe('AzureResponsesProvider.complete streaming', () => {
|
||||
|
||||
const result = await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'gpt-5-codex',
|
||||
model: 'gpt-5.3-codex',
|
||||
messages: [{ role: 'user', content: 'say hi' }],
|
||||
stream: true,
|
||||
}),
|
||||
@@ -563,7 +563,7 @@ describe('AzureResponsesProvider.complete streaming', () => {
|
||||
completion_tokens: 2,
|
||||
cached_tokens: 1,
|
||||
});
|
||||
expect(recordSpy.mock.calls[0]![2]).toBe('azure-openai:gpt-5-codex');
|
||||
expect(recordSpy.mock.calls[0]![2]).toBe('azure-openai:gpt-5.3-codex');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -617,7 +617,7 @@ describe('AzureResponsesProvider.complete error mapping', () => {
|
||||
await expect(
|
||||
withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'gpt-5-codex',
|
||||
model: 'gpt-5.3-codex',
|
||||
messages: [{ role: 'user', content: 'boom' }],
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -49,7 +49,7 @@ export class AzureResponsesProvider implements IChatProvider {
|
||||
/** @type {import('openai').OpenAI} */
|
||||
#openAi: OpenAI;
|
||||
|
||||
#defaultModel = 'gpt-5-codex';
|
||||
#defaultModel = 'gpt-5.3-codex';
|
||||
|
||||
#meteringService: MeteringService;
|
||||
|
||||
|
||||
@@ -170,30 +170,6 @@ export const AZURE_MODELS: IChatModel[] = [
|
||||
context: 128_000,
|
||||
max_tokens: 128000,
|
||||
},
|
||||
{
|
||||
// Costs mirror openai gpt-5-codex (same list price as gpt-5).
|
||||
puterId: 'azure:openai/gpt-5-codex',
|
||||
id: 'gpt-5-codex',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2024-09-30',
|
||||
release_date: '2025-08-07',
|
||||
aliases: ['openai/gpt-5-codex'],
|
||||
// Codex models are Responses-API only on Azure, same as OpenAI.
|
||||
responses_api_only: true,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 125,
|
||||
cached_tokens: 13,
|
||||
completion_tokens: 1000,
|
||||
},
|
||||
context: 128_000,
|
||||
max_tokens: 128000,
|
||||
},
|
||||
{
|
||||
// Costs mirror openai gpt-5-nano.
|
||||
puterId: 'azure:openai/gpt-5-nano',
|
||||
@@ -260,29 +236,6 @@ export const AZURE_MODELS: IChatModel[] = [
|
||||
context: 128_000,
|
||||
max_tokens: 16384,
|
||||
},
|
||||
{
|
||||
// Costs mirror openai gpt-5.1-codex-mini.
|
||||
puterId: 'azure:openai/gpt-5.1-codex-mini',
|
||||
id: 'gpt-5.1-codex-mini',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2024-09-30',
|
||||
release_date: '2025-11-13',
|
||||
aliases: ['openai/gpt-5.1-codex-mini'],
|
||||
responses_api_only: true,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 25,
|
||||
cached_tokens: 3,
|
||||
completion_tokens: 200,
|
||||
},
|
||||
context: 128_000,
|
||||
max_tokens: 128000,
|
||||
},
|
||||
{
|
||||
// Costs mirror openai gpt-5.1.
|
||||
puterId: 'azure:openai/gpt-5.1',
|
||||
@@ -305,29 +258,6 @@ export const AZURE_MODELS: IChatModel[] = [
|
||||
context: 128_000,
|
||||
max_tokens: 128000,
|
||||
},
|
||||
{
|
||||
// Costs mirror openai gpt-5.1-codex.
|
||||
puterId: 'azure:openai/gpt-5.1-codex',
|
||||
id: 'gpt-5.1-codex',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2024-09-30',
|
||||
release_date: '2025-11-13',
|
||||
aliases: ['openai/gpt-5.1-codex'],
|
||||
responses_api_only: true,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 125,
|
||||
cached_tokens: 13,
|
||||
completion_tokens: 1000,
|
||||
},
|
||||
context: 128_000,
|
||||
max_tokens: 128000,
|
||||
},
|
||||
{
|
||||
// Costs mirror openai gpt-5.2.
|
||||
puterId: 'azure:openai/gpt-5.2',
|
||||
@@ -350,29 +280,6 @@ export const AZURE_MODELS: IChatModel[] = [
|
||||
context: 128_000,
|
||||
max_tokens: 128000,
|
||||
},
|
||||
{
|
||||
// Costs mirror openai gpt-5.2-codex.
|
||||
puterId: 'azure:openai/gpt-5.2-codex',
|
||||
id: 'gpt-5.2-codex',
|
||||
modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2025-08-31',
|
||||
release_date: '2025-12-11',
|
||||
aliases: ['openai/gpt-5.2-codex'],
|
||||
responses_api_only: true,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 175,
|
||||
cached_tokens: 18,
|
||||
completion_tokens: 1400,
|
||||
},
|
||||
context: 128_000,
|
||||
max_tokens: 128000,
|
||||
},
|
||||
{
|
||||
// Costs mirror openai gpt-5.4-nano.
|
||||
puterId: 'azure:openai/gpt-5.4-nano',
|
||||
|
||||
@@ -49,6 +49,87 @@ export const GEMINI_MODELS: IChatModel[] = [
|
||||
grounding_requests: 1_400_000,
|
||||
},
|
||||
},
|
||||
{
|
||||
puterId: 'google:google/gemini-3.5-flash-lite',
|
||||
id: 'gemini-3.5-flash-lite',
|
||||
modalities: {
|
||||
input: ['text', 'image', 'audio', 'video', 'pdf'],
|
||||
output: ['text'],
|
||||
},
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2025-01',
|
||||
release_date: '2026-07-21',
|
||||
name: 'Gemini 3.5 Flash-Lite',
|
||||
aliases: ['google/gemini-3.5-flash-lite'],
|
||||
context: 1_048_576,
|
||||
max_tokens: 65_536,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 30,
|
||||
completion_tokens: 250,
|
||||
thinking_tokens: 250,
|
||||
cached_tokens: 3,
|
||||
grounding_requests: 1_400_000,
|
||||
},
|
||||
},
|
||||
{
|
||||
puterId: 'google:google/gemini-3.6-flash',
|
||||
id: 'gemini-3.6-flash',
|
||||
modalities: {
|
||||
input: ['text', 'image', 'audio', 'video', 'pdf'],
|
||||
output: ['text'],
|
||||
},
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2025-01',
|
||||
release_date: '2026-07-21',
|
||||
name: 'Gemini 3.6 Flash',
|
||||
aliases: ['google/gemini-3.6-flash'],
|
||||
context: 1_048_576,
|
||||
max_tokens: 65_536,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 150,
|
||||
completion_tokens: 750,
|
||||
thinking_tokens: 750,
|
||||
cached_tokens: 15,
|
||||
grounding_requests: 1_400_000,
|
||||
},
|
||||
},
|
||||
{
|
||||
puterId: 'google:google/gemini-3.7-flash',
|
||||
id: 'gemini-3.7-flash',
|
||||
modalities: {
|
||||
input: ['text', 'image', 'audio', 'video', 'pdf'],
|
||||
output: ['text'],
|
||||
},
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2025-01',
|
||||
release_date: '2026-08-13',
|
||||
name: 'Gemini 3.7 Flash',
|
||||
aliases: ['google/gemini-3.7-flash'],
|
||||
context: 1_048_576,
|
||||
max_tokens: 65_536,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 75,
|
||||
completion_tokens: 375,
|
||||
thinking_tokens: 375,
|
||||
cached_tokens: 8,
|
||||
grounding_requests: 1_400_000,
|
||||
},
|
||||
},
|
||||
{
|
||||
puterId: 'google:google/gemini-2.5-flash',
|
||||
id: 'gemini-2.5-flash',
|
||||
|
||||
@@ -305,16 +305,16 @@ describe('GroqAIProvider model resolution', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'gemma2-9b-it',
|
||||
model: 'llama-3.3-70b-versatile',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
}),
|
||||
);
|
||||
|
||||
expect(createMock.mock.calls[0]![0].model).toBe('gemma2-9b-it');
|
||||
expect(createMock.mock.calls[0]![0].model).toBe('llama-3.3-70b-versatile');
|
||||
expect(recordSpy).toHaveBeenCalledWith(
|
||||
expect.any(Object),
|
||||
expect.anything(),
|
||||
'groq:gemma2-9b-it',
|
||||
'groq:llama-3.3-70b-versatile',
|
||||
expect.any(Object),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -19,116 +19,17 @@
|
||||
|
||||
import type { IChatModel } from '../../types.js';
|
||||
|
||||
// Hardcoded from https://models.dev/api.json
|
||||
// Hardcoded from https://models.dev/api.json (Groq chat/text models)
|
||||
export const GROQ_MODELS: IChatModel[] = [
|
||||
{
|
||||
id: 'gemma2-9b-it',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: true,
|
||||
knowledge: '2024-06',
|
||||
release_date: '2024-06-27',
|
||||
name: 'Gemma 2 9B 8k',
|
||||
context: 8192,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 20,
|
||||
completion_tokens: 20,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 8192,
|
||||
},
|
||||
{
|
||||
id: 'gemma-7b-it',
|
||||
// Not present in models.dev/api.json (as of 2026-02-11)
|
||||
name: 'Gemma 7B 8k Instruct',
|
||||
context: 8192,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 7,
|
||||
completion_tokens: 7,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 8192,
|
||||
},
|
||||
{
|
||||
id: 'llama3-groq-70b-8192-tool-use-preview',
|
||||
// Not present in models.dev/api.json (as of 2026-02-11)
|
||||
name: 'Llama 3 Groq 70B Tool Use Preview 8k',
|
||||
context: 8192,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 89,
|
||||
completion_tokens: 89,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 8192,
|
||||
},
|
||||
{
|
||||
id: 'llama3-groq-8b-8192-tool-use-preview',
|
||||
// Not present in models.dev/api.json (as of 2026-02-11)
|
||||
name: 'Llama 3 Groq 8B Tool Use Preview 8k',
|
||||
context: 8192,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 19,
|
||||
completion_tokens: 19,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 8192,
|
||||
},
|
||||
{
|
||||
id: 'llama-3.1-70b-versatile',
|
||||
// Not present in models.dev/api.json (as of 2026-02-11)
|
||||
name: 'Llama 3.1 70B Versatile 128k',
|
||||
context: 128000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 59,
|
||||
completion_tokens: 79,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 128000,
|
||||
},
|
||||
{
|
||||
id: 'llama-3.1-70b-specdec',
|
||||
// Not present in models.dev/api.json (as of 2026-02-11)
|
||||
name: 'Llama 3.1 8B Instant 128k',
|
||||
context: 128000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 59,
|
||||
completion_tokens: 99,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 128000,
|
||||
},
|
||||
{
|
||||
puterId: 'groq:llama-3.1-8b-instant',
|
||||
id: 'llama-3.1-8b-instant',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: true,
|
||||
knowledge: '2023-12',
|
||||
release_date: '2024-07-23',
|
||||
name: 'Llama 3.1 8B Instant 128k',
|
||||
name: 'Llama 3.1 8B Instant',
|
||||
aliases: ['llama-3.1-8b-instant'],
|
||||
context: 131072,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
@@ -142,28 +43,182 @@ export const GROQ_MODELS: IChatModel[] = [
|
||||
max_tokens: 131072,
|
||||
},
|
||||
{
|
||||
id: 'meta-llama/llama-guard-4-12b',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
puterId: 'groq:llama-3.3-70b-versatile',
|
||||
id: 'llama-3.3-70b-versatile',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: false,
|
||||
release_date: '2025-04-05',
|
||||
name: 'Llama Guard 4 12B',
|
||||
tool_call: true,
|
||||
release_date: '2024-12-06',
|
||||
name: 'Llama 3.3 70B Versatile',
|
||||
aliases: ['llama-3.3-70b-versatile'],
|
||||
context: 131072,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 20,
|
||||
completion_tokens: 20,
|
||||
prompt_tokens: 59,
|
||||
completion_tokens: 79,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 1024,
|
||||
max_tokens: 32768,
|
||||
},
|
||||
{
|
||||
puterId: 'groq:openai/gpt-oss-120b',
|
||||
id: 'openai/gpt-oss-120b',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: true,
|
||||
release_date: '2025-08-05',
|
||||
name: 'GPT OSS 120B',
|
||||
aliases: ['openai/gpt-oss-120b'],
|
||||
context: 131072,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 15,
|
||||
completion_tokens: 60,
|
||||
cached_tokens: 8,
|
||||
},
|
||||
max_tokens: 65536,
|
||||
},
|
||||
{
|
||||
puterId: 'groq:openai/gpt-oss-20b',
|
||||
id: 'openai/gpt-oss-20b',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: true,
|
||||
release_date: '2025-08-05',
|
||||
name: 'GPT OSS 20B',
|
||||
aliases: ['openai/gpt-oss-20b'],
|
||||
context: 131072,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 8,
|
||||
completion_tokens: 30,
|
||||
cached_tokens: 4,
|
||||
},
|
||||
max_tokens: 65536,
|
||||
},
|
||||
{
|
||||
puterId: 'groq:openai/gpt-oss-safeguard-20b',
|
||||
id: 'openai/gpt-oss-safeguard-20b',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: true,
|
||||
release_date: '2025-10-29',
|
||||
name: 'GPT OSS Safeguard 20B',
|
||||
aliases: ['openai/gpt-oss-safeguard-20b'],
|
||||
context: 131072,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 8,
|
||||
completion_tokens: 30,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 65536,
|
||||
},
|
||||
{
|
||||
puterId: 'groq:groq/compound',
|
||||
id: 'groq/compound',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: false,
|
||||
release_date: '2025-09-04',
|
||||
name: 'Groq Compound',
|
||||
aliases: ['groq/compound'],
|
||||
context: 131072,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 0,
|
||||
completion_tokens: 0,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 8192,
|
||||
},
|
||||
{
|
||||
puterId: 'groq:groq/compound-mini',
|
||||
id: 'groq/compound-mini',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: false,
|
||||
release_date: '2025-09-04',
|
||||
name: 'Groq Compound Mini',
|
||||
aliases: ['groq/compound-mini'],
|
||||
context: 131072,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 0,
|
||||
completion_tokens: 0,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 8192,
|
||||
},
|
||||
{
|
||||
puterId: 'groq:qwen/qwen3.6-27b',
|
||||
id: 'qwen/qwen3.6-27b',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: true,
|
||||
release_date: '2026-04-22',
|
||||
name: 'Qwen3.6 27B',
|
||||
aliases: ['qwen/qwen3.6-27b'],
|
||||
context: 131072,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 60,
|
||||
completion_tokens: 300,
|
||||
cached_tokens: 30,
|
||||
},
|
||||
max_tokens: 16384,
|
||||
},
|
||||
{
|
||||
puterId: 'groq:meta-llama/llama-prompt-guard-2-22m',
|
||||
id: 'meta-llama/llama-prompt-guard-2-22m',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: false,
|
||||
release_date: '2025-05-29',
|
||||
name: 'Llama Prompt Guard 2 22M',
|
||||
aliases: ['meta-llama/llama-prompt-guard-2-22m'],
|
||||
context: 512,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 3,
|
||||
completion_tokens: 3,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 512,
|
||||
},
|
||||
{
|
||||
puterId: 'groq:meta-llama/llama-prompt-guard-2-86m',
|
||||
id: 'meta-llama/llama-prompt-guard-2-86m',
|
||||
// Not present in models.dev/api.json (as of 2026-02-11)
|
||||
name: 'Prompt Guard 2 86M',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: false,
|
||||
release_date: '2025-05-29',
|
||||
name: 'Llama Prompt Guard 2 86M',
|
||||
aliases: ['meta-llama/llama-prompt-guard-2-86m'],
|
||||
context: 512,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
@@ -177,133 +232,36 @@ export const GROQ_MODELS: IChatModel[] = [
|
||||
max_tokens: 512,
|
||||
},
|
||||
{
|
||||
id: 'llama-3.2-1b-preview',
|
||||
// Not present in models.dev/api.json (as of 2026-02-11)
|
||||
name: 'Llama 3.2 1B (Preview) 8k',
|
||||
context: 128000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 4,
|
||||
completion_tokens: 4,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 128000,
|
||||
},
|
||||
{
|
||||
id: 'llama-3.2-3b-preview',
|
||||
// Not present in models.dev/api.json (as of 2026-02-11)
|
||||
name: 'Llama 3.2 3B (Preview) 8k',
|
||||
context: 128000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 6,
|
||||
completion_tokens: 6,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 128000,
|
||||
},
|
||||
{
|
||||
id: 'llama-3.2-11b-vision-preview',
|
||||
// Not present in models.dev/api.json (as of 2026-02-11)
|
||||
name: 'Llama 3.2 11B Vision 8k (Preview)',
|
||||
context: 8000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 18,
|
||||
completion_tokens: 18,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 8000,
|
||||
},
|
||||
{
|
||||
id: 'llama-3.2-90b-vision-preview',
|
||||
// Not present in models.dev/api.json (as of 2026-02-11)
|
||||
name: 'Llama 3.2 90B Vision 8k (Preview)',
|
||||
context: 8000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 90,
|
||||
completion_tokens: 90,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 8000,
|
||||
},
|
||||
{
|
||||
id: 'llama3-70b-8192',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: true,
|
||||
knowledge: '2023-03',
|
||||
release_date: '2024-04-18',
|
||||
name: 'Llama 3 70B 8k',
|
||||
context: 8192,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 59,
|
||||
completion_tokens: 79,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 8192,
|
||||
},
|
||||
{
|
||||
id: 'llama3-8b-8192',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: true,
|
||||
knowledge: '2023-03',
|
||||
release_date: '2024-04-18',
|
||||
name: 'Llama 3 8B 8k',
|
||||
context: 8192,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 5,
|
||||
completion_tokens: 8,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 8192,
|
||||
},
|
||||
{
|
||||
id: 'mixtral-8x7b-32768',
|
||||
// Not present in models.dev/api.json (as of 2026-02-11)
|
||||
name: 'Mixtral 8x7B Instruct 32k',
|
||||
context: 32768,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 24,
|
||||
completion_tokens: 24,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 32768,
|
||||
},
|
||||
{
|
||||
id: 'llama-guard-3-8b',
|
||||
puterId: 'groq:allam-2-7b',
|
||||
id: 'allam-2-7b',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: false,
|
||||
release_date: '2024-07-23',
|
||||
name: 'Llama Guard 3 8B 8k',
|
||||
context: 8192,
|
||||
release_date: '2025-01-23',
|
||||
name: 'ALLaM 2 7B',
|
||||
aliases: ['allam-2-7b'],
|
||||
context: 4096,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 0,
|
||||
completion_tokens: 0,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 4096,
|
||||
},
|
||||
{
|
||||
puterId: 'groq:meta-llama/llama-guard-4-12b',
|
||||
id: 'meta-llama/llama-guard-4-12b',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: false,
|
||||
release_date: '2025-04-05',
|
||||
name: 'Llama Guard 4 12B',
|
||||
aliases: ['meta-llama/llama-guard-4-12b'],
|
||||
context: 131072,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
@@ -313,6 +271,6 @@ export const GROQ_MODELS: IChatModel[] = [
|
||||
completion_tokens: 20,
|
||||
cached_tokens: 0,
|
||||
},
|
||||
max_tokens: 8192,
|
||||
max_tokens: 1024,
|
||||
},
|
||||
];
|
||||
@@ -22,8 +22,8 @@ import type { IChatModel } from '../../types.js';
|
||||
// Hardcoded from https://models.dev/api.json and https://docs.mistral.ai/models/overview
|
||||
export const MISTRAL_MODELS: IChatModel[] = [
|
||||
{
|
||||
puterId: 'mistralai:mistralai/mistral-medium-3-5',
|
||||
id: 'mistral-medium-3-5',
|
||||
puterId: 'mistralai:mistralai/mistral-medium-2604',
|
||||
id: 'mistral-medium-2604',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: true,
|
||||
@@ -31,8 +31,10 @@ export const MISTRAL_MODELS: IChatModel[] = [
|
||||
release_date: '2026-04-29',
|
||||
name: 'Mistral Medium 3.5',
|
||||
aliases: [
|
||||
'mistral-medium-3-5',
|
||||
'mistral-medium-3',
|
||||
'mistral-medium-2604',
|
||||
'mistral-medium-latest',
|
||||
'mistral-medium',
|
||||
'mistralai/mistral-medium-3-5',
|
||||
'mistralai/mistral-medium-2604',
|
||||
],
|
||||
@@ -50,34 +52,6 @@ export const MISTRAL_MODELS: IChatModel[] = [
|
||||
completion_tokens: 750,
|
||||
},
|
||||
},
|
||||
{
|
||||
puterId: 'mistralai:mistralai/mistral-medium-2508',
|
||||
id: 'mistral-medium-2508',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2025-05',
|
||||
release_date: '2025-08-12',
|
||||
name: 'Mistral Medium 3.1',
|
||||
aliases: [
|
||||
'mistralai/mistral-medium-2508',
|
||||
'mistral-medium-2508',
|
||||
'mistral-medium-latest',
|
||||
'mistralai/mistral-medium-latest',
|
||||
],
|
||||
context: 262_144,
|
||||
max_tokens: 262_144,
|
||||
description: 'Frontier-class multimodal model.',
|
||||
provider: 'mistral',
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 40,
|
||||
completion_tokens: 200,
|
||||
},
|
||||
},
|
||||
{
|
||||
puterId: 'mistralai:mistralai/mistral-large-2512',
|
||||
id: 'mistral-large-2512',
|
||||
@@ -161,68 +135,19 @@ export const MISTRAL_MODELS: IChatModel[] = [
|
||||
},
|
||||
},
|
||||
{
|
||||
puterId: 'mistralai:mistralai/devstral-2512',
|
||||
id: 'devstral-2512',
|
||||
puterId: 'mistralai:mistralai/magistral-small-latest',
|
||||
id: 'magistral-small-latest',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: true,
|
||||
knowledge: '2025-12',
|
||||
release_date: '2025-12-09',
|
||||
name: 'Devstral 2',
|
||||
knowledge: '2025-06',
|
||||
release_date: '2025-09-01',
|
||||
name: 'Magistral Small',
|
||||
aliases: [
|
||||
'devstral-latest',
|
||||
'mistralai/devstral-latest',
|
||||
'mistralai/devstral-2512',
|
||||
'devstral-medium-latest',
|
||||
'mistralai/devstral-medium-latest',
|
||||
'magistral-small-2509',
|
||||
'mistralai/magistral-small-2509',
|
||||
'mistralai/magistral-small-latest',
|
||||
],
|
||||
context: 262_144,
|
||||
max_tokens: 262_144,
|
||||
description:
|
||||
'Frontier open-source code agents model for software engineering.',
|
||||
provider: 'mistral',
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 40,
|
||||
completion_tokens: 200,
|
||||
},
|
||||
},
|
||||
{
|
||||
puterId: 'mistralai:mistralai/magistral-medium-2509',
|
||||
id: 'magistral-medium-2509',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2025-06',
|
||||
release_date: '2025-09-01',
|
||||
name: 'Magistral Medium 1.2',
|
||||
aliases: ['magistral-medium-latest', 'mistralai/magistral-medium-2509'],
|
||||
context: 131_072,
|
||||
max_tokens: 131_072,
|
||||
description: 'Frontier-class multimodal reasoning model.',
|
||||
provider: 'mistral',
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 200,
|
||||
completion_tokens: 500,
|
||||
},
|
||||
},
|
||||
{
|
||||
puterId: 'mistralai:mistralai/magistral-small-2509',
|
||||
id: 'magistral-small-2509',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: true,
|
||||
knowledge: '2025-06',
|
||||
release_date: '2025-09-01',
|
||||
name: 'Magistral Small 1.2',
|
||||
aliases: ['magistral-small-latest', 'mistralai/magistral-small-2509'],
|
||||
context: 131_072,
|
||||
max_tokens: 131_072,
|
||||
description: 'Efficient open-weight reasoning model.',
|
||||
@@ -306,38 +231,7 @@ export const MISTRAL_MODELS: IChatModel[] = [
|
||||
prompt_tokens: 4,
|
||||
completion_tokens: 4,
|
||||
},
|
||||
},
|
||||
{
|
||||
puterId: 'mistralai:mistralai/open-mistral-nemo-2407',
|
||||
id: 'open-mistral-nemo-2407',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: true,
|
||||
tool_call: true,
|
||||
knowledge: '2024-07',
|
||||
release_date: '2024-07-25',
|
||||
name: 'Mistral Nemo 12B',
|
||||
aliases: [
|
||||
'open-mistral-nemo',
|
||||
'mistral-nemo',
|
||||
'mistral-nemo-latest',
|
||||
'mistralai/open-mistral-nemo',
|
||||
'mistralai/open-mistral-nemo-2407',
|
||||
'mistralai/mistral-nemo',
|
||||
],
|
||||
context: 128_000,
|
||||
max_tokens: 128_000,
|
||||
description: 'Best multilingual open source model.',
|
||||
provider: 'mistral',
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 15,
|
||||
completion_tokens: 15,
|
||||
},
|
||||
},
|
||||
{
|
||||
}, {
|
||||
puterId: 'mistralai:mistralai/voxtral-small-2507',
|
||||
id: 'voxtral-small-2507',
|
||||
modalities: { input: ['text', 'audio'], output: ['text'] },
|
||||
|
||||
@@ -68,6 +68,55 @@ export const MOONSHOT_MODELS: IChatModel[] = [
|
||||
knowledge: '2025-01',
|
||||
},
|
||||
|
||||
// -- Kimi K2.7 Code ---------------------------------------------
|
||||
{
|
||||
puterId: 'moonshotai:moonshotai/kimi-k2.7-code',
|
||||
id: 'kimi-k2.7-code',
|
||||
name: 'Kimi K2.7 Code',
|
||||
aliases: [
|
||||
'moonshotai/kimi-k2.7-code',
|
||||
'moonshot/kimi-k2.7-code',
|
||||
],
|
||||
modalities: { input: ['text', 'image', 'video'], output: ['text'] },
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 95,
|
||||
completion_tokens: 400,
|
||||
cached_tokens: 19,
|
||||
},
|
||||
context: 262_144,
|
||||
max_tokens: 262_144,
|
||||
tool_call: true,
|
||||
release_date: '2026-06-12',
|
||||
},
|
||||
{
|
||||
puterId: 'moonshotai:moonshotai/kimi-k2.7-code-highspeed',
|
||||
id: 'kimi-k2.7-code-highspeed',
|
||||
name: 'Kimi K2.7 Code Highspeed',
|
||||
aliases: [
|
||||
'moonshotai/kimi-k2.7-code-highspeed',
|
||||
'moonshot/kimi-k2.7-code-highspeed',
|
||||
],
|
||||
modalities: { input: ['text', 'image', 'video'], output: ['text'] },
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 190,
|
||||
completion_tokens: 800,
|
||||
cached_tokens: 38,
|
||||
},
|
||||
context: 262_144,
|
||||
max_tokens: 262_144,
|
||||
tool_call: true,
|
||||
release_date: '2026-06-12',
|
||||
},
|
||||
|
||||
|
||||
// -- Kimi K2.5 --------------------------------------------------
|
||||
{
|
||||
puterId: 'moonshotai:moonshotai/kimi-k2.5',
|
||||
|
||||
@@ -218,6 +218,28 @@ export const OPEN_AI_MODELS: IChatModel[] = [
|
||||
context: 400_000,
|
||||
max_tokens: 128_000,
|
||||
},
|
||||
{
|
||||
puterId: 'openai:openai/gpt-5-pro',
|
||||
id: 'gpt-5-pro',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2025-10',
|
||||
release_date: '2025-10-06',
|
||||
aliases: ['gpt-5-pro', 'openai/gpt-5-pro'],
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 1500,
|
||||
completion_tokens: 12000,
|
||||
},
|
||||
context: 400_000,
|
||||
max_tokens: 272_000,
|
||||
responses_api_only: true,
|
||||
},
|
||||
|
||||
{
|
||||
puterId: 'openai:openai/gpt-5.3-codex',
|
||||
id: 'gpt-5.3-codex',
|
||||
@@ -239,49 +261,6 @@ export const OPEN_AI_MODELS: IChatModel[] = [
|
||||
max_tokens: 128000,
|
||||
responses_api_only: true,
|
||||
},
|
||||
{
|
||||
puterId: 'openai:openai/gpt-5.2-codex',
|
||||
id: 'gpt-5.2-codex',
|
||||
modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2025-08-31',
|
||||
release_date: '2025-12-11',
|
||||
aliases: ['openai/gpt-5.2-codex'],
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 175,
|
||||
cached_tokens: 18,
|
||||
completion_tokens: 1400,
|
||||
},
|
||||
context: 128_000,
|
||||
max_tokens: 128000,
|
||||
responses_api_only: true,
|
||||
},
|
||||
{
|
||||
puterId: 'openai:openai/gpt-5.2-chat',
|
||||
id: 'gpt-5.2-chat-latest',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2025-08-31',
|
||||
release_date: '2025-12-11',
|
||||
aliases: ['gpt-5.2-chat', 'openai/gpt-5.2-chat'],
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 175,
|
||||
cached_tokens: 17.5,
|
||||
completion_tokens: 1400,
|
||||
},
|
||||
context: 128_000,
|
||||
max_tokens: 16384,
|
||||
},
|
||||
{
|
||||
puterId: 'openai:openai/gpt-5.2-pro',
|
||||
id: 'gpt-5.2-pro-2025-12-11',
|
||||
@@ -345,71 +324,6 @@ export const OPEN_AI_MODELS: IChatModel[] = [
|
||||
context: 128_000,
|
||||
max_tokens: 128000,
|
||||
},
|
||||
{
|
||||
puterId: 'openai:openai/gpt-5.1-codex',
|
||||
id: 'gpt-5.1-codex',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2024-09-30',
|
||||
release_date: '2025-11-13',
|
||||
aliases: ['openai/gpt-5.1-codex'],
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 125,
|
||||
cached_tokens: 13,
|
||||
completion_tokens: 1000,
|
||||
},
|
||||
context: 128_000,
|
||||
max_tokens: 128000,
|
||||
responses_api_only: true,
|
||||
},
|
||||
{
|
||||
puterId: 'openai:openai/gpt-5.1-codex-mini',
|
||||
id: 'gpt-5.1-codex-mini',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2024-09-30',
|
||||
release_date: '2025-11-13',
|
||||
aliases: ['openai/gpt-5.1-codex-mini'],
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 25,
|
||||
cached_tokens: 3,
|
||||
completion_tokens: 200,
|
||||
},
|
||||
context: 128_000,
|
||||
max_tokens: 128000,
|
||||
responses_api_only: true,
|
||||
},
|
||||
{
|
||||
puterId: 'openai:openai/gpt-5.1-chat',
|
||||
id: 'gpt-5.1-chat-latest',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2024-09-30',
|
||||
release_date: '2025-11-13',
|
||||
aliases: ['openai/gpt-5.1-chat'],
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 125,
|
||||
cached_tokens: 13,
|
||||
completion_tokens: 1000,
|
||||
},
|
||||
context: 128_000,
|
||||
max_tokens: 16384,
|
||||
},
|
||||
{
|
||||
puterId: 'openai:openai/gpt-5',
|
||||
id: 'gpt-5-2025-08-07',
|
||||
@@ -431,30 +345,6 @@ export const OPEN_AI_MODELS: IChatModel[] = [
|
||||
context: 128_000,
|
||||
max_tokens: 128000,
|
||||
},
|
||||
{
|
||||
puterId: 'openai:openai/gpt-5-codex',
|
||||
id: 'gpt-5-codex',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2024-09-30',
|
||||
release_date: '2025-09-15',
|
||||
aliases: ['openai/gpt-5-codex'],
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
// models.dev openai: input $1.25 / output $10 / cache_read $0.125
|
||||
// per 1M — identical to gpt-5.
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 125,
|
||||
cached_tokens: 13,
|
||||
completion_tokens: 1000,
|
||||
},
|
||||
context: 128_000,
|
||||
max_tokens: 128000,
|
||||
responses_api_only: true,
|
||||
},
|
||||
{
|
||||
puterId: 'openai:openai/gpt-5-mini',
|
||||
id: 'gpt-5-mini-2025-08-07',
|
||||
@@ -497,27 +387,6 @@ export const OPEN_AI_MODELS: IChatModel[] = [
|
||||
context: 128_000,
|
||||
max_tokens: 128000,
|
||||
},
|
||||
{
|
||||
puterId: 'openai:openai/gpt-5-chat',
|
||||
id: 'gpt-5-chat-latest',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: false,
|
||||
knowledge: '2024-09-30',
|
||||
release_date: '2025-08-07',
|
||||
aliases: ['openai/gpt-5-chat'],
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 125,
|
||||
cached_tokens: 13,
|
||||
completion_tokens: 1000,
|
||||
},
|
||||
context: 128_000,
|
||||
max_tokens: 16384,
|
||||
},
|
||||
{
|
||||
puterId: 'openai:openai/gpt-4o',
|
||||
id: 'gpt-4o',
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
/**
|
||||
* Integration test for the xAI (Grok) provider.
|
||||
*
|
||||
* Uses `grok-3-mini` — the cheapest small variant. Skipped when
|
||||
* Uses `grok-build-0.1` — the cheapest coding/build variant. Skipped when
|
||||
* `PUTER_TEST_AI_XAI_API_KEY` is unset.
|
||||
*/
|
||||
|
||||
@@ -37,7 +37,7 @@ import { XAIProvider } from './XAIProvider.js';
|
||||
const ENV_VAR = 'PUTER_TEST_AI_XAI_API_KEY';
|
||||
|
||||
describe.skipIf(skipUnlessEnv(ENV_VAR))('XAIProvider (integration)', () => {
|
||||
it('returns a non-empty completion from grok-3-mini', { timeout: INTEGRATION_TEST_TIMEOUT_MS }, async () => {
|
||||
it('returns a non-empty completion from grok-build-0.1', { timeout: INTEGRATION_TEST_TIMEOUT_MS }, async () => {
|
||||
const provider = new XAIProvider(
|
||||
{ apiKey: optionalEnv(ENV_VAR)! },
|
||||
makeMeteringStub(),
|
||||
@@ -45,7 +45,7 @@ describe.skipIf(skipUnlessEnv(ENV_VAR))('XAIProvider (integration)', () => {
|
||||
|
||||
const result = await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'grok-3-mini',
|
||||
model: 'grok-build-0.1',
|
||||
messages: [{ role: 'user', content: 'Say hi in one word.' }],
|
||||
max_tokens: 16,
|
||||
}),
|
||||
|
||||
@@ -177,8 +177,8 @@ describe('XAIProvider model catalog', () => {
|
||||
}
|
||||
}
|
||||
// Sanity: a known alias resolves to its expected id sibling.
|
||||
expect(names).toContain('grok-3');
|
||||
expect(names).toContain('x-ai/grok-3');
|
||||
expect(names).toContain('grok-4.6');
|
||||
expect(names).toContain('x-ai/grok-4.6');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -201,13 +201,13 @@ describe('XAIProvider.complete request shape', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'grok-3',
|
||||
model: 'grok-4.6',
|
||||
messages: [{ role: 'user', content: 'hello' }],
|
||||
}),
|
||||
);
|
||||
|
||||
const [args] = createMock.mock.calls[0]!;
|
||||
expect(args.model).toBe('grok-3');
|
||||
expect(args.model).toBe('grok-4.6');
|
||||
expect(args.messages).toEqual([{ role: 'user', content: 'hello' }]);
|
||||
// max_tokens is hardcoded by the provider — the call to xAI
|
||||
// should always cap at 1000 tokens of completion.
|
||||
@@ -220,7 +220,7 @@ describe('XAIProvider.complete request shape', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'grok-3',
|
||||
model: 'grok-4.6',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
}),
|
||||
);
|
||||
@@ -251,7 +251,7 @@ describe('XAIProvider.complete request shape', () => {
|
||||
];
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'grok-3',
|
||||
model: 'grok-4.6',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
tools,
|
||||
}),
|
||||
@@ -268,7 +268,7 @@ describe('XAIProvider.complete request shape', () => {
|
||||
createMock.mockResolvedValueOnce(baseCompletion);
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'grok-3',
|
||||
model: 'grok-4.6',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
stream: false,
|
||||
}),
|
||||
@@ -281,7 +281,7 @@ describe('XAIProvider.complete request shape', () => {
|
||||
createMock.mockReturnValueOnce(asAsyncIterable([]));
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'grok-3',
|
||||
model: 'grok-4.6',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
stream: true,
|
||||
}),
|
||||
@@ -297,7 +297,7 @@ describe('XAIProvider.complete request shape', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'grok-3',
|
||||
model: 'grok-4.6',
|
||||
messages: [
|
||||
{
|
||||
role: 'assistant',
|
||||
@@ -350,17 +350,17 @@ describe('XAIProvider model resolution', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'grok-3-mini',
|
||||
model: 'grok-build-0.1',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
}),
|
||||
);
|
||||
|
||||
expect(createMock.mock.calls[0]![0].model).toBe('grok-3-mini');
|
||||
expect(createMock.mock.calls[0]![0].model).toBe('grok-build-0.1');
|
||||
// Metering namespace mirrors the resolved canonical id.
|
||||
expect(recordSpy).toHaveBeenCalledWith(
|
||||
expect.any(Object),
|
||||
expect.anything(),
|
||||
'xai:grok-3-mini',
|
||||
'xai:grok-build-0.1',
|
||||
expect.any(Object),
|
||||
);
|
||||
});
|
||||
@@ -371,18 +371,18 @@ describe('XAIProvider model resolution', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
// `x-ai/grok-3` is an alias of `grok-3` in models.ts.
|
||||
model: 'x-ai/grok-3',
|
||||
// `x-ai/grok-4.6` is an alias of `grok-4.6` in models.ts.
|
||||
model: 'x-ai/grok-4.6',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
}),
|
||||
);
|
||||
|
||||
// The wire model should be the canonical id, not the alias.
|
||||
expect(createMock.mock.calls[0]![0].model).toBe('grok-3');
|
||||
expect(createMock.mock.calls[0]![0].model).toBe('grok-4.6');
|
||||
expect(recordSpy).toHaveBeenCalledWith(
|
||||
expect.any(Object),
|
||||
expect.anything(),
|
||||
'xai:grok-3',
|
||||
'xai:grok-4.6',
|
||||
expect.any(Object),
|
||||
);
|
||||
});
|
||||
@@ -465,7 +465,7 @@ describe('XAIProvider.complete non-stream output', () => {
|
||||
|
||||
const result = await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'grok-3',
|
||||
model: 'grok-4.6',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
}),
|
||||
);
|
||||
@@ -486,7 +486,7 @@ describe('XAIProvider.complete non-stream output', () => {
|
||||
|
||||
// Metering: usage is recorded once, with the right model
|
||||
// namespace, actor, and a costsOverride priced from
|
||||
// models.ts (grok-3: prompt=300, completion=1500, cached=0.75).
|
||||
// models.ts (grok-4.6: prompt=200, completion=600, cached=50).
|
||||
expect(recordSpy).toHaveBeenCalledTimes(1);
|
||||
const [usage, actor, prefix, overrides] =
|
||||
recordSpy.mock.calls[0]!;
|
||||
@@ -496,11 +496,11 @@ describe('XAIProvider.complete non-stream output', () => {
|
||||
cached_tokens: 10,
|
||||
});
|
||||
expect(actor).toBe(SYSTEM_ACTOR);
|
||||
expect(prefix).toBe('xai:grok-3');
|
||||
expect(prefix).toBe('xai:grok-4.6');
|
||||
expect(overrides).toEqual({
|
||||
prompt_tokens: 100 * 300,
|
||||
completion_tokens: 50 * 1500,
|
||||
cached_tokens: 10 * 0.75,
|
||||
prompt_tokens: 100 * 200,
|
||||
completion_tokens: 50 * 600,
|
||||
cached_tokens: 10 * 50,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -531,7 +531,7 @@ describe('XAIProvider.complete non-stream output', () => {
|
||||
|
||||
const result = (await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'grok-3',
|
||||
model: 'grok-4.6',
|
||||
messages: [{ role: 'user', content: 'do a tool call' }],
|
||||
tools: [
|
||||
{
|
||||
@@ -572,7 +572,7 @@ describe('XAIProvider.complete non-stream output', () => {
|
||||
|
||||
await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'grok-3',
|
||||
model: 'grok-4.6',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
}),
|
||||
);
|
||||
@@ -607,7 +607,7 @@ describe('XAIProvider.complete streaming', () => {
|
||||
|
||||
const result = await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'grok-3-mini',
|
||||
model: 'grok-build-0.1',
|
||||
messages: [{ role: 'user', content: 'say hi' }],
|
||||
stream: true,
|
||||
}),
|
||||
@@ -634,15 +634,15 @@ describe('XAIProvider.complete streaming', () => {
|
||||
cached_tokens: 1,
|
||||
});
|
||||
|
||||
// grok-3-mini costs: prompt=30, completion=50, cached=0.075.
|
||||
// grok-build-0.1 costs: prompt=100, completion=200, cached=20.
|
||||
expect(recordSpy).toHaveBeenCalledTimes(1);
|
||||
const [, , prefix, overrides] =
|
||||
recordSpy.mock.calls[0]!;
|
||||
expect(prefix).toBe('xai:grok-3-mini');
|
||||
expect(prefix).toBe('xai:grok-build-0.1');
|
||||
expect(overrides).toEqual({
|
||||
prompt_tokens: 4 * 30,
|
||||
completion_tokens: 2 * 50,
|
||||
cached_tokens: 1 * 0.075,
|
||||
prompt_tokens: 4 * 100,
|
||||
completion_tokens: 2 * 200,
|
||||
cached_tokens: 1 * 20,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -691,7 +691,7 @@ describe('XAIProvider.complete streaming', () => {
|
||||
|
||||
const result = await withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'grok-3',
|
||||
model: 'grok-4.6',
|
||||
messages: [{ role: 'user', content: 'do tool call' }],
|
||||
tools: [
|
||||
{
|
||||
@@ -733,7 +733,7 @@ describe('XAIProvider.complete error mapping', () => {
|
||||
await expect(
|
||||
withTestActor(() =>
|
||||
provider.complete({
|
||||
model: 'grok-3',
|
||||
model: 'grok-4.6',
|
||||
messages: [{ role: 'user', content: 'boom' }],
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
|
||||
import type { IChatModel } from '../../types.js';
|
||||
|
||||
// Hardcoded from https://models.dev/api.json
|
||||
// Hardcoded from https://models.dev/api.json and live xAI /models
|
||||
export const XAI_MODELS: IChatModel[] = [
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-4.6',
|
||||
id: 'grok-4.6',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2026-02',
|
||||
@@ -46,12 +46,12 @@ export const XAI_MODELS: IChatModel[] = [
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-4.5',
|
||||
id: 'grok-4.5',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
release_date: '2026-07-08',
|
||||
name: 'Grok 4.5',
|
||||
aliases: ['x-ai/grok-4.5', 'grok-4.5-latest'],
|
||||
aliases: ['x-ai/grok-4.5', 'grok-4.5-latest', 'grok-build-latest'],
|
||||
context: 500_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
@@ -60,109 +60,19 @@ export const XAI_MODELS: IChatModel[] = [
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 200,
|
||||
completion_tokens: 600,
|
||||
cached_tokens: 50,
|
||||
cached_tokens: 30,
|
||||
},
|
||||
max_tokens: 30_000,
|
||||
},
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-3',
|
||||
id: 'grok-3',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2024-11',
|
||||
release_date: '2025-02-17',
|
||||
name: 'Grok 3',
|
||||
aliases: ['x-ai/grok-3'],
|
||||
context: 131072,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 300,
|
||||
completion_tokens: 1500,
|
||||
// Cached tokens billed at 0.75 cents / 1M tokens = 0.75 micro-cents / token
|
||||
cached_tokens: 0.75,
|
||||
},
|
||||
max_tokens: 131072,
|
||||
},
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-3-fast',
|
||||
id: 'grok-3-fast',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2024-11',
|
||||
release_date: '2025-02-17',
|
||||
name: 'Grok 3 Fast',
|
||||
aliases: ['x-ai/grok-3-fast'],
|
||||
context: 131072,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 500,
|
||||
completion_tokens: 2500,
|
||||
},
|
||||
max_tokens: 131072,
|
||||
},
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-3-mini',
|
||||
id: 'grok-3-mini',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2024-11',
|
||||
release_date: '2025-02-17',
|
||||
name: 'Grok 3 Mini',
|
||||
aliases: ['x-ai/grok-3-mini'],
|
||||
context: 131072,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 30,
|
||||
completion_tokens: 50,
|
||||
// Cached tokens billed at 0.075 cents / 1M tokens = 0.075 micro-cents / token
|
||||
cached_tokens: 0.075,
|
||||
},
|
||||
max_tokens: 131072,
|
||||
},
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-3-mini-fast',
|
||||
id: 'grok-3-mini-fast',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2024-11',
|
||||
release_date: '2025-02-17',
|
||||
name: 'Grok 3 Mini Fast',
|
||||
aliases: ['x-ai/grok-3-mini-fast'],
|
||||
context: 131072,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 60,
|
||||
completion_tokens: 400,
|
||||
// https://www.oracle.com/artificial-intelligence/generative-ai/generative-ai-service/pricing/ is the only place I could find this??
|
||||
cached_tokens: 15,
|
||||
},
|
||||
max_tokens: 131072,
|
||||
max_tokens: 500_000,
|
||||
},
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-4.3',
|
||||
id: 'grok-4.3',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
release_date: '2026-05-01',
|
||||
name: 'Grok 4.3',
|
||||
aliases: ['x-ai/grok-4.3'],
|
||||
aliases: ['x-ai/grok-4.3', 'grok-4.3-latest'],
|
||||
context: 1_000_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
@@ -171,15 +81,12 @@ export const XAI_MODELS: IChatModel[] = [
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 125,
|
||||
completion_tokens: 250,
|
||||
// Cached tokens billed at 20 cents / 1M tokens = 20 micro-cents / token
|
||||
cached_tokens: 20,
|
||||
},
|
||||
max_tokens: 30_000,
|
||||
},
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-4-20-reasoning',
|
||||
// xAI exposes this as the dated snapshot id; `grok-4-20-reasoning`
|
||||
// (and dotted forms) are accepted as aliases by callers.
|
||||
id: 'grok-4.20-0309-reasoning',
|
||||
modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
|
||||
open_weights: false,
|
||||
@@ -191,15 +98,17 @@ export const XAI_MODELS: IChatModel[] = [
|
||||
'x-ai/grok-4-20-reasoning',
|
||||
'grok-4-20-reasoning',
|
||||
'grok-4.20-reasoning',
|
||||
'grok-4.20',
|
||||
'grok-4.20-0309',
|
||||
'grok-4.20-reasoning-latest',
|
||||
'x-ai/grok-4.20-reasoning',
|
||||
],
|
||||
context: 2_000_000,
|
||||
context: 1_000_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
// models.dev xai: input $1.25 / output $2.5 / cache_read $0.2 per 1M.
|
||||
prompt_tokens: 125,
|
||||
completion_tokens: 250,
|
||||
cached_tokens: 20,
|
||||
@@ -208,8 +117,6 @@ export const XAI_MODELS: IChatModel[] = [
|
||||
},
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-4-20-non-reasoning',
|
||||
// xAI exposes this as the dated snapshot id; `grok-4-20-non-reasoning`
|
||||
// (and dotted forms) are accepted as aliases by callers.
|
||||
id: 'grok-4.20-0309-non-reasoning',
|
||||
modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
|
||||
open_weights: false,
|
||||
@@ -221,15 +128,15 @@ export const XAI_MODELS: IChatModel[] = [
|
||||
'x-ai/grok-4-20-non-reasoning',
|
||||
'grok-4-20-non-reasoning',
|
||||
'grok-4.20-non-reasoning',
|
||||
'grok-4.20-non-reasoning-latest',
|
||||
'x-ai/grok-4.20-non-reasoning',
|
||||
],
|
||||
context: 2_000_000,
|
||||
context: 1_000_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
// models.dev xai: input $1.25 / output $2.5 / cache_read $0.2 per 1M.
|
||||
prompt_tokens: 125,
|
||||
completion_tokens: 250,
|
||||
cached_tokens: 20,
|
||||
@@ -237,164 +144,56 @@ export const XAI_MODELS: IChatModel[] = [
|
||||
max_tokens: 30_000,
|
||||
},
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-4-1-fast',
|
||||
id: 'grok-4-1-fast',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
puterId: 'x-ai:x-ai/grok-4.20-multi-agent-0309',
|
||||
id: 'grok-4.20-multi-agent-0309',
|
||||
modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
tool_call: false,
|
||||
knowledge: '2025-07',
|
||||
release_date: '2025-11-19',
|
||||
name: 'Grok 4.1 Fast (Reasoning)',
|
||||
aliases: ['x-ai/grok-4-1-fast', 'grok-4-1-fast-reasoning'],
|
||||
context: 2_000_000,
|
||||
release_date: '2026-03-09',
|
||||
name: 'Grok 4.20 Multi-Agent',
|
||||
aliases: [
|
||||
'x-ai/grok-4.20-multi-agent-0309',
|
||||
'grok-4.20-multi-agent',
|
||||
'grok-4.20-multi-agent-latest',
|
||||
],
|
||||
context: 1_000_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 20,
|
||||
completion_tokens: 50,
|
||||
// Cached tokens billed at 5 cents / 1M tokens = 5 micro-cents / token
|
||||
cached_tokens: 5,
|
||||
prompt_tokens: 125,
|
||||
completion_tokens: 250,
|
||||
cached_tokens: 20,
|
||||
},
|
||||
max_tokens: 2_000_000,
|
||||
max_tokens: 30_000,
|
||||
},
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-4-1-fast-non-reasoning',
|
||||
id: 'grok-4-1-fast-non-reasoning',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2025-07',
|
||||
release_date: '2025-11-19',
|
||||
name: 'Grok 4.1 Fast (Non-Reasoning)',
|
||||
aliases: ['x-ai/grok-4-1-fast-non-reasoning'],
|
||||
context: 2_000_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 20,
|
||||
completion_tokens: 50,
|
||||
// Cached tokens billed at 5 cents / 1M tokens = 5 micro-cents / token
|
||||
cached_tokens: 5,
|
||||
},
|
||||
max_tokens: 2_000_000,
|
||||
},
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-code-fast-1',
|
||||
id: 'grok-code-fast-1',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
puterId: 'x-ai:x-ai/grok-build-0.1',
|
||||
id: 'grok-build-0.1',
|
||||
modalities: { input: ['text', 'image', 'pdf'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2023-10',
|
||||
release_date: '2025-08-28',
|
||||
name: 'Grok Code Fast 1',
|
||||
aliases: ['x-ai/grok-code-fast-1'],
|
||||
release_date: '2026-04-16',
|
||||
name: 'Grok Build 0.1',
|
||||
aliases: [
|
||||
'x-ai/grok-build-0.1',
|
||||
'grok-code-fast-1',
|
||||
'grok-code-fast',
|
||||
'grok-code-fast-1-0825',
|
||||
'x-ai/grok-code-fast-1',
|
||||
],
|
||||
context: 256_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 20,
|
||||
completion_tokens: 150,
|
||||
// Cached tokens billed at 2 cents / 1M tokens = 2 micro-cents / token
|
||||
cached_tokens: 2,
|
||||
},
|
||||
max_tokens: 256_000,
|
||||
},
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-4-fast',
|
||||
id: 'grok-4-fast',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2025-07',
|
||||
release_date: '2025-09-19',
|
||||
name: 'Grok 4 Fast (Reasoning)',
|
||||
aliases: ['x-ai/grok-4-fast', 'grok-4-fast-reasoning'],
|
||||
context: 2_000_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 20,
|
||||
completion_tokens: 50,
|
||||
// Cached tokens billed at 5 cents / 1M tokens = 5 micro-cents / token
|
||||
cached_tokens: 5,
|
||||
},
|
||||
max_tokens: 2_000_000,
|
||||
},
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-4-fast-non-reasoning',
|
||||
id: 'grok-4-fast-non-reasoning',
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2025-07',
|
||||
release_date: '2025-09-19',
|
||||
name: 'Grok 4 Fast (Non-Reasoning)',
|
||||
aliases: ['x-ai/grok-4-fast-non-reasoning'],
|
||||
context: 2_000_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 20,
|
||||
completion_tokens: 50,
|
||||
// Cached tokens billed at 5 cents / 1M tokens = 5 micro-cents / token
|
||||
cached_tokens: 5,
|
||||
},
|
||||
max_tokens: 2_000_000,
|
||||
},
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-4-0709',
|
||||
id: 'grok-4-0709',
|
||||
// Not present in models.dev/api.json (as of 2026-02-11); values below follow xAI pricing page.
|
||||
modalities: { input: ['text', 'image'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2025-07',
|
||||
release_date: '2025-07-09',
|
||||
name: 'Grok 4 (0709)',
|
||||
aliases: ['x-ai/grok-4-0709'],
|
||||
context: 256_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 300,
|
||||
completion_tokens: 1500,
|
||||
// Cached tokens billed at 75 cents / 1M tokens = 75 micro-cents / token
|
||||
cached_tokens: 75,
|
||||
},
|
||||
max_tokens: 256_000,
|
||||
},
|
||||
{
|
||||
puterId: 'x-ai:x-ai/grok-4',
|
||||
id: 'grok-4',
|
||||
modalities: { input: ['text'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
knowledge: '2025-07',
|
||||
release_date: '2025-07-09',
|
||||
name: 'Grok 4',
|
||||
aliases: ['x-ai/grok-4'],
|
||||
context: 256_000,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs: {
|
||||
tokens: 1_000_000,
|
||||
prompt_tokens: 300,
|
||||
completion_tokens: 1500,
|
||||
// Cached tokens billed at 75 cents / 1M tokens = 75 micro-cents / token
|
||||
cached_tokens: 75,
|
||||
prompt_tokens: 100,
|
||||
completion_tokens: 200,
|
||||
cached_tokens: 20,
|
||||
},
|
||||
max_tokens: 256_000,
|
||||
},
|
||||
|
||||
@@ -44,31 +44,15 @@ const textModel = (
|
||||
costs,
|
||||
});
|
||||
|
||||
const visionModel = (
|
||||
id: string,
|
||||
name: string,
|
||||
context: number,
|
||||
maxTokens: number,
|
||||
costs: IChatModel['costs'],
|
||||
): IChatModel => ({
|
||||
puterId: `z-ai:z-ai/${id}`,
|
||||
id,
|
||||
name,
|
||||
aliases: [`z-ai/${id}`, `zai/${id}`],
|
||||
modalities: { input: ['text', 'image', 'video', 'file'], output: ['text'] },
|
||||
open_weights: false,
|
||||
tool_call: true,
|
||||
context,
|
||||
max_tokens: maxTokens,
|
||||
costs_currency: 'usd-cents',
|
||||
input_cost_key: 'prompt_tokens',
|
||||
output_cost_key: 'completion_tokens',
|
||||
costs,
|
||||
});
|
||||
|
||||
// Hardcoded from https://docs.z.ai/api-reference/llm/chat-completion and
|
||||
// https://docs.z.ai/guides/overview/pricing.
|
||||
// Hardcoded from live Z.AI /models and https://docs.z.ai/guides/overview/pricing.
|
||||
export const ZAI_MODELS: IChatModel[] = [
|
||||
textModel(
|
||||
'glm-5.3',
|
||||
'GLM-5.3',
|
||||
1_000 * K,
|
||||
128 * K,
|
||||
usdPerMToken(1.4, 4.4, 0.26),
|
||||
),
|
||||
textModel(
|
||||
'glm-5.2',
|
||||
'GLM-5.2',
|
||||
@@ -98,20 +82,6 @@ export const ZAI_MODELS: IChatModel[] = [
|
||||
128 * K,
|
||||
usdPerMToken(0.6, 2.2, 0.11),
|
||||
),
|
||||
textModel(
|
||||
'glm-4.7-flashx',
|
||||
'GLM-4.7-FlashX',
|
||||
200 * K,
|
||||
128 * K,
|
||||
usdPerMToken(0.07, 0.4, 0.01),
|
||||
),
|
||||
textModel(
|
||||
'glm-4.7-flash',
|
||||
'GLM-4.7-Flash',
|
||||
200 * K,
|
||||
128 * K,
|
||||
usdPerMToken(0, 0, 0),
|
||||
),
|
||||
textModel(
|
||||
'glm-4.6',
|
||||
'GLM-4.6',
|
||||
@@ -126,13 +96,6 @@ export const ZAI_MODELS: IChatModel[] = [
|
||||
96 * K,
|
||||
usdPerMToken(0.6, 2.2, 0.11),
|
||||
),
|
||||
textModel(
|
||||
'glm-4.5-x',
|
||||
'GLM-4.5-X',
|
||||
128 * K,
|
||||
96 * K,
|
||||
usdPerMToken(2.2, 8.9, 0.45),
|
||||
),
|
||||
textModel(
|
||||
'glm-4.5-air',
|
||||
'GLM-4.5-Air',
|
||||
@@ -140,67 +103,4 @@ export const ZAI_MODELS: IChatModel[] = [
|
||||
96 * K,
|
||||
usdPerMToken(0.2, 1.1, 0.03),
|
||||
),
|
||||
textModel(
|
||||
'glm-4.5-airx',
|
||||
'GLM-4.5-AirX',
|
||||
128 * K,
|
||||
96 * K,
|
||||
usdPerMToken(1.1, 4.5, 0.22),
|
||||
),
|
||||
textModel(
|
||||
'glm-4.5-flash',
|
||||
'GLM-4.5-Flash',
|
||||
128 * K,
|
||||
96 * K,
|
||||
usdPerMToken(0, 0, 0),
|
||||
),
|
||||
textModel(
|
||||
'glm-4-32b-0414-128k',
|
||||
'GLM-4-32B-0414-128K',
|
||||
128 * K,
|
||||
16 * K,
|
||||
usdPerMToken(0.1, 0.1, 0),
|
||||
),
|
||||
visionModel(
|
||||
'glm-5v-turbo',
|
||||
'GLM-5V-Turbo',
|
||||
200 * K,
|
||||
128 * K,
|
||||
usdPerMToken(1.2, 4, 0.24),
|
||||
),
|
||||
visionModel(
|
||||
'glm-4.6v',
|
||||
'GLM-4.6V',
|
||||
128 * K,
|
||||
32 * K,
|
||||
usdPerMToken(0.3, 0.9, 0.05),
|
||||
),
|
||||
visionModel(
|
||||
'glm-4.6v-flashx',
|
||||
'GLM-4.6V-FlashX',
|
||||
128 * K,
|
||||
32 * K,
|
||||
usdPerMToken(0.04, 0.4, 0.004),
|
||||
),
|
||||
visionModel(
|
||||
'glm-4.6v-flash',
|
||||
'GLM-4.6V-Flash',
|
||||
128 * K,
|
||||
32 * K,
|
||||
usdPerMToken(0, 0, 0),
|
||||
),
|
||||
visionModel(
|
||||
'glm-4.5v',
|
||||
'GLM-4.5V',
|
||||
128 * K,
|
||||
16 * K,
|
||||
usdPerMToken(0.6, 1.8, 0.11),
|
||||
),
|
||||
visionModel(
|
||||
'autoglm-phone-multilingual',
|
||||
'AutoGLM-Phone-Multilingual',
|
||||
4 * K,
|
||||
4 * K,
|
||||
usdPerMToken(0, 0, 0),
|
||||
),
|
||||
];
|
||||
Reference in new issue
Block a user