diff --git a/src/components/landing/InteractiveHeroAiPanel.tsx b/src/components/landing/InteractiveHeroAiPanel.tsx index 3f288ed6..eb542938 100644 --- a/src/components/landing/InteractiveHeroAiPanel.tsx +++ b/src/components/landing/InteractiveHeroAiPanel.tsx @@ -10,7 +10,7 @@ import type { WorkspaceItem } from "#/features/workspaces/contracts"; import { getWorkspaceItemDisplay } from "#/features/workspaces/model/item-display"; import { cn } from "#/lib/utils"; -const MODELS = ["Auto", "GPT-5", "Claude Sonnet", "Gemini Pro"] as const; +const MODELS = ["Auto", "GPT-6.1 Sol", "Claude Sonnet", "Gemini Pro"] as const; /** Lightweight AI chat simulation for the public workspace preview. */ export function InteractiveHeroAiPanel({ diff --git a/src/components/landing/visuals/ModelsVisual.tsx b/src/components/landing/visuals/ModelsVisual.tsx index 31ac42fa..6db4e738 100644 --- a/src/components/landing/visuals/ModelsVisual.tsx +++ b/src/components/landing/visuals/ModelsVisual.tsx @@ -20,7 +20,7 @@ const MODEL_GROUPS = WORKSPACE_AI_CHAT_PROVIDERS.map((provider) => ({ })).filter((group) => group.models.length > 0); export function ModelsVisual() { - const [selectedModelId, setSelectedModelId] = useState("gpt-terra"); + const [selectedModelId, setSelectedModelId] = useState("gpt-sol"); // Derived from the registry rather than restated, so a new provider or model // shows up here without an edit. Hoisted out of render: it is constant. const detailModel = getWorkspaceAiChatModelById(selectedModelId); diff --git a/src/features/workspaces/ai/ai-gateway-routing.ts b/src/features/workspaces/ai/ai-gateway-routing.ts index a7b72bd9..05fdd0d1 100644 --- a/src/features/workspaces/ai/ai-gateway-routing.ts +++ b/src/features/workspaces/ai/ai-gateway-routing.ts @@ -8,10 +8,10 @@ type GatewayRoutingOptions = { const GOOGLE_GATEWAY_PROVIDER_ORDER = ["google", "vertex"]; // The native Anthropic route is the only one we want. Vertex has no Anthropic -// quota in our GCP project (429 in ~200ms) and Bedrock has no Sonnet 5 access -// (403), so both only ever landed on Vercel's own credits. Cross-model fallback -// below covers a genuine Anthropic outage; add a provider back here if its -// account-side access is ever granted. +// quota in our GCP project (429 in ~200ms) and Bedrock has no current Sonnet +// access (403), so both only ever landed on Vercel's own credits. Cross-model +// fallback below covers a genuine Anthropic outage; add a provider back here if +// its account-side access is ever granted. const CLAUDE_GATEWAY_PROVIDER_ORDER = ["anthropic"]; // `only` is the gateway's sole exclusion primitive, and it is a hard filter over // the whole request — the fallback models below are unreachable unless their @@ -29,33 +29,33 @@ const CLAUDE_GATEWAY_PROVIDER_ALLOWLIST = ["anthropic", "openai", "google"]; const workspaceAiGatewayRouting: Record = { auto: { order: ["openai", "azure"], - models: ["google/gemini-3-flash", "anthropic/claude-haiku-4.5"], + models: ["google/gemini-3.8-flash", "anthropic/claude-haiku-4.5"], }, "claude-sonnet": { only: CLAUDE_GATEWAY_PROVIDER_ALLOWLIST, order: CLAUDE_GATEWAY_PROVIDER_ORDER, - models: ["openai/gpt-5.6-terra", "google/gemini-3.1-pro-preview"], + models: ["openai/gpt-6.1-sol", "google/gemini-3.1-pro-preview"], }, "claude-haiku": { only: CLAUDE_GATEWAY_PROVIDER_ALLOWLIST, order: CLAUDE_GATEWAY_PROVIDER_ORDER, - models: ["openai/gpt-5.6-luna", "google/gemini-3-flash"], + models: ["openai/gpt-6-luna", "google/gemini-3.8-flash"], }, - "gpt-terra": { + "gpt-sol": { order: ["openai", "azure"], - models: ["anthropic/claude-sonnet-5", "google/gemini-3.1-pro-preview"], + models: ["anthropic/claude-sonnet-5.5", "google/gemini-3.1-pro-preview"], }, "gpt-luna": { order: ["openai", "azure"], - models: ["google/gemini-3-flash", "anthropic/claude-haiku-4.5"], + models: ["google/gemini-3.8-flash", "anthropic/claude-haiku-4.5"], }, "gemini-pro": { order: GOOGLE_GATEWAY_PROVIDER_ORDER, - models: ["openai/gpt-5.6-terra", "anthropic/claude-sonnet-5"], + models: ["openai/gpt-6.1-sol", "anthropic/claude-sonnet-5.5"], }, gemini: { order: GOOGLE_GATEWAY_PROVIDER_ORDER, - models: ["openai/gpt-5.6-luna", "anthropic/claude-haiku-4.5"], + models: ["openai/gpt-6-luna", "anthropic/claude-haiku-4.5"], }, }; @@ -66,10 +66,8 @@ export function getWorkspaceAiGatewayRoutingOptions(modelId: WorkspaceAiChatMode export function getAIThreadTitleGatewayRoutingOptions() { return { order: GOOGLE_GATEWAY_PROVIDER_ORDER, - // Cross-provider backstop for the Google primary. gpt-4.1-nano was retired - // from ChatGPT and has an Azure end-of-life with no named successor, so - // track a current nano instead. - models: ["openai/gpt-5.4-nano"], + // Lightweight cross-provider backstop for title generation. + models: ["openai/gpt-6-luna"], }; } @@ -78,6 +76,6 @@ export function getWorkspaceImageExtractionGatewayRoutingOptions() { order: GOOGLE_GATEWAY_PROVIDER_ORDER, // Cross-provider backstop so a Google outage still gets an image read. // Both fallbacks accept image input; a text-only model would 400 the leg. - models: ["openai/gpt-5.6-luna", "anthropic/claude-haiku-4.5"], + models: ["openai/gpt-6-luna", "anthropic/claude-haiku-4.5"], }; } diff --git a/src/features/workspaces/ai/chat/chat-telemetry.ts b/src/features/workspaces/ai/chat/chat-telemetry.ts index 31834b0e..4cd66c9a 100644 --- a/src/features/workspaces/ai/chat/chat-telemetry.ts +++ b/src/features/workspaces/ai/chat/chat-telemetry.ts @@ -27,7 +27,7 @@ export interface AiChatGenerationTelemetry { threadId: string; /** The turn's stream id — one trace groups the turn and its utility calls. */ traceId: string; - /** The gateway model string, e.g. "anthropic/claude-sonnet-5". */ + /** The gateway model string, e.g. "anthropic/claude-sonnet-5.5". */ gatewayModel: string; /** The app-level model id the user picked, for the requested_model property. */ requestedModel?: string; diff --git a/src/features/workspaces/ai/gateway.ts b/src/features/workspaces/ai/gateway.ts index e1f0b739..b13c55b8 100644 --- a/src/features/workspaces/ai/gateway.ts +++ b/src/features/workspaces/ai/gateway.ts @@ -17,7 +17,7 @@ import { // has no framework dependencies; the comments carry over because the tuning // rationale is unchanged. -export const AI_THREAD_TITLE_GATEWAY_MODEL = "google/gemini-2.5-flash-lite"; +export const AI_THREAD_TITLE_GATEWAY_MODEL = "google/gemini-3.5-flash-lite"; type WorkspaceAiProviderOptions = NonNullable< Parameters[0]["providerOptions"] @@ -52,7 +52,7 @@ export function getWorkspaceAiGatewayTransportOptions() { // Buy the fast lane where it exists. The gateway only forwards a tier to // OpenAI, Google AI Studio, and Vertex, so this is a no-op on the Claude // primaries and moves the models we actually default to (`auto`/luna, the - // Gemini pair, the nano/flash-lite title legs). It is a hint, never a + // Gemini pair, the luna/flash-lite title legs). It is a hint, never a // promise: an unsupported model ignores it, and a provider that is out of // priority capacity silently downgrades to standard and bills standard. serviceTier: "priority" as const, @@ -109,9 +109,9 @@ export function getAIThreadTitleGatewayProviderOptions(): WorkspaceAiProviderOpt `model:${AI_THREAD_TITLE_GATEWAY_MODEL}`, ], }, - // The 2.5-series title model rejects `thinkingLevel`; budget is its knob. - google: { thinkingConfig: { thinkingBudget: 0 } }, - vertex: { thinkingConfig: { thinkingBudget: 0 } }, + // Keep title generation at the lowest supported thinking level. + google: { thinkingConfig: { thinkingLevel: "minimal" } }, + vertex: { thinkingConfig: { thinkingLevel: "minimal" } }, openai: { reasoningEffort: "none" }, }; } @@ -129,10 +129,11 @@ function getWorkspaceAiReasoningOptions( thinkingConfig: { thinkingLevel: "low" }, }, }; - case "gpt-terra": + case "gpt-sol": return { openai: { - reasoningEffort: "none", + // Sol 6.1 requires reasoning; low is its minimum supported effort. + reasoningEffort: "low", }, }; default: diff --git a/src/features/workspaces/ai/models.ts b/src/features/workspaces/ai/models.ts index 6c15050d..49c4f06f 100644 --- a/src/features/workspaces/ai/models.ts +++ b/src/features/workspaces/ai/models.ts @@ -25,7 +25,8 @@ export type WorkspaceAiChatModelBillingTier = "standard" | "premium"; // across input, cached input, and output rather than output alone — output // price by itself understates the models we send the most tokens to. // -// Measured 1.0x / 2.5x / 4.7x / 9.5x / 10x, rounded to a clean ladder so these +// Standard-rate estimates: Luna 1x, Flash 7.5x, Haiku 10x, Sol 18.9x, +// Sonnet 20x, and Pro 21.2x, rounded to whole multipliers so these // double as credit weights if usage is ever metered. Re-derive from the gateway // catalog when the lineup changes; a stale multiplier misprices the plan. // @@ -38,7 +39,7 @@ export const WORKSPACE_AI_CHAT_MODELS = [ name: "Auto", // Keep this a stable product choice while the server owns its availability // policy and fallback chain. - gatewayModel: "openai/gpt-5.6-luna", + gatewayModel: "openai/gpt-6-luna", provider: "auto", tagline: "Fast and capable by default", description: @@ -48,12 +49,12 @@ export const WORKSPACE_AI_CHAT_MODELS = [ speed: 3, cost: 1, billingTier: "standard", - contextWindow: 1_000_000, + contextWindow: 1_050_000, }, { id: "claude-sonnet", - name: "Claude Sonnet 5", - gatewayModel: "anthropic/claude-sonnet-5", + name: "Claude Sonnet 5.5", + gatewayModel: "anthropic/claude-sonnet-5.5", provider: "anthropic", tagline: "Thoughtful and polished", description: @@ -61,7 +62,7 @@ export const WORKSPACE_AI_CHAT_MODELS = [ bestFor: "Writing, analysis & coding", intelligence: 4, speed: 3, - cost: 10, + cost: 20, billingTier: "premium", contextWindow: 1_000_000, }, @@ -75,14 +76,14 @@ export const WORKSPACE_AI_CHAT_MODELS = [ bestFor: "Quick help & short drafts", intelligence: 2, speed: 4, - cost: 5, + cost: 10, billingTier: "standard", contextWindow: 200_000, }, { - id: "gpt-terra", - name: "GPT-5.6 Terra", - gatewayModel: "openai/gpt-5.6-terra", + id: "gpt-sol", + name: "GPT-6.1 Sol", + gatewayModel: "openai/gpt-6.1-sol", provider: "openai", tagline: "Strong on harder tasks", description: @@ -90,14 +91,14 @@ export const WORKSPACE_AI_CHAT_MODELS = [ bestFor: "Planning, research & knowledge work", intelligence: 4, speed: 3, - cost: 10, + cost: 19, billingTier: "premium", - contextWindow: 1_000_000, + contextWindow: 1_050_000, }, { id: "gpt-luna", - name: "GPT-5.6 Luna", - gatewayModel: "openai/gpt-5.6-luna", + name: "GPT-6 Luna", + gatewayModel: "openai/gpt-6-luna", provider: "openai", tagline: "Quick and capable", description: "A faster GPT for quick help, everyday questions, and practical tasks.", @@ -106,7 +107,7 @@ export const WORKSPACE_AI_CHAT_MODELS = [ speed: 4, cost: 1, billingTier: "standard", - contextWindow: 1_000_000, + contextWindow: 1_050_000, }, { id: "gemini-pro", @@ -119,14 +120,14 @@ export const WORKSPACE_AI_CHAT_MODELS = [ bestFor: "Long docs, research & hard problems", intelligence: 4, speed: 2, - cost: 10, + cost: 21, billingTier: "premium", contextWindow: 1_000_000, }, { id: "gemini", - name: "Gemini 3 Flash", - gatewayModel: "google/gemini-3-flash", + name: "Gemini 3.8 Flash", + gatewayModel: "google/gemini-3.8-flash", provider: "google", tagline: "Fast and wide-ranging", description: @@ -134,7 +135,7 @@ export const WORKSPACE_AI_CHAT_MODELS = [ bestFor: "Fast answers & big context", intelligence: 3, speed: 4, - cost: 3, + cost: 8, billingTier: "standard", contextWindow: 1_000_000, }, diff --git a/src/features/workspaces/extraction/providers/gemini-image-markdown.ts b/src/features/workspaces/extraction/providers/gemini-image-markdown.ts index d6992b32..1d70620e 100644 --- a/src/features/workspaces/extraction/providers/gemini-image-markdown.ts +++ b/src/features/workspaces/extraction/providers/gemini-image-markdown.ts @@ -13,7 +13,7 @@ import type { MarkdownExtractionResult, } from "#/features/workspaces/extraction/types"; -const IMAGE_EXTRACTION_GATEWAY_MODEL = "google/gemini-2.5-flash"; +const IMAGE_EXTRACTION_GATEWAY_MODEL = "google/gemini-3.8-flash"; const jpegMediaType = "image/jpeg"; // Transcription, not interpretation: the markdown feeds search and chat context, @@ -50,14 +50,12 @@ export function createGeminiImageMarkdownProvider(env: Env): MarkdownExtractionP `model:${IMAGE_EXTRACTION_GATEWAY_MODEL}`, ], }, - // The 2.5-series rejects `thinkingLevel` outright, which 400s every - // Google leg; budget is its knob. Reading what is on the page needs - // no reasoning, and the fallbacks bill for it if it is left on. + // Minimize reasoning for transcription and its fallback models. google: { - thinkingConfig: { thinkingBudget: 0 }, + thinkingConfig: { thinkingLevel: "low" }, }, vertex: { - thinkingConfig: { thinkingBudget: 0 }, + thinkingConfig: { thinkingLevel: "low" }, }, openai: { reasoningEffort: "none", diff --git a/src/integrations/autumn/workspace-ai-access.test.ts b/src/integrations/autumn/workspace-ai-access.test.ts index 0f8b83e8..f529bd39 100644 --- a/src/integrations/autumn/workspace-ai-access.test.ts +++ b/src/integrations/autumn/workspace-ai-access.test.ts @@ -23,7 +23,7 @@ describe("resolveWorkspaceAiMessageAccess", () => { }); it("falls back to auto when premium is spent but standard remains", () => { - for (const chosenModelId of ["claude-sonnet", "gpt-terra", "gemini-pro"] as const) { + for (const chosenModelId of ["claude-sonnet", "gpt-sol", "gemini-pro"] as const) { expect( resolveWorkspaceAiMessageAccess({ chosenModelId, @@ -99,7 +99,7 @@ describe("resolveWorkspaceAiMessageAccess", () => { // quietly becoming the priciest model in the tier it lands on. describe("fallback pricing", () => { it("lands on the cheapest model in the tier it falls back to", () => { - for (const chosenModelId of ["claude-sonnet", "gpt-terra", "gemini-pro"] as const) { + for (const chosenModelId of ["claude-sonnet", "gpt-sol", "gemini-pro"] as const) { const access = resolveWorkspaceAiMessageAccess({ chosenModelId, chosenTierAllowed: false, diff --git a/src/integrations/posthog/ai-observability.worker.test.ts b/src/integrations/posthog/ai-observability.worker.test.ts index bd4bd543..fcec852c 100644 --- a/src/integrations/posthog/ai-observability.worker.test.ts +++ b/src/integrations/posthog/ai-observability.worker.test.ts @@ -93,7 +93,7 @@ describe("getGatewayServedRoute", () => { routing: { finalProvider: "openai", modelAttempts: [ - { canonicalSlug: "anthropic/claude-sonnet-5", success: false, providerAttempts: [] }, + { canonicalSlug: "anthropic/claude-sonnet-5.5", success: false, providerAttempts: [] }, { canonicalSlug: "openai/gpt-5.6-terra", success: true,