Skip to content

feat: add MiniMax as first-class LLM provider - #231

Open
octo-patch wants to merge 1 commit into
plastic-labs:mainfrom
octo-patch:feature/add-minimax-provider
Open

feat: add MiniMax as first-class LLM provider#231
octo-patch wants to merge 1 commit into
plastic-labs:mainfrom
octo-patch:feature/add-minimax-provider

Conversation

@octo-patch

@octo-patch octo-patch commented Mar 28, 2026

Copy link
Copy Markdown

Summary

  • Add MiniMax as a built-in LLM provider alongside OpenRouter via a provider presets system
  • Temperature clamping for MiniMax API (requires (0, 1] range) and conditional OpenRouter-specific providerOptions
  • Updated .env.template and README with MiniMax setup guide and provider preset table

Motivation

Tutor-GPT currently defaults to OpenRouter, but the architecture already uses @ai-sdk/openai-compatible with configurable env vars. This PR adds MiniMax as a recognized provider preset so users can switch to MiniMax-M2.7 (1M context, latest reasoning model) by simply setting AI_PROVIDER=minimax and AI_API_KEY.

Changes

File Change
utils/ai.ts Provider presets map, clampTemperature(), conditional providerOptions
.env.template MiniMax configuration example
README.md Provider preset table, MiniMax setup instructions
tests/provider.test.ts 14 unit tests for presets and temperature clamping
tests/provider.integration.test.ts 8 integration tests for preset resolution and API endpoint compatibility

Usage

AI_PROVIDER=minimax
AI_API_KEY=your-minimax-api-key
# MODEL=MiniMax-M2.7-highspeed  # optional: faster variant

Test plan

  • 22 unit + integration tests pass (pnpm test)
  • Verify MiniMax M2.7 generates valid tutor responses with AI_PROVIDER=minimax
  • Verify OpenRouter behavior is unchanged (default path)
  • Verify unknown providers fall back to OpenRouter defaults

Summary by CodeRabbit

Release Notes

  • New Features

    • Added MiniMax as a supported LLM inference provider. OpenRouter is now designated as the default provider option.
    • Improved provider configuration system with intelligent preset defaults for each supported provider.
  • Documentation

    • Updated environment configuration templates and README documentation with MiniMax provider setup instructions and complete supported provider reference information.

Add MiniMax (MiniMax-M2.7 / MiniMax-M2.7-highspeed) as a built-in LLM
provider alongside OpenRouter. Changes include:

- Provider presets system in utils/ai.ts with auto-configured base URL
  and default model per provider
- Temperature clamping for MiniMax (requires (0, 1] range)
- Conditional OpenRouter-specific providerOptions (only applied when
  AI_PROVIDER=openrouter)
- Updated .env.template with MiniMax configuration example
- Updated README with provider preset table and MiniMax setup guide
- 22 unit + integration tests covering presets, temperature clamping,
  and endpoint compatibility

Usage: set AI_PROVIDER=minimax and AI_API_KEY to switch providers.
@vercel

vercel Bot commented Mar 28, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the Plastic Labs Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Mar 28, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This pull request adds support for the MiniMax LLM provider alongside the existing Openrouter default. Changes include a new provider preset system with base URLs and model defaults, temperature clamping logic specific to MiniMax constraints, updated documentation, and comprehensive test coverage for provider selection and temperature handling.

Changes

Cohort / File(s) Summary
Configuration & Documentation
.env.template, README.md
Added MiniMax provider configuration guidance to .env.template. Updated README to document Openrouter as default and MiniMax as an alternative, including a provider preset table and .env example for MiniMax selection.
Provider System Implementation
utils/ai.ts
Introduced PROVIDER_PRESETS centralized configuration mapping providers to base URLs, default models, and optional headers. Implemented clampTemperature() helper function for MiniMax-specific temperature range constraints (0.01–1). Updated streamText, streamObject, and generateText to use preset values and apply temperature clamping. Made OpenRouter providerOptions.order conditional on provider selection.
Provider Test Coverage
tests/provider.test.ts, tests/provider.integration.test.ts
Added unit tests validating PROVIDER_PRESETS structure, header definitions, and URL distinctness. Added integration tests verifying preset resolution fallback behavior, temperature clamping boundaries for MiniMax (0 and negatives → 0.01, above 1 → 1), and MiniMax endpoint HTTPS/OpenAI-compatibility characteristics.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 A provider named MiniMax hops into view,
With presets and clamps, the bounds stay true,
Temperatures clamped from zero to one,
New tests ensure the work is done! 🌟

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: adding MiniMax as a first-class LLM provider alongside the existing OpenRouter provider.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
utils/ai.ts (1)

136-148: Deduplicate repeated OpenRouter providerOptions block.

The same openrouter.order object is repeated in four places; centralizing it will reduce drift.

♻️ Suggested refactor
+const OPENROUTER_PROVIDER_OPTIONS =
+  AI_PROVIDER === 'openrouter'
+    ? {
+        providerOptions: {
+          openrouter: {
+            order: ['DeepInfra', 'Hyperbolic', 'Fireworks', 'Together', 'Lambda'],
+          },
+        },
+      }
+    : {};

 // in each AI call:
-    ...(AI_PROVIDER === 'openrouter' && {
-      providerOptions: {
-        openrouter: {
-          order: [
-            'DeepInfra',
-            'Hyperbolic',
-            'Fireworks',
-            'Together',
-            'Lambda',
-          ],
-        },
-      },
-    }),
+    ...OPENROUTER_PROVIDER_OPTIONS,

Also applies to: 183-195, 236-248, 282-294

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@utils/ai.ts` around lines 136 - 148, Extract the repeated openrouter order
array into a single constant (e.g. OPENROUTER_ORDER) and replace each duplicated
providerOptions block with a reference to that constant; specifically, where the
code checks AI_PROVIDER === 'openrouter' and constructs
providerOptions.openrouter.order, use order: OPENROUTER_ORDER instead of
inlining the array (this ensures the blocks in the AI configuration that
currently repeat the same array are centralized and reused).
tests/provider.test.ts (1)

77-82: You can remove the duplicate 0.01 edge-case test.

Line 81 already validates 0.01; the separate test at Lines 84-86 is redundant.

Also applies to: 84-86

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/provider.test.ts` around lines 77 - 82, Remove the redundant edge-case
assertion for clampTemperature('minimax', 0.01): there is already an assertion
checking 0.01 in the "keeps valid minimax temperatures unchanged" test, so
delete the duplicate expect(clampTemperature('minimax', 0.01)).toBe(0.01) in the
other test block to avoid duplicated coverage of the same edge case while
keeping the rest of the tests intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@README.md`:
- Line 86: Update the README text for the AI_BASE_URL description to use the
compound adjective form "OpenAI-compatible" instead of "OpenAI compatible";
locate the line containing the `AI_BASE_URL` entry and change the phrase to "An
OpenAI-compatible API endpoint for LLM inference" to ensure correctness and
consistency.

In `@tests/provider.integration.test.ts`:
- Line 24: Remove the redundant "undefined ||" prefix from the test constants
(e.g., the const baseURL assignment and the other consts flagged on lines 31,
38, 39) so the expressions read directly as fallback chains (for example: use
preset?.baseURL || 'https://openrouter.ai/api/v1' instead of undefined ||
preset?.baseURL || ...); update the const declarations where the pattern appears
(search for "undefined ||" in tests/provider.integration.test.ts) to simplify
the expressions and improve clarity.

---

Nitpick comments:
In `@tests/provider.test.ts`:
- Around line 77-82: Remove the redundant edge-case assertion for
clampTemperature('minimax', 0.01): there is already an assertion checking 0.01
in the "keeps valid minimax temperatures unchanged" test, so delete the
duplicate expect(clampTemperature('minimax', 0.01)).toBe(0.01) in the other test
block to avoid duplicated coverage of the same edge case while keeping the rest
of the tests intact.

In `@utils/ai.ts`:
- Around line 136-148: Extract the repeated openrouter order array into a single
constant (e.g. OPENROUTER_ORDER) and replace each duplicated providerOptions
block with a reference to that constant; specifically, where the code checks
AI_PROVIDER === 'openrouter' and constructs providerOptions.openrouter.order,
use order: OPENROUTER_ORDER instead of inlining the array (this ensures the
blocks in the AI configuration that currently repeat the same array are
centralized and reused).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4c1c0433-405f-484c-bbc0-d0875d596a8e

📥 Commits

Reviewing files that changed from the base of the PR and between 5c2f924 and 417631f.

📒 Files selected for processing (5)
  • .env.template
  • README.md
  • tests/provider.integration.test.ts
  • tests/provider.test.ts
  • utils/ai.ts

Comment thread README.md
- `AI_API_KEY` — The API key for the inference provider
- `AI_PROVIDER` — The name of the LLM inference provider
- `AI_PROVIDER` — The name of the LLM inference provider (e.g. `openrouter`, `minimax`)
- `AI_BASE_URL` — An OpenAI compatible API endpoint for LLM inference

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Hyphenate “OpenAI-compatible” for correctness and consistency.

Line 86 should use the compound adjective form.

✏️ Proposed doc fix
-- `AI_BASE_URL` — An OpenAI compatible API endpoint for LLM inference
+- `AI_BASE_URL` — An OpenAI-compatible API endpoint for LLM inference
🧰 Tools
🪛 LanguageTool

[grammar] ~86-~86: Use a hyphen to join words.
Context: ..., minimax) - AI_BASE_URL — An OpenAI compatible API endpoint for LLM inferenc...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` at line 86, Update the README text for the AI_BASE_URL description
to use the compound adjective form "OpenAI-compatible" instead of "OpenAI
compatible"; locate the line containing the `AI_BASE_URL` entry and change the
phrase to "An OpenAI-compatible API endpoint for LLM inference" to ensure
correctness and consistency.

// AI_BASE_URL is not set.
const provider = 'minimax';
const preset = PROVIDER_PRESETS[provider];
const baseURL = undefined || preset?.baseURL || 'https://openrouter.ai/api/v1';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify no constant-left `undefined ||` remains in this test file.
rg -nP 'undefined\s*\|\|' tests/provider.integration.test.ts
# Expected result after fix: no matches

Repository: plastic-labs/tutor-gpt

Length of output: 389


🏁 Script executed:

# Search for ESLint configuration files
fd -e '.eslintrc*' -e 'eslint.config.*' -type f

Repository: plastic-labs/tutor-gpt

Length of output: 236


🏁 Script executed:

# Check package.json for lint scripts and dependencies
cat package.json | grep -A 20 '"scripts"' | head -30

Repository: plastic-labs/tutor-gpt

Length of output: 927


🏁 Script executed:

# View the full test file to see context around the flagged lines
wc -l tests/provider.integration.test.ts

Repository: plastic-labs/tutor-gpt

Length of output: 103


🏁 Script executed:

# Find ESLint configuration properly
find . -maxdepth 2 -name '.eslintrc*' -o -name 'eslint.config.*' 2>/dev/null

Repository: plastic-labs/tutor-gpt

Length of output: 85


🏁 Script executed:

# View the test file around the flagged lines
cat -n tests/provider.integration.test.ts

Repository: plastic-labs/tutor-gpt

Length of output: 4290


🏁 Script executed:

# Check the ESLint configuration
cat eslint.config.mjs

Repository: plastic-labs/tutor-gpt

Length of output: 806


Remove unnecessary undefined || expressions.

Lines 24, 31, 38, and 39 contain undefined || ... patterns that serve no purpose and reduce code clarity. While the no-constant-binary-expression rule would flag these, they don't impact CI since the test directory is excluded from linting. Simplify by removing the undefined || prefix.

Proposed fix
-    const baseURL = undefined || preset?.baseURL || 'https://openrouter.ai/api/v1';
+    const baseURL = preset?.baseURL || 'https://openrouter.ai/api/v1';
-    const model = undefined || preset?.defaultModel || 'gpt-3.5-turbo';
+    const model = preset?.defaultModel || 'gpt-3.5-turbo';

Also applies to: 31-31, 38-39

🧰 Tools
🪛 ESLint

[error] 24-24: Unexpected constant truthiness on the left-hand side of a || expression.

(no-constant-binary-expression)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/provider.integration.test.ts` at line 24, Remove the redundant
"undefined ||" prefix from the test constants (e.g., the const baseURL
assignment and the other consts flagged on lines 31, 38, 39) so the expressions
read directly as fallback chains (for example: use preset?.baseURL ||
'https://openrouter.ai/api/v1' instead of undefined || preset?.baseURL || ...);
update the const declarations where the pattern appears (search for "undefined
||" in tests/provider.integration.test.ts) to simplify the expressions and
improve clarity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant