From 1a6c1a5f6cd97321b609127548aa25811af456c0 Mon Sep 17 00:00:00 2001 From: Kyle Mistele Date: Wed, 23 Sep 2026 10:59:52 -0700 Subject: [PATCH 1/2] feat: add GPT-6 Sol and Luna support HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0cf31-76ac-77af-a656-2e0e74a69323 --- .../fold-agent/src/Catalog/BakedCatalog.ts | 392 ++++++++++-------- .../test/Catalog/BakedCatalog.vi.test.ts | 41 +- .../test/Config/AgentModels.vi.test.ts | 18 + .../fold-codex/test/CodexModel.vi.test.ts | 13 + .../src/Compaction/CompactionEngine.ts | 2 +- .../test/Api/ResumeSession.vi.test.ts | 40 ++ .../fold-core/test/Api/SwitchModel.vi.test.ts | 30 ++ .../Compaction/AutoCompactSession.vi.test.ts | 31 ++ .../Compaction/CompactionEngine.vi.test.ts | 4 + .../test/Model/ModelFamily.vi.test.ts | 2 + 10 files changed, 392 insertions(+), 181 deletions(-) diff --git a/packages/fold-agent/src/Catalog/BakedCatalog.ts b/packages/fold-agent/src/Catalog/BakedCatalog.ts index e08e270..5f0f2cc 100644 --- a/packages/fold-agent/src/Catalog/BakedCatalog.ts +++ b/packages/fold-agent/src/Catalog/BakedCatalog.ts @@ -24,21 +24,21 @@ export const bakedModelCatalog: ReadonlyArray = [ }, { providerId: 'anthropic', - modelId: 'claude-haiku-4-5', - name: 'Claude Haiku 4.5 (latest)', - contextWindow: 200000, + modelId: 'claude-fable-5-1', + name: 'Claude Fable 5.1', + contextWindow: 1000000, maxInputTokens: null, - maxOutputTokens: 64000, + maxOutputTokens: 128000, reasoning: true, - reasoningEfforts: null, + reasoningEfforts: ['low', 'medium', 'high', 'xhigh', 'max'], vision: true, toolCall: true, - pricing: { inputPerMTokens: 1, outputPerMTokens: 5, cacheReadPerMTokens: 0.1, cacheWritePerMTokens: 1.25 }, + pricing: { inputPerMTokens: 10, outputPerMTokens: 50, cacheReadPerMTokens: 0.25, cacheWritePerMTokens: 12.5 }, }, { providerId: 'anthropic', - modelId: 'claude-haiku-4-5-20251001', - name: 'Claude Haiku 4.5', + modelId: 'claude-haiku-4-5', + name: 'Claude Haiku 4.5 (latest)', contextWindow: 200000, maxInputTokens: null, maxOutputTokens: 64000, @@ -50,29 +50,16 @@ export const bakedModelCatalog: ReadonlyArray = [ }, { providerId: 'anthropic', - modelId: 'claude-opus-4-1', - name: 'Claude Opus 4.1 (latest)', - contextWindow: 200000, - maxInputTokens: null, - maxOutputTokens: 32000, - reasoning: true, - reasoningEfforts: null, - vision: true, - toolCall: true, - pricing: { inputPerMTokens: 15, outputPerMTokens: 75, cacheReadPerMTokens: 1.5, cacheWritePerMTokens: 18.75 }, - }, - { - providerId: 'anthropic', - modelId: 'claude-opus-4-1-20250805', - name: 'Claude Opus 4.1', + modelId: 'claude-haiku-4-5-20251001', + name: 'Claude Haiku 4.5', contextWindow: 200000, maxInputTokens: null, - maxOutputTokens: 32000, + maxOutputTokens: 64000, reasoning: true, reasoningEfforts: null, vision: true, toolCall: true, - pricing: { inputPerMTokens: 15, outputPerMTokens: 75, cacheReadPerMTokens: 1.5, cacheWritePerMTokens: 18.75 }, + pricing: { inputPerMTokens: 1, outputPerMTokens: 5, cacheReadPerMTokens: 0.1, cacheWritePerMTokens: 1.25 }, }, { providerId: 'anthropic', @@ -139,6 +126,32 @@ export const bakedModelCatalog: ReadonlyArray = [ toolCall: true, pricing: { inputPerMTokens: 5, outputPerMTokens: 25, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: 6.25 }, }, + { + providerId: 'anthropic', + modelId: 'claude-opus-5', + name: 'Claude Opus 5', + contextWindow: 1000000, + maxInputTokens: null, + maxOutputTokens: 128000, + reasoning: true, + reasoningEfforts: ['low', 'medium', 'high', 'xhigh', 'max'], + vision: true, + toolCall: true, + pricing: { inputPerMTokens: 5, outputPerMTokens: 25, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: 6.25 }, + }, + { + providerId: 'anthropic', + modelId: 'claude-opus-5-5', + name: 'Claude Opus 5.5', + contextWindow: 1000000, + maxInputTokens: null, + maxOutputTokens: 128000, + reasoning: true, + reasoningEfforts: ['low', 'medium', 'high', 'xhigh', 'max'], + vision: true, + toolCall: true, + pricing: { inputPerMTokens: 4, outputPerMTokens: 20, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: 5 }, + }, { providerId: 'anthropic', modelId: 'claude-sonnet-4-5', @@ -375,42 +388,6 @@ export const bakedModelCatalog: ReadonlyArray = [ cacheWritePerMTokens: null, }, }, - { - providerId: 'openai', - modelId: 'gpt-5-chat-latest', - name: 'GPT-5 Chat (latest)', - contextWindow: 400000, - maxInputTokens: 272000, - maxOutputTokens: 128000, - reasoning: true, - reasoningEfforts: null, - vision: true, - toolCall: false, - pricing: { - inputPerMTokens: 1.25, - outputPerMTokens: 10, - cacheReadPerMTokens: 0.125, - cacheWritePerMTokens: null, - }, - }, - { - providerId: 'openai', - modelId: 'gpt-5-codex', - name: 'GPT-5-Codex', - contextWindow: 400000, - maxInputTokens: 272000, - maxOutputTokens: 128000, - reasoning: true, - reasoningEfforts: ['low', 'medium', 'high'], - vision: true, - toolCall: true, - pricing: { - inputPerMTokens: 1.25, - outputPerMTokens: 10, - cacheReadPerMTokens: 0.125, - cacheWritePerMTokens: null, - }, - }, { providerId: 'openai', modelId: 'gpt-5-mini', @@ -473,73 +450,6 @@ export const bakedModelCatalog: ReadonlyArray = [ cacheWritePerMTokens: null, }, }, - { - providerId: 'openai', - modelId: 'gpt-5.1-chat-latest', - name: 'GPT-5.1 Chat', - contextWindow: 128000, - maxInputTokens: null, - maxOutputTokens: 16384, - reasoning: true, - reasoningEfforts: ['medium'], - vision: true, - toolCall: true, - pricing: { - inputPerMTokens: 1.25, - outputPerMTokens: 10, - cacheReadPerMTokens: 0.125, - cacheWritePerMTokens: null, - }, - }, - { - providerId: 'openai', - modelId: 'gpt-5.1-codex', - name: 'GPT-5.1 Codex', - contextWindow: 400000, - maxInputTokens: 272000, - maxOutputTokens: 128000, - reasoning: true, - reasoningEfforts: ['low', 'medium', 'high'], - vision: true, - toolCall: true, - pricing: { - inputPerMTokens: 1.25, - outputPerMTokens: 10, - cacheReadPerMTokens: 0.125, - cacheWritePerMTokens: null, - }, - }, - { - providerId: 'openai', - modelId: 'gpt-5.1-codex-max', - name: 'GPT-5.1 Codex Max', - contextWindow: 400000, - maxInputTokens: 272000, - maxOutputTokens: 128000, - reasoning: true, - reasoningEfforts: ['low', 'medium', 'high', 'xhigh'], - vision: true, - toolCall: true, - pricing: { - inputPerMTokens: 1.25, - outputPerMTokens: 10, - cacheReadPerMTokens: 0.125, - cacheWritePerMTokens: null, - }, - }, - { - providerId: 'openai', - modelId: 'gpt-5.1-codex-mini', - name: 'GPT-5.1 Codex mini', - contextWindow: 400000, - maxInputTokens: 272000, - maxOutputTokens: 128000, - reasoning: true, - reasoningEfforts: ['low', 'medium', 'high'], - vision: true, - toolCall: true, - pricing: { inputPerMTokens: 0.25, outputPerMTokens: 2, cacheReadPerMTokens: 0.025, cacheWritePerMTokens: null }, - }, { providerId: 'openai', modelId: 'gpt-5.2', @@ -576,24 +486,6 @@ export const bakedModelCatalog: ReadonlyArray = [ cacheWritePerMTokens: null, }, }, - { - providerId: 'openai', - modelId: 'gpt-5.2-codex', - name: 'GPT-5.2 Codex', - contextWindow: 400000, - maxInputTokens: 272000, - maxOutputTokens: 128000, - reasoning: true, - reasoningEfforts: ['low', 'medium', 'high', 'xhigh'], - vision: true, - toolCall: true, - pricing: { - inputPerMTokens: 1.75, - outputPerMTokens: 14, - cacheReadPerMTokens: 0.175, - cacheWritePerMTokens: null, - }, - }, { providerId: 'openai', modelId: 'gpt-5.2-pro', @@ -760,7 +652,7 @@ export const bakedModelCatalog: ReadonlyArray = [ reasoningEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'], vision: true, toolCall: true, - pricing: { inputPerMTokens: 5, outputPerMTokens: 30, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: 6.25 }, + pricing: { inputPerMTokens: 4, outputPerMTokens: 20, cacheReadPerMTokens: 0.4, cacheWritePerMTokens: 5 }, }, { providerId: 'openai', @@ -773,7 +665,7 @@ export const bakedModelCatalog: ReadonlyArray = [ reasoningEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'], vision: true, toolCall: true, - pricing: { inputPerMTokens: 1, outputPerMTokens: 6, cacheReadPerMTokens: 0.1, cacheWritePerMTokens: 1.25 }, + pricing: { inputPerMTokens: 0.2, outputPerMTokens: 1.2, cacheReadPerMTokens: 0.02, cacheWritePerMTokens: 0.25 }, }, { providerId: 'openai', @@ -786,7 +678,7 @@ export const bakedModelCatalog: ReadonlyArray = [ reasoningEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'], vision: true, toolCall: true, - pricing: { inputPerMTokens: 5, outputPerMTokens: 30, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: 6.25 }, + pricing: { inputPerMTokens: 4, outputPerMTokens: 20, cacheReadPerMTokens: 0.4, cacheWritePerMTokens: 5 }, }, { providerId: 'openai', @@ -799,7 +691,7 @@ export const bakedModelCatalog: ReadonlyArray = [ reasoningEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'], vision: true, toolCall: true, - pricing: { inputPerMTokens: 2.5, outputPerMTokens: 15, cacheReadPerMTokens: 0.25, cacheWritePerMTokens: 3.125 }, + pricing: { inputPerMTokens: 2, outputPerMTokens: 12, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: 2.5 }, }, { providerId: 'openai', @@ -814,6 +706,37 @@ export const bakedModelCatalog: ReadonlyArray = [ toolCall: true, pricing: { inputPerMTokens: 10, outputPerMTokens: 50, cacheReadPerMTokens: 1, cacheWritePerMTokens: 12.5 }, }, + { + providerId: 'openai', + modelId: 'gpt-6-luna', + name: 'GPT-6 Luna', + contextWindow: 1050000, + maxInputTokens: 922000, + maxOutputTokens: 128000, + reasoning: true, + reasoningEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'], + vision: true, + toolCall: true, + pricing: { + inputPerMTokens: 0.1, + outputPerMTokens: 0.5, + cacheReadPerMTokens: 0.01, + cacheWritePerMTokens: 0.125, + }, + }, + { + providerId: 'openai', + modelId: 'gpt-6-sol', + name: 'GPT-6 Sol', + contextWindow: 1050000, + maxInputTokens: 922000, + maxOutputTokens: 128000, + reasoning: true, + reasoningEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'], + vision: true, + toolCall: true, + pricing: { inputPerMTokens: 2, outputPerMTokens: 10, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: 2.5 }, + }, { providerId: 'openai', modelId: 'gpt-image-1', @@ -866,6 +789,19 @@ export const bakedModelCatalog: ReadonlyArray = [ toolCall: false, pricing: { inputPerMTokens: 5, outputPerMTokens: 30, cacheReadPerMTokens: 1.25, cacheWritePerMTokens: null }, }, + { + providerId: 'openai', + modelId: 'gpt-realtime-2.1', + name: 'GPT-Realtime-2.1', + contextWindow: 128000, + maxInputTokens: 96000, + maxOutputTokens: 32000, + reasoning: true, + reasoningEfforts: ['minimal', 'low', 'medium', 'high', 'xhigh'], + vision: true, + toolCall: true, + pricing: { inputPerMTokens: 4, outputPerMTokens: 24, cacheReadPerMTokens: 0.4, cacheWritePerMTokens: null }, + }, { providerId: 'openai', modelId: 'o1', @@ -905,19 +841,6 @@ export const bakedModelCatalog: ReadonlyArray = [ toolCall: true, pricing: { inputPerMTokens: 2, outputPerMTokens: 8, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: null }, }, - { - providerId: 'openai', - modelId: 'o3-deep-research', - name: 'o3-deep-research', - contextWindow: 200000, - maxInputTokens: null, - maxOutputTokens: 100000, - reasoning: true, - reasoningEfforts: ['medium'], - vision: true, - toolCall: true, - pricing: { inputPerMTokens: 10, outputPerMTokens: 40, cacheReadPerMTokens: 2.5, cacheWritePerMTokens: null }, - }, { providerId: 'openai', modelId: 'o3-mini', @@ -962,19 +885,6 @@ export const bakedModelCatalog: ReadonlyArray = [ cacheWritePerMTokens: null, }, }, - { - providerId: 'openai', - modelId: 'o4-mini-deep-research', - name: 'o4-mini-deep-research', - contextWindow: 200000, - maxInputTokens: null, - maxOutputTokens: 100000, - reasoning: true, - reasoningEfforts: ['medium'], - vision: true, - toolCall: true, - pricing: { inputPerMTokens: 2, outputPerMTokens: 8, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: null }, - }, { providerId: 'openai', modelId: 'text-embedding-3-large', @@ -1014,6 +924,58 @@ export const bakedModelCatalog: ReadonlyArray = [ toolCall: false, pricing: { inputPerMTokens: 0.1, outputPerMTokens: 0, cacheReadPerMTokens: null, cacheWritePerMTokens: null }, }, + { + providerId: 'xai', + modelId: 'grok-4.20-0309-non-reasoning', + name: 'Grok 4.20 (Non-Reasoning)', + contextWindow: 1000000, + maxInputTokens: null, + maxOutputTokens: 30000, + reasoning: false, + reasoningEfforts: null, + vision: true, + toolCall: true, + pricing: { inputPerMTokens: 1.25, outputPerMTokens: 2.5, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: null }, + }, + { + providerId: 'xai', + modelId: 'grok-4.20-0309-reasoning', + name: 'Grok 4.20 (Reasoning)', + contextWindow: 1000000, + maxInputTokens: null, + maxOutputTokens: 30000, + reasoning: true, + reasoningEfforts: null, + vision: true, + toolCall: true, + pricing: { inputPerMTokens: 1.25, outputPerMTokens: 2.5, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: null }, + }, + { + providerId: 'xai', + modelId: 'grok-4.20-multi-agent-0309', + name: 'Grok 4.20 Multi-Agent', + contextWindow: 1000000, + maxInputTokens: null, + maxOutputTokens: 30000, + reasoning: true, + reasoningEfforts: ['low', 'medium', 'high', 'xhigh'], + vision: true, + toolCall: false, + pricing: { inputPerMTokens: 1.25, outputPerMTokens: 2.5, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: null }, + }, + { + providerId: 'xai', + modelId: 'grok-4.3', + name: 'Grok 4.3', + contextWindow: 1000000, + maxInputTokens: null, + maxOutputTokens: 30000, + reasoning: true, + reasoningEfforts: ['none', 'low', 'medium', 'high'], + vision: true, + toolCall: true, + pricing: { inputPerMTokens: 1.25, outputPerMTokens: 2.5, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: null }, + }, { providerId: 'xai', modelId: 'grok-4.5', @@ -1040,4 +1002,82 @@ export const bakedModelCatalog: ReadonlyArray = [ toolCall: true, pricing: { inputPerMTokens: 2, outputPerMTokens: 6, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: null }, }, + { + providerId: 'xai', + modelId: 'grok-4.7', + name: 'Grok 4.7', + contextWindow: 500000, + maxInputTokens: null, + maxOutputTokens: 500000, + reasoning: true, + reasoningEfforts: ['low', 'medium', 'high', 'xhigh'], + vision: true, + toolCall: true, + pricing: { inputPerMTokens: 2, outputPerMTokens: 6, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: null }, + }, + { + providerId: 'xai', + modelId: 'grok-build-0.1', + name: 'Grok Build 0.1', + contextWindow: 256000, + maxInputTokens: null, + maxOutputTokens: 256000, + reasoning: true, + reasoningEfforts: null, + vision: true, + toolCall: true, + pricing: { inputPerMTokens: 1, outputPerMTokens: 2, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: null }, + }, + { + providerId: 'xai', + modelId: 'grok-imagine-image', + name: 'Grok Imagine Image', + contextWindow: 16000, + maxInputTokens: null, + maxOutputTokens: 0, + reasoning: false, + reasoningEfforts: null, + vision: true, + toolCall: false, + pricing: null, + }, + { + providerId: 'xai', + modelId: 'grok-imagine-image-quality', + name: 'Grok Imagine Image Quality', + contextWindow: 16000, + maxInputTokens: null, + maxOutputTokens: 0, + reasoning: false, + reasoningEfforts: null, + vision: true, + toolCall: false, + pricing: null, + }, + { + providerId: 'xai', + modelId: 'grok-imagine-video', + name: 'Grok Imagine Video', + contextWindow: 1024, + maxInputTokens: null, + maxOutputTokens: 0, + reasoning: false, + reasoningEfforts: null, + vision: true, + toolCall: false, + pricing: null, + }, + { + providerId: 'xai', + modelId: 'grok-imagine-video-1.5', + name: 'Grok Imagine Video 1.5', + contextWindow: 1024, + maxInputTokens: null, + maxOutputTokens: 0, + reasoning: false, + reasoningEfforts: null, + vision: true, + toolCall: false, + pricing: null, + }, ] diff --git a/packages/fold-agent/test/Catalog/BakedCatalog.vi.test.ts b/packages/fold-agent/test/Catalog/BakedCatalog.vi.test.ts index 0bc736f..a5fca71 100644 --- a/packages/fold-agent/test/Catalog/BakedCatalog.vi.test.ts +++ b/packages/fold-agent/test/Catalog/BakedCatalog.vi.test.ts @@ -46,6 +46,15 @@ const xaiGrok: ActiveModel = { reasoning: { _tag: 'effort', effort: 'xhigh' }, } +const codexModel = (modelId: string): ActiveModel => ({ + providerId: 'codex', + providerKind: 'codex', + modelId, + role: null, + requestedReasoningLevel: 'max', + reasoning: { _tag: 'effort', effort: 'max', summary: 'auto' }, +}) + it('resolves a codex-kind gpt-5.6-sol to the baked openai entry', () => { const entry = lookupCatalogEntry(bakedModelCatalog, codexSol) @@ -53,8 +62,8 @@ it('resolves a codex-kind gpt-5.6-sol to the baked openai entry', () => { expect(entry?.providerId).toBe('openai') expect(entry?.modelId).toBe('gpt-5.6-sol') expect(entry?.contextWindow).toBe(1050000) - expect(entry?.pricing?.inputPerMTokens).toBe(5) - expect(entry?.pricing?.outputPerMTokens).toBe(30) + expect(entry?.pricing?.inputPerMTokens).toBe(4) + expect(entry?.pricing?.outputPerMTokens).toBe(20) expect(entry?.reasoningEfforts).toContain('max') }) @@ -71,6 +80,30 @@ it('resolves a codex-kind gpt-6-astra to the baked OpenAI entry', () => { expect(entry?.reasoningEfforts).toContain('max') }) +it('ships the GPT-6 Sol and Luna public limits, efforts, pricing, and Codex provider lookup', () => { + const expectations = [ + { modelId: 'gpt-6-sol', inputPrice: 2, outputPrice: 10 }, + { modelId: 'gpt-6-luna', inputPrice: 0.1, outputPrice: 0.5 }, + ] as const + + for (const expected of expectations) { + const entry = lookupCatalogEntry(bakedModelCatalog, codexModel(expected.modelId)) + + expect(entry).not.toBeNull() + expect(entry).toMatchObject({ + providerId: 'openai', + modelId: expected.modelId, + contextWindow: 1_050_000, + maxInputTokens: 922_000, + maxOutputTokens: 128_000, + reasoning: true, + reasoningEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'], + }) + expect(entry?.pricing?.inputPerMTokens).toBe(expected.inputPrice) + expect(entry?.pricing?.outputPerMTokens).toBe(expected.outputPrice) + } +}) + it('resolves an openai-compatible gpt-5.6-terra to the baked openai entry', () => { const entry = lookupCatalogEntry(bakedModelCatalog, openAiTerra) @@ -78,8 +111,8 @@ it('resolves an openai-compatible gpt-5.6-terra to the baked openai entry', () = expect(entry?.providerId).toBe('openai') expect(entry?.modelId).toBe('gpt-5.6-terra') expect(entry?.contextWindow).toBe(1050000) - expect(entry?.pricing?.inputPerMTokens).toBe(2.5) - expect(entry?.pricing?.outputPerMTokens).toBe(15) + expect(entry?.pricing?.inputPerMTokens).toBe(2) + expect(entry?.pricing?.outputPerMTokens).toBe(12) expect(entry?.reasoningEfforts).toContain('max') }) diff --git a/packages/fold-agent/test/Config/AgentModels.vi.test.ts b/packages/fold-agent/test/Config/AgentModels.vi.test.ts index 0bc6d95..eaddd33 100644 --- a/packages/fold-agent/test/Config/AgentModels.vi.test.ts +++ b/packages/fold-agent/test/Config/AgentModels.vi.test.ts @@ -266,6 +266,24 @@ it.effect("an openai-compat binding for gpt-5.6-luna with reasoning 'max' resolv }), ) +it.effect("GPT-6 Sol and Luna bindings with reasoning 'max' resolve against the baked catalog", () => + Effect.gen(function* () { + const config = yield* parseFoldConfig(`{ + "providers": { "codex": { "kind": "codex" } }, + "roles": { + "smart": { "provider": "codex", "model": "gpt-6-sol", "reasoning": "max" }, + "fast": { "provider": "codex", "model": "gpt-6-luna", "reasoning": "max" } + } + }`) + const models = agentModelsFromConfig(config, { env: env({}), catalog: bakedModelCatalog }) + + const smart = yield* models.resolve('smart') + const fast = yield* models.resolve('fast') + expect(smart.activeModel).toMatchObject({ modelId: 'gpt-6-sol', requestedReasoningLevel: 'max' }) + expect(fast.activeModel).toMatchObject({ modelId: 'gpt-6-luna', requestedReasoningLevel: 'max' }) + }), +) + it.effect("gpt-5.5 with reasoning 'max' fails RoleResolutionError naming its supported levels", () => Effect.gen(function* () { const config = yield* parseFoldConfig(gpt56ConfigText('gpt-5.5')) diff --git a/packages/fold-codex/test/CodexModel.vi.test.ts b/packages/fold-codex/test/CodexModel.vi.test.ts index a74036d..dd30bc3 100644 --- a/packages/fold-codex/test/CodexModel.vi.test.ts +++ b/packages/fold-codex/test/CodexModel.vi.test.ts @@ -278,4 +278,17 @@ describe('codexModel defaults', () => { it('an explicit model wins over the default', () => { expect(codexModel({ model: 'gpt-5.5' }).activeModel.modelId).toBe('gpt-5.5') }) + + it('preserves the canonical GPT-6 Sol and Luna ids and max reasoning', () => { + for (const modelId of ['gpt-6-sol', 'gpt-6-luna']) { + const model = codexModel({ model: modelId, reasoning: 'max' }) + + expect(model.activeModel.modelId).toBe(modelId) + expect(model.activeModel).toMatchObject({ + providerKind: 'codex', + requestedReasoningLevel: 'max', + reasoning: { _tag: 'effort', effort: 'max', summary: 'auto' }, + }) + } + }) }) diff --git a/packages/fold-core/src/Compaction/CompactionEngine.ts b/packages/fold-core/src/Compaction/CompactionEngine.ts index f84407d..ba01b57 100644 --- a/packages/fold-core/src/Compaction/CompactionEngine.ts +++ b/packages/fold-core/src/Compaction/CompactionEngine.ts @@ -37,7 +37,7 @@ const filePartEstimateChars = 4_800 */ export const defaultModelContextWindows: ReadonlyArray = [ [/claude|fable|mythos/, 200_000], - [/gpt-6-astra/, 272_000], + [/gpt-6-(?:astra|sol|luna)/, 272_000], [/gpt-5|codex/, 272_000], [/gpt-4\.1/, 1_000_000], ] diff --git a/packages/fold-core/test/Api/ResumeSession.vi.test.ts b/packages/fold-core/test/Api/ResumeSession.vi.test.ts index b2234ea..bb684b5 100644 --- a/packages/fold-core/test/Api/ResumeSession.vi.test.ts +++ b/packages/fold-core/test/Api/ResumeSession.vi.test.ts @@ -19,6 +19,7 @@ import { resumeSession, startSession, ToolCallId, + type ActiveModel, type EventLogService, } from '../../src/index' import { textTurn } from '../TestLayers/ScriptedLanguageModel' @@ -165,6 +166,45 @@ it.effect('resume with a different model binding writes one epoch transition (D1 }).pipe(Effect.scoped, Effect.provide(NodeFileSystem.layer)), ) +it.effect('resume records exactly one durable transition from GPT-6 Sol to Luna', () => + Effect.gen(function* () { + const sharedLog = yield* makeSharedLog + const sol: ActiveModel = { + ...gptActiveModel, + providerId: 'codex', + providerKind: 'codex', + modelId: 'gpt-6-sol', + requestedReasoningLevel: 'max', + reasoning: { _tag: 'effort', effort: 'max', summary: 'auto' }, + } + const luna: ActiveModel = { ...sol, modelId: 'gpt-6-luna' } + + yield* Effect.scoped( + Effect.gen(function* () { + const first = yield* scriptedModel(sol, [textTurn('first answer')]) + const session = yield* startSession({ + agent: defineAgent({ model: first.model, systemPrompt: 'You are the assistant.' }), + log: eventLogSource(Effect.succeed(sharedLog)), + }) + yield* session.send('go') + }), + ) + + const resumed = yield* scriptedModel(luna, [textTurn('second answer')]) + const session = yield* resumeSession({ + agent: defineAgent({ model: resumed.model, systemPrompt: 'You are the assistant.' }), + log: eventLogSource(Effect.succeed(sharedLog)), + }) + const entries = yield* session.entries + const modelChanges = entries.filter((entry) => Predicate.isTagged(entry, 'model-change')) + + expect(modelChanges).toHaveLength(1) + expect(modelChanges[0]).toMatchObject({ model: { modelId: 'gpt-6-luna' } }) + yield* session.send('continue') + expect((yield* resumed.scripted.requests)[0]?.openAiConfig?.model).toBe('gpt-6-luna') + }).pipe(Effect.scoped, Effect.provide(NodeFileSystem.layer)), +) + it.effect('resume with changed leading blocks transitions too (D20 resume rule)', () => Effect.gen(function* () { const sharedLog = yield* makeSharedLog diff --git a/packages/fold-core/test/Api/SwitchModel.vi.test.ts b/packages/fold-core/test/Api/SwitchModel.vi.test.ts index b73fcd4..3e900be 100644 --- a/packages/fold-core/test/Api/SwitchModel.vi.test.ts +++ b/packages/fold-core/test/Api/SwitchModel.vi.test.ts @@ -251,6 +251,36 @@ it.effect('switchModel records thinking-change when the reasoning level changes }).pipe(Effect.scoped, Effect.provide(NodeFileSystem.layer)), ) +it.effect('switchModel preserves exact GPT-6 Sol and Luna ids in the durable transition and requests', () => + Effect.gen(function* () { + const sol: ActiveModel = { + ...gptActiveModel, + providerId: 'codex', + providerKind: 'codex', + modelId: 'gpt-6-sol', + requestedReasoningLevel: 'max', + reasoning: { _tag: 'effort', effort: 'max', summary: 'auto' }, + } + const luna: ActiveModel = { ...sol, modelId: 'gpt-6-luna' } + const first = yield* scriptedModel(sol, [textTurn('from sol')]) + const second = yield* scriptedModel(luna, [textTurn('from luna')]) + const session = yield* startSession({ agent: defineAgent({ model: first.model }) }) + + yield* session.send('first turn') + yield* session.switchModel(second.model, { reason: 'switch canonical model' }) + yield* session.send('second turn') + + const entries = yield* session.entries + const modelChanges = entries.filter((entry): entry is ModelChangeLogEntry => + Predicate.isTagged(entry, 'model-change'), + ) + expect(modelChanges).toHaveLength(1) + expect(modelChanges[0]?.model.modelId).toBe('gpt-6-luna') + expect((yield* first.scripted.requests)[0]?.openAiConfig?.model).toBe('gpt-6-sol') + expect((yield* second.scripted.requests)[0]?.openAiConfig?.model).toBe('gpt-6-luna') + }).pipe(Effect.scoped, Effect.provide(NodeFileSystem.layer)), +) + it.effect('switchModel rejects duplicate tool names in the replacement toolset as a defect', () => Effect.gen(function* () { const first = yield* scriptedModel(gptActiveModel, [textTurn('one')]) diff --git a/packages/fold-core/test/Compaction/AutoCompactSession.vi.test.ts b/packages/fold-core/test/Compaction/AutoCompactSession.vi.test.ts index ac3575c..bdd7c45 100644 --- a/packages/fold-core/test/Compaction/AutoCompactSession.vi.test.ts +++ b/packages/fold-core/test/Compaction/AutoCompactSession.vi.test.ts @@ -605,6 +605,37 @@ it.effect('a Codex model uses the app context window instead of the public API c }).pipe(Effect.scoped, Effect.provide(NodeFileSystem.layer)), ) +it.effect('GPT-6 Sol and Luna compact against the 272k Codex window instead of the public catalog', () => + Effect.gen(function* () { + for (const modelId of ['gpt-6-sol', 'gpt-6-luna']) { + const activeModel = { ...codexActiveModel, modelId } + const { model, scripted } = yield* scriptedModel(activeModel, [ + textTurn(`noted ${'a'.repeat(120)}`, { inputTokens: 224_000 }), + textTurn(`## Goal\n- ${modelId} summary`), + textTurn(`${modelId} answer`), + ]) + + const session = yield* startSession({ + agent: defineAgent({ model, autoCompact: { enabled: true, keepRecentTokens: 10 } }), + catalog: [ + { + ...scriptedCatalogEntry(1_050_000), + providerId: 'openai', + modelId, + }, + ], + }) + + yield* session.send(`${modelId} topic one`) + const finished = yield* session.send(`${modelId} topic two`) + + expect(finished.resultText).toBe(`${modelId} answer`) + expect(compactionEntries(yield* session.entries)).toHaveLength(1) + expect(yield* scripted.remainingTurns).toBe(0) + } + }).pipe(Effect.scoped, Effect.provide(NodeFileSystem.layer)), +) + it.effect('an explicit autoCompact.contextWindow beats the catalog entry', () => Effect.gen(function* () { const { model, scripted } = yield* scriptedModel(gptActiveModel, [ diff --git a/packages/fold-core/test/Compaction/CompactionEngine.vi.test.ts b/packages/fold-core/test/Compaction/CompactionEngine.vi.test.ts index adc9ae9..7d95e32 100644 --- a/packages/fold-core/test/Compaction/CompactionEngine.vi.test.ts +++ b/packages/fold-core/test/Compaction/CompactionEngine.vi.test.ts @@ -148,6 +148,8 @@ it('defaultContextWindowFor uses the interim table with a conservative fallback' expect(defaultContextWindowFor('gpt-5.5')).toBe(272_000) expect(defaultContextWindowFor('gpt-5.3-codex')).toBe(272_000) expect(defaultContextWindowFor('gpt-6-astra')).toBe(272_000) + expect(defaultContextWindowFor('gpt-6-sol')).toBe(272_000) + expect(defaultContextWindowFor('gpt-6-luna')).toBe(272_000) expect(defaultContextWindowFor('some-unknown-model')).toBe(128_000) expect(defaultContextWindowFor(null)).toBe(128_000) }) @@ -157,6 +159,8 @@ it('compactionUsableTokens applies the D11 formula, clamped for tiny windows', ( expect(compactionUsableTokens({ contextWindow: 200_000, reserveTokens: 16_384 })).toBe(151_616) // Tiny windows clamp the output budget to window/4 and the reserve to window/8, staying positive. expect(compactionUsableTokens({ contextWindow: 2_000, reserveTokens: 16_384 })).toBe(1_250) + // Fold's raw 272k Codex window compacts at 223,616 for Sol and Luna. + expect(compactionUsableTokens({ contextWindow: 272_000, reserveTokens: 16_384 })).toBe(223_616) }) // ── Stale-usage / progress guard ───────────────────────────────────────────── diff --git a/packages/fold-core/test/Model/ModelFamily.vi.test.ts b/packages/fold-core/test/Model/ModelFamily.vi.test.ts index 1be2a5f..0e11de3 100644 --- a/packages/fold-core/test/Model/ModelFamily.vi.test.ts +++ b/packages/fold-core/test/Model/ModelFamily.vi.test.ts @@ -38,6 +38,8 @@ it('classifies openai-compatible models by model id patterns', () => { expect(modelFamilyFor(openAiCompatible('gpt-5.5'))).toBe('gpt') expect(modelFamilyFor(openAiCompatible('o3-mini'))).toBe('gpt') expect(modelFamilyFor(openAiCompatible('gpt-5.1-codex-max'))).toBe('codex') + expect(modelFamilyFor(openAiCompatible('gpt-6-sol'))).toBe('gpt') + expect(modelFamilyFor(openAiCompatible('gpt-6-luna'))).toBe('gpt') expect(modelFamilyFor(openAiCompatible('anthropic/claude-opus-4-8'))).toBe('claude') expect(modelFamilyFor(openAiCompatible('llama-3.3-70b'))).toBe('unknown') }) From 4172ef19eab511adfbf1ee89d90d0ebc1a31869d Mon Sep 17 00:00:00 2001 From: Kyle Mistele Date: Wed, 23 Sep 2026 11:12:30 -0700 Subject: [PATCH 2/2] fix: limit catalog update to GPT-6 models HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0cf31-76ac-77af-a656-2e0e74a69323 --- .../fold-agent/src/Catalog/BakedCatalog.ts | 361 +++++++++--------- .../test/Catalog/BakedCatalog.vi.test.ts | 8 +- 2 files changed, 180 insertions(+), 189 deletions(-) diff --git a/packages/fold-agent/src/Catalog/BakedCatalog.ts b/packages/fold-agent/src/Catalog/BakedCatalog.ts index 5f0f2cc..35f9c49 100644 --- a/packages/fold-agent/src/Catalog/BakedCatalog.ts +++ b/packages/fold-agent/src/Catalog/BakedCatalog.ts @@ -24,21 +24,21 @@ export const bakedModelCatalog: ReadonlyArray = [ }, { providerId: 'anthropic', - modelId: 'claude-fable-5-1', - name: 'Claude Fable 5.1', - contextWindow: 1000000, + modelId: 'claude-haiku-4-5', + name: 'Claude Haiku 4.5 (latest)', + contextWindow: 200000, maxInputTokens: null, - maxOutputTokens: 128000, + maxOutputTokens: 64000, reasoning: true, - reasoningEfforts: ['low', 'medium', 'high', 'xhigh', 'max'], + reasoningEfforts: null, vision: true, toolCall: true, - pricing: { inputPerMTokens: 10, outputPerMTokens: 50, cacheReadPerMTokens: 0.25, cacheWritePerMTokens: 12.5 }, + pricing: { inputPerMTokens: 1, outputPerMTokens: 5, cacheReadPerMTokens: 0.1, cacheWritePerMTokens: 1.25 }, }, { providerId: 'anthropic', - modelId: 'claude-haiku-4-5', - name: 'Claude Haiku 4.5 (latest)', + modelId: 'claude-haiku-4-5-20251001', + name: 'Claude Haiku 4.5', contextWindow: 200000, maxInputTokens: null, maxOutputTokens: 64000, @@ -50,16 +50,29 @@ export const bakedModelCatalog: ReadonlyArray = [ }, { providerId: 'anthropic', - modelId: 'claude-haiku-4-5-20251001', - name: 'Claude Haiku 4.5', + modelId: 'claude-opus-4-1', + name: 'Claude Opus 4.1 (latest)', contextWindow: 200000, maxInputTokens: null, - maxOutputTokens: 64000, + maxOutputTokens: 32000, reasoning: true, reasoningEfforts: null, vision: true, toolCall: true, - pricing: { inputPerMTokens: 1, outputPerMTokens: 5, cacheReadPerMTokens: 0.1, cacheWritePerMTokens: 1.25 }, + pricing: { inputPerMTokens: 15, outputPerMTokens: 75, cacheReadPerMTokens: 1.5, cacheWritePerMTokens: 18.75 }, + }, + { + providerId: 'anthropic', + modelId: 'claude-opus-4-1-20250805', + name: 'Claude Opus 4.1', + contextWindow: 200000, + maxInputTokens: null, + maxOutputTokens: 32000, + reasoning: true, + reasoningEfforts: null, + vision: true, + toolCall: true, + pricing: { inputPerMTokens: 15, outputPerMTokens: 75, cacheReadPerMTokens: 1.5, cacheWritePerMTokens: 18.75 }, }, { providerId: 'anthropic', @@ -126,32 +139,6 @@ export const bakedModelCatalog: ReadonlyArray = [ toolCall: true, pricing: { inputPerMTokens: 5, outputPerMTokens: 25, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: 6.25 }, }, - { - providerId: 'anthropic', - modelId: 'claude-opus-5', - name: 'Claude Opus 5', - contextWindow: 1000000, - maxInputTokens: null, - maxOutputTokens: 128000, - reasoning: true, - reasoningEfforts: ['low', 'medium', 'high', 'xhigh', 'max'], - vision: true, - toolCall: true, - pricing: { inputPerMTokens: 5, outputPerMTokens: 25, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: 6.25 }, - }, - { - providerId: 'anthropic', - modelId: 'claude-opus-5-5', - name: 'Claude Opus 5.5', - contextWindow: 1000000, - maxInputTokens: null, - maxOutputTokens: 128000, - reasoning: true, - reasoningEfforts: ['low', 'medium', 'high', 'xhigh', 'max'], - vision: true, - toolCall: true, - pricing: { inputPerMTokens: 4, outputPerMTokens: 20, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: 5 }, - }, { providerId: 'anthropic', modelId: 'claude-sonnet-4-5', @@ -388,6 +375,42 @@ export const bakedModelCatalog: ReadonlyArray = [ cacheWritePerMTokens: null, }, }, + { + providerId: 'openai', + modelId: 'gpt-5-chat-latest', + name: 'GPT-5 Chat (latest)', + contextWindow: 400000, + maxInputTokens: 272000, + maxOutputTokens: 128000, + reasoning: true, + reasoningEfforts: null, + vision: true, + toolCall: false, + pricing: { + inputPerMTokens: 1.25, + outputPerMTokens: 10, + cacheReadPerMTokens: 0.125, + cacheWritePerMTokens: null, + }, + }, + { + providerId: 'openai', + modelId: 'gpt-5-codex', + name: 'GPT-5-Codex', + contextWindow: 400000, + maxInputTokens: 272000, + maxOutputTokens: 128000, + reasoning: true, + reasoningEfforts: ['low', 'medium', 'high'], + vision: true, + toolCall: true, + pricing: { + inputPerMTokens: 1.25, + outputPerMTokens: 10, + cacheReadPerMTokens: 0.125, + cacheWritePerMTokens: null, + }, + }, { providerId: 'openai', modelId: 'gpt-5-mini', @@ -450,6 +473,73 @@ export const bakedModelCatalog: ReadonlyArray = [ cacheWritePerMTokens: null, }, }, + { + providerId: 'openai', + modelId: 'gpt-5.1-chat-latest', + name: 'GPT-5.1 Chat', + contextWindow: 128000, + maxInputTokens: null, + maxOutputTokens: 16384, + reasoning: true, + reasoningEfforts: ['medium'], + vision: true, + toolCall: true, + pricing: { + inputPerMTokens: 1.25, + outputPerMTokens: 10, + cacheReadPerMTokens: 0.125, + cacheWritePerMTokens: null, + }, + }, + { + providerId: 'openai', + modelId: 'gpt-5.1-codex', + name: 'GPT-5.1 Codex', + contextWindow: 400000, + maxInputTokens: 272000, + maxOutputTokens: 128000, + reasoning: true, + reasoningEfforts: ['low', 'medium', 'high'], + vision: true, + toolCall: true, + pricing: { + inputPerMTokens: 1.25, + outputPerMTokens: 10, + cacheReadPerMTokens: 0.125, + cacheWritePerMTokens: null, + }, + }, + { + providerId: 'openai', + modelId: 'gpt-5.1-codex-max', + name: 'GPT-5.1 Codex Max', + contextWindow: 400000, + maxInputTokens: 272000, + maxOutputTokens: 128000, + reasoning: true, + reasoningEfforts: ['low', 'medium', 'high', 'xhigh'], + vision: true, + toolCall: true, + pricing: { + inputPerMTokens: 1.25, + outputPerMTokens: 10, + cacheReadPerMTokens: 0.125, + cacheWritePerMTokens: null, + }, + }, + { + providerId: 'openai', + modelId: 'gpt-5.1-codex-mini', + name: 'GPT-5.1 Codex mini', + contextWindow: 400000, + maxInputTokens: 272000, + maxOutputTokens: 128000, + reasoning: true, + reasoningEfforts: ['low', 'medium', 'high'], + vision: true, + toolCall: true, + pricing: { inputPerMTokens: 0.25, outputPerMTokens: 2, cacheReadPerMTokens: 0.025, cacheWritePerMTokens: null }, + }, { providerId: 'openai', modelId: 'gpt-5.2', @@ -486,6 +576,24 @@ export const bakedModelCatalog: ReadonlyArray = [ cacheWritePerMTokens: null, }, }, + { + providerId: 'openai', + modelId: 'gpt-5.2-codex', + name: 'GPT-5.2 Codex', + contextWindow: 400000, + maxInputTokens: 272000, + maxOutputTokens: 128000, + reasoning: true, + reasoningEfforts: ['low', 'medium', 'high', 'xhigh'], + vision: true, + toolCall: true, + pricing: { + inputPerMTokens: 1.75, + outputPerMTokens: 14, + cacheReadPerMTokens: 0.175, + cacheWritePerMTokens: null, + }, + }, { providerId: 'openai', modelId: 'gpt-5.2-pro', @@ -652,7 +760,7 @@ export const bakedModelCatalog: ReadonlyArray = [ reasoningEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'], vision: true, toolCall: true, - pricing: { inputPerMTokens: 4, outputPerMTokens: 20, cacheReadPerMTokens: 0.4, cacheWritePerMTokens: 5 }, + pricing: { inputPerMTokens: 5, outputPerMTokens: 30, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: 6.25 }, }, { providerId: 'openai', @@ -665,7 +773,7 @@ export const bakedModelCatalog: ReadonlyArray = [ reasoningEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'], vision: true, toolCall: true, - pricing: { inputPerMTokens: 0.2, outputPerMTokens: 1.2, cacheReadPerMTokens: 0.02, cacheWritePerMTokens: 0.25 }, + pricing: { inputPerMTokens: 1, outputPerMTokens: 6, cacheReadPerMTokens: 0.1, cacheWritePerMTokens: 1.25 }, }, { providerId: 'openai', @@ -678,7 +786,7 @@ export const bakedModelCatalog: ReadonlyArray = [ reasoningEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'], vision: true, toolCall: true, - pricing: { inputPerMTokens: 4, outputPerMTokens: 20, cacheReadPerMTokens: 0.4, cacheWritePerMTokens: 5 }, + pricing: { inputPerMTokens: 5, outputPerMTokens: 30, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: 6.25 }, }, { providerId: 'openai', @@ -691,7 +799,7 @@ export const bakedModelCatalog: ReadonlyArray = [ reasoningEfforts: ['none', 'low', 'medium', 'high', 'xhigh', 'max'], vision: true, toolCall: true, - pricing: { inputPerMTokens: 2, outputPerMTokens: 12, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: 2.5 }, + pricing: { inputPerMTokens: 2.5, outputPerMTokens: 15, cacheReadPerMTokens: 0.25, cacheWritePerMTokens: 3.125 }, }, { providerId: 'openai', @@ -789,19 +897,6 @@ export const bakedModelCatalog: ReadonlyArray = [ toolCall: false, pricing: { inputPerMTokens: 5, outputPerMTokens: 30, cacheReadPerMTokens: 1.25, cacheWritePerMTokens: null }, }, - { - providerId: 'openai', - modelId: 'gpt-realtime-2.1', - name: 'GPT-Realtime-2.1', - contextWindow: 128000, - maxInputTokens: 96000, - maxOutputTokens: 32000, - reasoning: true, - reasoningEfforts: ['minimal', 'low', 'medium', 'high', 'xhigh'], - vision: true, - toolCall: true, - pricing: { inputPerMTokens: 4, outputPerMTokens: 24, cacheReadPerMTokens: 0.4, cacheWritePerMTokens: null }, - }, { providerId: 'openai', modelId: 'o1', @@ -841,6 +936,19 @@ export const bakedModelCatalog: ReadonlyArray = [ toolCall: true, pricing: { inputPerMTokens: 2, outputPerMTokens: 8, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: null }, }, + { + providerId: 'openai', + modelId: 'o3-deep-research', + name: 'o3-deep-research', + contextWindow: 200000, + maxInputTokens: null, + maxOutputTokens: 100000, + reasoning: true, + reasoningEfforts: ['medium'], + vision: true, + toolCall: true, + pricing: { inputPerMTokens: 10, outputPerMTokens: 40, cacheReadPerMTokens: 2.5, cacheWritePerMTokens: null }, + }, { providerId: 'openai', modelId: 'o3-mini', @@ -885,6 +993,19 @@ export const bakedModelCatalog: ReadonlyArray = [ cacheWritePerMTokens: null, }, }, + { + providerId: 'openai', + modelId: 'o4-mini-deep-research', + name: 'o4-mini-deep-research', + contextWindow: 200000, + maxInputTokens: null, + maxOutputTokens: 100000, + reasoning: true, + reasoningEfforts: ['medium'], + vision: true, + toolCall: true, + pricing: { inputPerMTokens: 2, outputPerMTokens: 8, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: null }, + }, { providerId: 'openai', modelId: 'text-embedding-3-large', @@ -924,58 +1045,6 @@ export const bakedModelCatalog: ReadonlyArray = [ toolCall: false, pricing: { inputPerMTokens: 0.1, outputPerMTokens: 0, cacheReadPerMTokens: null, cacheWritePerMTokens: null }, }, - { - providerId: 'xai', - modelId: 'grok-4.20-0309-non-reasoning', - name: 'Grok 4.20 (Non-Reasoning)', - contextWindow: 1000000, - maxInputTokens: null, - maxOutputTokens: 30000, - reasoning: false, - reasoningEfforts: null, - vision: true, - toolCall: true, - pricing: { inputPerMTokens: 1.25, outputPerMTokens: 2.5, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: null }, - }, - { - providerId: 'xai', - modelId: 'grok-4.20-0309-reasoning', - name: 'Grok 4.20 (Reasoning)', - contextWindow: 1000000, - maxInputTokens: null, - maxOutputTokens: 30000, - reasoning: true, - reasoningEfforts: null, - vision: true, - toolCall: true, - pricing: { inputPerMTokens: 1.25, outputPerMTokens: 2.5, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: null }, - }, - { - providerId: 'xai', - modelId: 'grok-4.20-multi-agent-0309', - name: 'Grok 4.20 Multi-Agent', - contextWindow: 1000000, - maxInputTokens: null, - maxOutputTokens: 30000, - reasoning: true, - reasoningEfforts: ['low', 'medium', 'high', 'xhigh'], - vision: true, - toolCall: false, - pricing: { inputPerMTokens: 1.25, outputPerMTokens: 2.5, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: null }, - }, - { - providerId: 'xai', - modelId: 'grok-4.3', - name: 'Grok 4.3', - contextWindow: 1000000, - maxInputTokens: null, - maxOutputTokens: 30000, - reasoning: true, - reasoningEfforts: ['none', 'low', 'medium', 'high'], - vision: true, - toolCall: true, - pricing: { inputPerMTokens: 1.25, outputPerMTokens: 2.5, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: null }, - }, { providerId: 'xai', modelId: 'grok-4.5', @@ -1002,82 +1071,4 @@ export const bakedModelCatalog: ReadonlyArray = [ toolCall: true, pricing: { inputPerMTokens: 2, outputPerMTokens: 6, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: null }, }, - { - providerId: 'xai', - modelId: 'grok-4.7', - name: 'Grok 4.7', - contextWindow: 500000, - maxInputTokens: null, - maxOutputTokens: 500000, - reasoning: true, - reasoningEfforts: ['low', 'medium', 'high', 'xhigh'], - vision: true, - toolCall: true, - pricing: { inputPerMTokens: 2, outputPerMTokens: 6, cacheReadPerMTokens: 0.5, cacheWritePerMTokens: null }, - }, - { - providerId: 'xai', - modelId: 'grok-build-0.1', - name: 'Grok Build 0.1', - contextWindow: 256000, - maxInputTokens: null, - maxOutputTokens: 256000, - reasoning: true, - reasoningEfforts: null, - vision: true, - toolCall: true, - pricing: { inputPerMTokens: 1, outputPerMTokens: 2, cacheReadPerMTokens: 0.2, cacheWritePerMTokens: null }, - }, - { - providerId: 'xai', - modelId: 'grok-imagine-image', - name: 'Grok Imagine Image', - contextWindow: 16000, - maxInputTokens: null, - maxOutputTokens: 0, - reasoning: false, - reasoningEfforts: null, - vision: true, - toolCall: false, - pricing: null, - }, - { - providerId: 'xai', - modelId: 'grok-imagine-image-quality', - name: 'Grok Imagine Image Quality', - contextWindow: 16000, - maxInputTokens: null, - maxOutputTokens: 0, - reasoning: false, - reasoningEfforts: null, - vision: true, - toolCall: false, - pricing: null, - }, - { - providerId: 'xai', - modelId: 'grok-imagine-video', - name: 'Grok Imagine Video', - contextWindow: 1024, - maxInputTokens: null, - maxOutputTokens: 0, - reasoning: false, - reasoningEfforts: null, - vision: true, - toolCall: false, - pricing: null, - }, - { - providerId: 'xai', - modelId: 'grok-imagine-video-1.5', - name: 'Grok Imagine Video 1.5', - contextWindow: 1024, - maxInputTokens: null, - maxOutputTokens: 0, - reasoning: false, - reasoningEfforts: null, - vision: true, - toolCall: false, - pricing: null, - }, ] diff --git a/packages/fold-agent/test/Catalog/BakedCatalog.vi.test.ts b/packages/fold-agent/test/Catalog/BakedCatalog.vi.test.ts index a5fca71..4435257 100644 --- a/packages/fold-agent/test/Catalog/BakedCatalog.vi.test.ts +++ b/packages/fold-agent/test/Catalog/BakedCatalog.vi.test.ts @@ -62,8 +62,8 @@ it('resolves a codex-kind gpt-5.6-sol to the baked openai entry', () => { expect(entry?.providerId).toBe('openai') expect(entry?.modelId).toBe('gpt-5.6-sol') expect(entry?.contextWindow).toBe(1050000) - expect(entry?.pricing?.inputPerMTokens).toBe(4) - expect(entry?.pricing?.outputPerMTokens).toBe(20) + expect(entry?.pricing?.inputPerMTokens).toBe(5) + expect(entry?.pricing?.outputPerMTokens).toBe(30) expect(entry?.reasoningEfforts).toContain('max') }) @@ -111,8 +111,8 @@ it('resolves an openai-compatible gpt-5.6-terra to the baked openai entry', () = expect(entry?.providerId).toBe('openai') expect(entry?.modelId).toBe('gpt-5.6-terra') expect(entry?.contextWindow).toBe(1050000) - expect(entry?.pricing?.inputPerMTokens).toBe(2) - expect(entry?.pricing?.outputPerMTokens).toBe(12) + expect(entry?.pricing?.inputPerMTokens).toBe(2.5) + expect(entry?.pricing?.outputPerMTokens).toBe(15) expect(entry?.reasoningEfforts).toContain('max') })