diff --git a/.env.example b/.env.example index 4f475d5..7d2bca3 100644 --- a/.env.example +++ b/.env.example @@ -4,7 +4,7 @@ # Text generation provider AI_PROVIDER=minimax NEXT_PUBLIC_AI_PROVIDER=minimax -AI_DEFAULT_MODEL=MiniMax-M2.7 +AI_DEFAULT_MODEL=MiniMax-M3 MINIMAX_API_KEY=your_minimax_api_key_here # Optional override if you need a non-default MiniMax API base URL. MINIMAX_API_BASE_URL= @@ -24,7 +24,7 @@ SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key_here CSRF_SALT=generate_a_long_random_string_here # Optional client-side AI model hint -NEXT_PUBLIC_AI_MODEL=MiniMax-M2.7 +NEXT_PUBLIC_AI_MODEL=MiniMax-M3 # Optional features NEXT_PUBLIC_ENABLE_TRANSLATION_SELECTOR=false diff --git a/.env.local.example b/.env.local.example index b1d54c1..5e03a34 100644 --- a/.env.local.example +++ b/.env.local.example @@ -3,7 +3,7 @@ # Text generation provider AI_PROVIDER=minimax NEXT_PUBLIC_AI_PROVIDER=minimax -AI_DEFAULT_MODEL=MiniMax-M2.7 +AI_DEFAULT_MODEL=MiniMax-M3 MINIMAX_API_KEY=your_minimax_api_key_here # Optional override for self-hosted or alternate MiniMax gateways. MINIMAX_API_BASE_URL= @@ -23,7 +23,7 @@ SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key_here CSRF_SALT=generate_a_long_random_string_here # Optional client-side AI model hint -NEXT_PUBLIC_AI_MODEL=MiniMax-M2.7 +NEXT_PUBLIC_AI_MODEL=MiniMax-M3 # Optional features NEXT_PUBLIC_ENABLE_TRANSLATION_SELECTOR=false diff --git a/CLAUDE.md b/CLAUDE.md index ca59637..b288bf8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -326,7 +326,7 @@ Required in `.env.local`: Also commonly needed: - `AI_PROVIDER`: Server-side text provider selection (`minimax`, `grok`, or `gemini`) - `NEXT_PUBLIC_AI_PROVIDER`: Set this to match `AI_PROVIDER` for consistent client/server provider behavior in Phase 1 -- `AI_DEFAULT_MODEL`: Optional text model override (Phase 1 default: `MiniMax-M2.7`) +- `AI_DEFAULT_MODEL`: Optional text model override (current default: `MiniMax-M3`) - `NEXT_PUBLIC_AI_MODEL`: Optional client-side model hint; it does not select the server provider by itself - `GEMINI_API_KEY`: Still required for `app/api/generate-image/route.ts` diff --git a/README.md b/README.md index 0b60481..08e8a06 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ Create `.env.local` in the repo root: | `CSRF_SALT` | yes | Long random string used to sign CSRF tokens | | `AI_PROVIDER` | recommended | `minimax`, `grok`, or `gemini`; determines which server-side text provider adapter is used | | `NEXT_PUBLIC_AI_PROVIDER` | recommended | Set this to match `AI_PROVIDER` for consistent client/server provider behavior in Phase 1 | -| `AI_DEFAULT_MODEL` | recommended | Override provider default model (for Phase 1, `MiniMax-M2.7`) | +| `AI_DEFAULT_MODEL` | recommended | Override provider default model (currently `MiniMax-M3`) | | `NEXT_PUBLIC_AI_MODEL` | optional | Client-side model hint for UI/config display; does not control server routing by itself | | `NEXT_PUBLIC_APP_URL` | optional | Canonical app URL (defaults to `http://localhost:3000`) | | `NEXT_PUBLIC_ENABLE_TRANSLATION_SELECTOR` | optional | Set to `true` to show the transcript translation dropdown (hidden otherwise) | @@ -128,7 +128,7 @@ Create `.env.local` in the repo root: \** `GEMINI_API_KEY` is still required if image generation should work, because `app/api/generate-image/route.ts` remains Gemini-backed. -> Recommended Phase 1 setup: `AI_PROVIDER=minimax`, `NEXT_PUBLIC_AI_PROVIDER=minimax`, `AI_DEFAULT_MODEL=MiniMax-M2.7`, `MINIMAX_API_KEY=...`. Keep `GEMINI_API_KEY` set if you want image generation, and optionally keep `XAI_API_KEY` available for Grok fallback/testing. +> Recommended setup: `AI_PROVIDER=minimax`, `NEXT_PUBLIC_AI_PROVIDER=minimax`, `AI_DEFAULT_MODEL=MiniMax-M3`, `MINIMAX_API_KEY=...`. Keep `GEMINI_API_KEY` set if you want image generation, and optionally keep `XAI_API_KEY` available for Grok fallback/testing. > Generate a unique `CSRF_SALT` (e.g., `openssl rand -base64 32`). `UNLIMITED_VIDEO_USERS` entries are normalized to lowercase. diff --git a/docs/superpowers/specs/2026-06-04-minimax-m3-default-design.md b/docs/superpowers/specs/2026-06-04-minimax-m3-default-design.md new file mode 100644 index 0000000..d742466 --- /dev/null +++ b/docs/superpowers/specs/2026-06-04-minimax-m3-default-design.md @@ -0,0 +1,22 @@ +# MiniMax M3 Default Model Design + +## Context + +LongCut currently defaults MiniMax text generation to `MiniMax-M2.7`. MiniMax has released `MiniMax-M3`, and the project should use M3 by default while preserving existing environment-variable overrides for rollback or experimentation. + +## Scope + +- Change source-controlled MiniMax default model strings from `MiniMax-M2.7` to `MiniMax-M3`. +- Update provider and validation tests that assert MiniMax defaults. +- Update active environment examples and active documentation. +- Do not change the MiniMax adapter API shape, base URL, provider fallback order, request payload structure, or generated build output. +- Do not edit unrelated existing worktree changes such as `package.json`. + +## Approach + +Use the existing provider configuration and adapter defaults. `AI_DEFAULT_MODEL`, `AI_FAST_MODEL`, `AI_PRO_MODEL`, and `NEXT_PUBLIC_AI_MODEL` remain supported as overrides. This makes rollback possible by setting `AI_DEFAULT_MODEL=MiniMax-M2.7` without code changes. + +## Verification + +- Run targeted tests for MiniMax adapter, provider config, and validation defaults. +- Run lint if the targeted tests pass and time permits. diff --git a/lib/__tests__/minimax-adapter.test.ts b/lib/__tests__/minimax-adapter.test.ts index fc73914..0e1da34 100644 --- a/lib/__tests__/minimax-adapter.test.ts +++ b/lib/__tests__/minimax-adapter.test.ts @@ -42,7 +42,7 @@ test('MiniMax adapter strips tags and normalizes usage', async () => { async () => new Response( JSON.stringify({ - model: 'MiniMax-M2.7', + model: 'MiniMax-M3', choices: [ { message: { @@ -64,7 +64,7 @@ test('MiniMax adapter strips tags and normalizes usage', async () => { assert.equal(result.content, '{"ok":true}'); assert.equal(result.provider, 'minimax'); - assert.equal(result.model, 'MiniMax-M2.7'); + assert.equal(result.model, 'MiniMax-M3'); assert.deepEqual(result.usage, { promptTokens: 11, completionTokens: 7, @@ -116,7 +116,7 @@ test('MiniMax adapter uses prompt-based schema compatibility when zodSchema is p return new Response( JSON.stringify({ - model: 'MiniMax-M2.7', + model: 'MiniMax-M3', choices: [ { message: { @@ -158,7 +158,7 @@ test('MiniMax adapter coerces metadata values to strings for API compatibility', return new Response( JSON.stringify({ - model: 'MiniMax-M2.7', + model: 'MiniMax-M3', choices: [ { message: { diff --git a/lib/__tests__/provider-config.test.ts b/lib/__tests__/provider-config.test.ts index 9ca2f41..4d9dd76 100644 --- a/lib/__tests__/provider-config.test.ts +++ b/lib/__tests__/provider-config.test.ts @@ -66,8 +66,8 @@ test('deterministic fallback order prefers Grok before Gemini before MiniMax', ( assert.deepEqual(getProviderFallbackOrder('grok'), ['gemini', 'minimax']); }); -test('provider default model returns MiniMax-M2.7 for MiniMax', () => { - assert.equal(getProviderDefaultModel('minimax'), 'MiniMax-M2.7'); +test('provider default model returns MiniMax-M3 for MiniMax', () => { + assert.equal(getProviderDefaultModel('minimax'), 'MiniMax-M3'); }); test('provider model defaults derive fast and pro topic models from configured MiniMax provider', () => { @@ -81,9 +81,9 @@ test('provider model defaults derive fast and pro topic models from configured M }, () => { assert.deepEqual(getProviderModelDefaults(), { - defaultModel: 'MiniMax-M2.7', - fastModel: 'MiniMax-M2.7', - proModel: 'MiniMax-M2.7', + defaultModel: 'MiniMax-M3', + fastModel: 'MiniMax-M3', + proModel: 'MiniMax-M3', }); } ); @@ -104,9 +104,9 @@ test('effective provider resolves to MiniMax when only MINIMAX_API_KEY is presen () => { assert.equal(getEffectiveProviderKey(), 'minimax'); assert.deepEqual(getProviderModelDefaults(), { - defaultModel: 'MiniMax-M2.7', - fastModel: 'MiniMax-M2.7', - proModel: 'MiniMax-M2.7', + defaultModel: 'MiniMax-M3', + fastModel: 'MiniMax-M3', + proModel: 'MiniMax-M3', }); } ); diff --git a/lib/__tests__/validation.test.ts b/lib/__tests__/validation.test.ts index 23b8cf8..bdeb6d5 100644 --- a/lib/__tests__/validation.test.ts +++ b/lib/__tests__/validation.test.ts @@ -40,7 +40,7 @@ test('model schema defaults to MiniMax model when only MINIMAX_API_KEY is presen }, async () => { const { modelSchema } = await importFreshValidationModule(); - assert.equal(modelSchema.parse(undefined), 'MiniMax-M2.7'); + assert.equal(modelSchema.parse(undefined), 'MiniMax-M3'); } ); }); diff --git a/lib/ai-providers/minimax-adapter.ts b/lib/ai-providers/minimax-adapter.ts index 421f372..1a80cde 100644 --- a/lib/ai-providers/minimax-adapter.ts +++ b/lib/ai-providers/minimax-adapter.ts @@ -2,7 +2,7 @@ import { z } from 'zod'; import type { ProviderAdapter, ProviderGenerateParams, ProviderGenerateResult } from './types'; const PROVIDER_NAME = 'minimax'; -const DEFAULT_MODEL = 'MiniMax-M2.7'; +const DEFAULT_MODEL = 'MiniMax-M3'; const DEFAULT_BASE_URL = 'https://api.minimax.io/v1'; function buildAbortController(timeoutMs?: number) { diff --git a/lib/ai-providers/provider-config.ts b/lib/ai-providers/provider-config.ts index c93d080..ce5d365 100644 --- a/lib/ai-providers/provider-config.ts +++ b/lib/ai-providers/provider-config.ts @@ -5,7 +5,7 @@ const PROVIDER_ORDER: ProviderKey[] = ['grok', 'gemini', 'minimax']; const PROVIDER_DEFAULT_MODELS: Record = { grok: 'grok-4-1-fast-non-reasoning', gemini: 'gemini-2.5-flash-lite', - minimax: 'MiniMax-M2.7', + minimax: 'MiniMax-M3', }; const PROVIDER_BEHAVIORS: Record = {