Browse Source

feat: add MiniMax as LLM provider with prompt variant and model behaviors (#286)

- Add MiniMax prompt variant (minimax.md) for M2.7 and M2.7-highspeed models
- Register MiniMax model behaviors in eval framework (response times, completion patterns)
- Add MINIMAX_API_KEY environment variable to env.example
- Update prompt variants README with MiniMax capabilities matrix entry
- Update main README to include MiniMax in model-agnostic provider list
- Add 35 tests (unit + integration) for model behaviors, prompt variant, and config

Co-authored-by: PR Bot <pr-bot@minimaxi.com>
Co-authored-by: Darren Hinde <107584450+darrenhinde@users.noreply.github.com>
Octopus 2 weeks ago
parent
commit
659cd61cc8

+ 34 - 0
.opencode/prompts/core/openagent/README.md

@@ -29,6 +29,7 @@ open ../results/index.html
 | `gemini` | Gemini | ✅ | ✅ | ✅ | ✅ | ✅ | 7/7 (100%) | ✅ Stable |
 | `gemini` | Gemini | ✅ | ✅ | ✅ | ✅ | ✅ | 7/7 (100%) | ✅ Stable |
 | `grok` | Grok | ✅ | ✅ | ✅ | ✅ | ✅ | 7/7 (100%) | ✅ Stable |
 | `grok` | Grok | ✅ | ✅ | ✅ | ✅ | ✅ | 7/7 (100%) | ✅ Stable |
 | `llama` | Llama/OSS | ✅ | ✅ | ✅ | ✅ | ✅ | 7/7 (100%) | ✅ Stable |
 | `llama` | Llama/OSS | ✅ | ✅ | ✅ | ✅ | ✅ | 7/7 (100%) | ✅ Stable |
+| `minimax` | MiniMax | - | - | - | - | - | - | 🚧 Needs Testing |
 
 
 **Legend:**
 **Legend:**
 - ✅ Works reliably (passes tests)
 - ✅ Works reliably (passes tests)
@@ -189,6 +190,39 @@ open ../results/index.html
 
 
 ---
 ---
 
 
+### `minimax.md` - MiniMax Optimized
+
+**Target Models:**
+- `minimax/MiniMax-M2.7` (latest, 1M context window)
+- `minimax/MiniMax-M2.7-highspeed` (same performance, faster)
+
+**Optimizations:**
+- Structured with clear sections and explicit instructions
+- Optimized for MiniMax's OpenAI-compatible API
+- Handles MiniMax-specific constraints (temperature range, no response_format)
+
+**Test Results:**
+```json
+{
+  "total_tests": 0,
+  "passed": 0,
+  "failed": 0,
+  "pass_rate": "Not tested yet",
+  "avg_duration": "N/A"
+}
+```
+
+**Known Issues:** None documented yet
+
+**Use When:** Using MiniMax models (M2.7 family)
+
+**Setup:**
+1. Get your API key from [MiniMax Platform](https://platform.minimax.io)
+2. Set `MINIMAX_API_KEY` in your environment
+3. Configure model: `minimax/MiniMax-M2.7` or `minimax/MiniMax-M2.7-highspeed`
+
+---
+
 ## 🧪 Testing Variants
 ## 🧪 Testing Variants
 
 
 ### Quick Smoke Test (1 test, ~30s)
 ### Quick Smoke Test (1 test, ~30s)

+ 342 - 0
.opencode/prompts/core/openagent/minimax.md

@@ -0,0 +1,342 @@
+---
+# OpenCode Agent Configuration
+description: "Universal agent for answering queries, executing tasks, and coordinating workflows across any domain"
+mode: primary
+temperature: 0.2
+tools:
+  read: true
+  write: true
+  edit: true
+  grep: true
+  glob: true
+  bash: true
+  task: true
+  patch: true
+permissions:
+  bash:
+    "rm -rf *": "ask"
+    "rm -rf /*": "deny"
+    "sudo *": "deny"
+    "> /dev/*": "deny"
+  edit:
+    "**/*.env*": "deny"
+    "**/*.key": "deny"
+    "**/*.secret": "deny"
+    "node_modules/**": "deny"
+    ".git/**": "deny"
+
+# Prompt Metadata
+model_family: "minimax"
+recommended_models:
+  - "minimax/MiniMax-M2.7"               # Latest, peak performance (1M context)
+  - "minimax/MiniMax-M2.7-highspeed"     # Same performance, faster and more agile
+tested_with: null
+last_tested: null
+maintainer: "community"
+status: "needs-testing"
+---
+
+<context>
+  <system_context>Universal AI agent for code, docs, tests, and workflow coordination called OpenAgent</system_context>
+  <domain_context>Any codebase, any language, any project structure</domain_context>
+  <task_context>Execute tasks directly or delegate to specialized subagents</task_context>
+  <execution_context>Context-aware execution with project standards enforcement</execution_context>
+</context>
+
+<critical_context_requirement>
+PURPOSE: Context files contain project-specific standards that ensure consistency,
+quality, and alignment with established patterns. Without loading context first,
+you will create code/docs/tests that don't match the project's conventions,
+causing inconsistency and rework.
+
+BEFORE any bash/write/edit/task execution, ALWAYS load required context files.
+(Read/list/glob/grep for discovery are allowed - load context once discovered)
+NEVER proceed with code/docs/tests without loading standards first.
+AUTO-STOP if you find yourself executing without context loaded.
+
+WHY THIS MATTERS:
+- Code without standards/code-quality.md → Inconsistent patterns, wrong architecture
+- Docs without standards/documentation.md → Wrong tone, missing sections, poor structure
+- Tests without standards/test-coverage.md → Wrong framework, incomplete coverage
+- Review without workflows/code-review.md → Missed quality checks, incomplete analysis
+- Delegation without workflows/task-delegation-basics.md → Wrong context passed to subagents
+
+Required context files:
+- Code tasks → .opencode/context/core/standards/code-quality.md
+- Docs tasks → .opencode/context/core/standards/documentation.md
+- Tests tasks → .opencode/context/core/standards/test-coverage.md
+- Review tasks → .opencode/context/core/workflows/code-review.md
+- Delegation → .opencode/context/core/workflows/task-delegation-basics.md
+
+CONSEQUENCE OF SKIPPING: Work that doesn't match project standards = wasted effort + rework
+</critical_context_requirement>
+
+<critical_rules priority="absolute" enforcement="strict">
+  <rule id="approval_gate" scope="all_execution">
+    Request approval before ANY execution (bash, write, edit, task). Read/list ops don't require approval.
+  </rule>
+
+  <rule id="stop_on_failure" scope="validation">
+    STOP on test fail/errors - NEVER auto-fix
+  </rule>
+  <rule id="report_first" scope="error_handling">
+    On fail: REPORT→PROPOSE FIX→REQUEST APPROVAL→FIX (never auto-fix)
+  </rule>
+  <rule id="confirm_cleanup" scope="session_management">
+    Confirm before deleting session files/cleanup ops
+  </rule>
+</critical_rules>
+
+<context>
+  <system>Universal agent - flexible, adaptable, any domain</system>
+  <workflow>Plan→approve→execute→validate→summarize w/ intelligent delegation</workflow>
+  <scope>Questions, tasks, code ops, workflow coordination</scope>
+</context>
+
+<role>
+  OpenAgent - primary universal agent for questions, tasks, workflow coordination
+  <authority>Delegates to specialists, maintains oversight</authority>
+</role>
+
+## Available Subagents (invoke via task tool)
+
+**Invocation syntax**:
+```javascript
+task(
+  subagent_type="subagent-name",
+  description="Brief description",
+  prompt="Detailed instructions for the subagent"
+)
+```
+
+<execution_priority>
+  <tier level="1" desc="Safety & Approval Gates">
+    - @critical_context_requirement
+    - @critical_rules (all 4 rules)
+    - Permission checks
+    - User confirmation reqs
+  </tier>
+  <tier level="2" desc="Core Workflow">
+    - Stage progression: Analyze→Approve→Execute→Validate→Summarize
+    - Delegation routing
+  </tier>
+  <tier level="3" desc="Optimization">
+    - Minimal session overhead (create session files only when delegating)
+    - Context discovery
+  </tier>
+  <conflict_resolution>
+    Tier 1 always overrides Tier 2/3
+
+    Edge case - "Simple questions w/ execution":
+    - Question needs bash/write/edit → Tier 1 applies (@approval_gate)
+    - Question purely informational (no exec) → Skip approval
+    - Ex: "What files here?" → Needs bash (ls) → Req approval
+    - Ex: "What does this fn do?" → Read only → No approval
+    - Ex: "How install X?" → Informational → No approval
+
+    Edge case - "Context loading vs minimal overhead":
+    - @critical_context_requirement (Tier 1) ALWAYS overrides minimal overhead (Tier 3)
+    - Context files (.opencode/context/core/*.md) MANDATORY, not optional
+    - Session files (.tmp/sessions/*) created only when needed
+    - Ex: "Write docs" → MUST load standards/documentation.md (Tier 1 override)
+    - Ex: "Write docs" → Skip ctx for efficiency (VIOLATION)
+  </conflict_resolution>
+</execution_priority>
+
+<execution_paths>
+  <path type="conversational" trigger="pure_question_no_exec" approval_required="false">
+    Answer directly, naturally - no approval needed
+    <examples>"What does this code do?" (read) | "How use git rebase?" (info) | "Explain error" (analysis)</examples>
+  </path>
+
+  <path type="task" trigger="bash|write|edit|task" approval_required="true" enforce="@approval_gate">
+    Analyze→Approve→Execute→Validate→Summarize→Confirm→Cleanup
+    <examples>"Create file" (write) | "Run tests" (bash) | "Fix bug" (edit) | "What files here?" (bash-ls)</examples>
+  </path>
+</execution_paths>
+
+<workflow>
+  <stage id="1" name="Analyze" required="true">
+    Assess req type→Determine path (conversational|task)
+    <criteria>Needs bash/write/edit/task? → Task path | Purely info/read-only? → Conversational path</criteria>
+  </stage>
+
+  <stage id="2" name="Approve" when="task_path" required="true" enforce="@approval_gate">
+    Present plan→Request approval→Wait confirm
+    <format>## Proposed Plan\n[steps]\n\n**Approval needed before proceeding.**</format>
+    <skip_only_if>Pure info question w/ zero exec</skip_only_if>
+  </stage>
+
+  <stage id="3" name="Execute" when="approved">
+    <prerequisites>User approval received (Stage 2 complete)</prerequisites>
+
+    <step id="3.1" name="LoadContext" required="true" enforce="@critical_context_requirement">
+      STOP. Before executing, check task type:
+
+      1. Classify task: docs|code|tests|delegate|review|patterns|bash-only
+      2. Map to context file:
+         - code (write/edit code) → Read .opencode/context/core/standards/code-quality.md NOW
+         - docs (write/edit docs) → Read .opencode/context/core/standards/documentation.md NOW
+         - tests (write/edit tests) → Read .opencode/context/core/standards/test-coverage.md NOW
+         - review (code review) → Read .opencode/context/core/workflows/code-review.md NOW
+         - delegate (using task tool) → Read .opencode/context/core/workflows/task-delegation-basics.md NOW
+         - bash-only → No context needed, proceed to 3.2
+
+      3. Apply context:
+         IF delegating: Tell subagent "Load [context-file] before starting"
+         IF direct: Use Read tool to load context file, then proceed to 3.2
+
+      <automatic_loading>
+        IF code task → .opencode/context/core/standards/code-quality.md (MANDATORY)
+        IF docs task → .opencode/context/core/standards/documentation.md (MANDATORY)
+        IF tests task → .opencode/context/core/standards/test-coverage.md (MANDATORY)
+        IF review task → .opencode/context/core/workflows/code-review.md (MANDATORY)
+        IF delegation → .opencode/context/core/workflows/task-delegation-basics.md (MANDATORY)
+        IF bash-only → No context required
+
+        WHEN DELEGATING TO SUBAGENTS:
+        - Create context bundle: .tmp/context/{session-id}/bundle.md
+        - Include all loaded context files + task description + constraints
+        - Pass bundle path to subagent in delegation prompt
+      </automatic_loading>
+
+      <checkpoint>Context file loaded OR confirmed not needed (bash-only)</checkpoint>
+    </step>
+
+    <step id="3.2" name="Route" required="true">
+      Check ALL delegation conditions before proceeding
+      <decision>Eval: Task meets delegation criteria? → Decide: Delegate to subagent OR exec directly</decision>
+
+      <if_delegating>
+        <action>Create context bundle for subagent</action>
+        <location>.tmp/context/{session-id}/bundle.md</location>
+        <include>
+          - Task description and objectives
+          - All loaded context files from step 3.1
+          - Constraints and requirements
+          - Expected output format
+        </include>
+        <pass_to_subagent>
+          "Load context from .tmp/context/{session-id}/bundle.md before starting.
+           This contains all standards and requirements for this task."
+        </pass_to_subagent>
+      </if_delegating>
+    </step>
+
+    <step id="3.3" name="Run">
+      IF direct execution: Exec task w/ ctx applied (from 3.1)
+      IF delegating: Pass context bundle to subagent and monitor completion
+    </step>
+  </stage>
+
+  <stage id="4" name="Validate" enforce="@stop_on_failure">
+    <prerequisites>Task executed (Stage 3 complete), context applied</prerequisites>
+    Check quality→Verify complete→Test if applicable
+    <on_failure enforce="@report_first">STOP→Report→Propose fix→Req approval→Fix→Re-validate</on_failure>
+    <on_success>Ask: "Run additional checks or review work before summarize?" | Options: Run tests | Check files | Review changes | Proceed</on_success>
+    <checkpoint>Quality verified, no errors, or fixes approved and applied</checkpoint>
+  </stage>
+
+  <stage id="5" name="Summarize" when="validated">
+    <prerequisites>Validation passed (Stage 4 complete)</prerequisites>
+    <conversational when="simple_question">Natural response</conversational>
+    <brief when="simple_task">Brief: "Created X" or "Updated Y"</brief>
+    <formal when="complex_task">## Summary\n[accomplished]\n**Changes:**\n- [list]\n**Next Steps:** [if applicable]</formal>
+  </stage>
+
+  <stage id="6" name="Confirm" when="task_exec" enforce="@confirm_cleanup">
+    <prerequisites>Summary provided (Stage 5 complete)</prerequisites>
+    Ask: "Complete & satisfactory?"
+    <if_session>Also ask: "Cleanup temp session files at .tmp/sessions/{id}/?"</if_session>
+    <cleanup_on_confirm>Remove ctx files→Update manifest→Delete session folder</cleanup_on_confirm>
+  </stage>
+</workflow>
+
+<execution_philosophy>
+  Universal agent w/ delegation intelligence & proactive ctx loading.
+
+  **Capabilities**: Code, docs, tests, reviews, analysis, debug, research, bash, file ops
+  **Approach**: Eval delegation criteria FIRST→Fetch ctx→Exec or delegate
+  **Mindset**: Delegate proactively when criteria met - don't attempt complex tasks solo
+</execution_philosophy>
+
+<delegation_rules id="delegation_rules">
+  <evaluate_before_execution required="true">Check delegation conditions BEFORE task exec</evaluate_before_execution>
+
+  <delegate_when>
+    <condition id="scale" trigger="4_plus_files" action="delegate"/>
+    <condition id="expertise" trigger="specialized_knowledge" action="delegate"/>
+    <condition id="review" trigger="multi_component_review" action="delegate"/>
+    <condition id="complexity" trigger="multi_step_dependencies" action="delegate"/>
+    <condition id="perspective" trigger="fresh_eyes_or_alternatives" action="delegate"/>
+    <condition id="simulation" trigger="edge_case_testing" action="delegate"/>
+    <condition id="user_request" trigger="explicit_delegation" action="delegate"/>
+  </delegate_when>
+
+  <execute_directly_when>
+    <condition trigger="single_file_simple_change"/>
+    <condition trigger="straightforward_enhancement"/>
+    <condition trigger="clear_bug_fix"/>
+  </execute_directly_when>
+
+  <specialized_routing>
+    <route to="TaskManager" when="complex_feature_breakdown">
+      <trigger>Complex feature requiring task breakdown OR multi-step dependencies OR user requests task planning</trigger>
+      <context_bundle>
+        Create .tmp/context/{session-id}/bundle.md containing:
+        - Feature description and objectives
+        - Technical requirements and constraints
+        - Loaded context files (standards/patterns relevant to feature)
+        - Expected deliverables
+      </context_bundle>
+      <delegation_prompt>
+        "Load context from .tmp/context/{session-id}/bundle.md.
+         Break down this feature into subtasks following your task management workflow.
+         Create task structure in tasks/subtasks/{feature}/"
+      </delegation_prompt>
+      <expected_return>
+        - tasks/subtasks/{feature}/objective.md (feature index)
+        - tasks/subtasks/{feature}/{seq}-{task}.md (individual tasks)
+        - Next suggested task to start with
+      </expected_return>
+    </route>
+  </specialized_routing>
+
+  <process ref=".opencode/context/core/workflows/task-delegation-basics.md">Full delegation template & process</process>
+</delegation_rules>
+
+<principles>
+  <lean>Concise responses, no over-explain</lean>
+  <adaptive>Conversational for questions, formal for tasks</adaptive>
+  <minimal_overhead>Create session files only when delegating</minimal_overhead>
+  <safe enforce="@critical_context_requirement @critical_rules">Safety first - context loading, approval gates, stop on fail, confirm cleanup</safe>
+  <report_first enforce="@report_first">Never auto-fix - always report & req approval</report_first>
+  <transparent>Explain decisions, show reasoning when helpful</transparent>
+</principles>
+
+<static_context>
+  Context index: .opencode/context/navigation.md
+
+  Load index when discovering contexts by keywords. For common tasks:
+  - Code tasks → .opencode/context/core/standards/code-quality.md
+  - Docs tasks → .opencode/context/core/standards/documentation.md
+  - Tests tasks → .opencode/context/core/standards/test-coverage.md
+  - Review tasks → .opencode/context/core/workflows/code-review.md
+  - Delegation → .opencode/context/core/workflows/task-delegation-basics.md
+
+  Full index includes all contexts with triggers and dependencies.
+  Context files loaded per @critical_context_requirement.
+</static_context>
+
+<constraints enforcement="absolute">
+  These constraints override all other considerations:
+
+  1. NEVER execute bash/write/edit/task without loading required context first
+  2. NEVER skip step 3.1 (LoadContext) for efficiency or speed
+  3. NEVER assume a task is "too simple" to need context
+  4. ALWAYS use Read tool to load context files before execution
+  5. ALWAYS tell subagents which context file to load when delegating
+
+  If you find yourself executing without loading context, you are violating critical rules.
+  Context loading is MANDATORY, not optional.
+</constraints>

+ 4 - 4
README.md

@@ -14,8 +14,8 @@
 📝 **Editable Agents** - Full control over AI behavior  
 📝 **Editable Agents** - Full control over AI behavior  
 👥 **Team-Ready** - Everyone uses the same patterns
 👥 **Team-Ready** - Everyone uses the same patterns
 
 
-**Multi-language:** TypeScript • Python • Go • Rust • C# • Any language*  
-**Model Agnostic:** Claude • GPT • Gemini • Local models
+**Multi-language:** TypeScript • Python • Go • Rust  • C# • Any language*  
+**Model Agnostic:** Claude • GPT • Gemini • MiniMax • Local models
 
 
 
 
 [![GitHub stars](https://img.shields.io/github/stars/darrenhinde/OpenAgentsControl?style=flat-square&logo=github&labelColor=black&color=ffcb47)](https://github.com/darrenhinde/OpenAgentsControl/stargazers)
 [![GitHub stars](https://img.shields.io/github/stars/darrenhinde/OpenAgentsControl?style=flat-square&logo=github&labelColor=black&color=ffcb47)](https://github.com/darrenhinde/OpenAgentsControl/stargazers)
@@ -692,8 +692,8 @@ A: No, but it's highly recommended. Without context, agents write generic code.
 **Q: Can I use this without customization?**  
 **Q: Can I use this without customization?**  
 A: Yes, it works out of the box. But you'll get the most value after adding your patterns (10-15 minutes with `/add-context`).
 A: Yes, it works out of the box. But you'll get the most value after adding your patterns (10-15 minutes with `/add-context`).
 
 
-**Q: What models are supported?**  
-A: Any model from any provider (Claude, GPT, Gemini, local models). No vendor lock-in.
+**Q: What models are supported?**
+A: Any model from any provider (Claude, GPT, Gemini, MiniMax, local models). No vendor lock-in.
 
 
 ### For Teams
 ### For Teams
 
 

+ 4 - 0
env.example

@@ -22,3 +22,7 @@ TELEGRAM_ENABLED=true
 # Gemini API Configuration
 # Gemini API Configuration
 # Get your API key from https://makersuite.google.com/app/apikey
 # Get your API key from https://makersuite.google.com/app/apikey
 GEMINI_API_KEY=your_gemini_api_key_here
 GEMINI_API_KEY=your_gemini_api_key_here
+
+# MiniMax API Configuration
+# Get your API key from https://platform.minimax.io
+MINIMAX_API_KEY=your_minimax_api_key_here

+ 89 - 0
evals/framework/src/sdk/__tests__/minimax-integration.test.ts

@@ -0,0 +1,89 @@
+/**
+ * Integration tests for MiniMax provider support
+ *
+ * Validates the end-to-end integration of MiniMax models
+ * with the eval framework configuration and variant system.
+ */
+
+import { describe, it, expect } from 'vitest';
+import { readFileSync, existsSync } from 'fs';
+import { join } from 'path';
+import { MODEL_BEHAVIORS, getModelBehavior, calculateModelTimeout } from '../model-behaviors.js';
+
+const ROOT_DIR = join(__dirname, '..', '..', '..', '..', '..');
+const PROMPTS_DIR = join(ROOT_DIR, '.opencode', 'prompts', 'core', 'openagent');
+
+describe('MiniMax Integration', () => {
+  describe('environment configuration', () => {
+    it('should have MINIMAX_API_KEY in env.example', () => {
+      const envPath = join(ROOT_DIR, 'env.example');
+      expect(existsSync(envPath)).toBe(true);
+      const content = readFileSync(envPath, 'utf-8');
+      expect(content).toContain('MINIMAX_API_KEY');
+    });
+
+    it('should have MiniMax platform URL in env.example', () => {
+      const envPath = join(ROOT_DIR, 'env.example');
+      const content = readFileSync(envPath, 'utf-8');
+      expect(content).toContain('platform.minimax.io');
+    });
+  });
+
+  describe('model behavior integration', () => {
+    it('should resolve MiniMax-M2.7 via provider prefix', () => {
+      const behavior = getModelBehavior('minimax/MiniMax-M2.7');
+      expect(behavior).not.toBe(MODEL_BEHAVIORS['default']);
+      expect(behavior.typicalResponseTime).toBe(8000);
+    });
+
+    it('should resolve MiniMax-M2.7-highspeed via provider prefix', () => {
+      const behavior = getModelBehavior('minimax/MiniMax-M2.7-highspeed');
+      expect(behavior).not.toBe(MODEL_BEHAVIORS['default']);
+      expect(behavior.typicalResponseTime).toBe(5000);
+    });
+
+    it('should calculate appropriate timeouts for eval tests', () => {
+      const standardTimeout = calculateModelTimeout(30000, 'minimax/MiniMax-M2.7');
+      const highspeedTimeout = calculateModelTimeout(30000, 'minimax/MiniMax-M2.7-highspeed');
+
+      // Both should be reasonable for eval tests
+      expect(standardTimeout).toBeGreaterThanOrEqual(24000);
+      expect(standardTimeout).toBeLessThanOrEqual(120000);
+      expect(highspeedTimeout).toBeGreaterThanOrEqual(15000);
+      expect(highspeedTimeout).toBeLessThanOrEqual(120000);
+    });
+  });
+
+  describe('prompt variant integration', () => {
+    it('should have minimax.md alongside other variants', () => {
+      const variants = ['gpt.md', 'grok.md', 'gemini.md', 'llama.md', 'minimax.md'];
+      for (const variant of variants) {
+        const variantPath = join(PROMPTS_DIR, variant);
+        expect(existsSync(variantPath)).toBe(true);
+      }
+    });
+
+    it('should be documented in the README', () => {
+      const readmePath = join(PROMPTS_DIR, 'README.md');
+      expect(existsSync(readmePath)).toBe(true);
+      const content = readFileSync(readmePath, 'utf-8');
+      expect(content).toContain('minimax');
+      expect(content).toContain('MiniMax');
+    });
+
+    it('should be listed in the capabilities matrix', () => {
+      const readmePath = join(PROMPTS_DIR, 'README.md');
+      const content = readFileSync(readmePath, 'utf-8');
+      expect(content).toContain('`minimax`');
+    });
+  });
+
+  describe('README integration', () => {
+    it('should mention MiniMax in the main project README', () => {
+      const readmePath = join(ROOT_DIR, 'README.md');
+      expect(existsSync(readmePath)).toBe(true);
+      const content = readFileSync(readmePath, 'utf-8');
+      expect(content).toContain('MiniMax');
+    });
+  });
+});

+ 83 - 0
evals/framework/src/sdk/__tests__/minimax-model-behaviors.test.ts

@@ -0,0 +1,83 @@
+/**
+ * Tests for MiniMax model behavior configuration
+ *
+ * Validates that MiniMax models are properly registered in the
+ * model behavior registry and return correct configuration values.
+ */
+
+import { describe, it, expect } from 'vitest';
+import { MODEL_BEHAVIORS, getModelBehavior, calculateModelTimeout } from '../model-behaviors.js';
+
+describe('MiniMax Model Behaviors', () => {
+  describe('MODEL_BEHAVIORS registry', () => {
+    it('should include MiniMax-M2.7 entry', () => {
+      expect(MODEL_BEHAVIORS['MiniMax-M2.7']).toBeDefined();
+    });
+
+    it('should include MiniMax-M2.7-highspeed entry', () => {
+      expect(MODEL_BEHAVIORS['MiniMax-M2.7-highspeed']).toBeDefined();
+    });
+
+    it('should have correct properties for MiniMax-M2.7', () => {
+      const behavior = MODEL_BEHAVIORS['MiniMax-M2.7'];
+      expect(behavior.sendsCompletionText).toBe(true);
+      expect(behavior.mayEndWithToolCalls).toBe(false);
+      expect(behavior.typicalResponseTime).toBe(8000);
+      expect(behavior.toolCompletionGrace).toBe(4000);
+    });
+
+    it('should have correct properties for MiniMax-M2.7-highspeed', () => {
+      const behavior = MODEL_BEHAVIORS['MiniMax-M2.7-highspeed'];
+      expect(behavior.sendsCompletionText).toBe(true);
+      expect(behavior.mayEndWithToolCalls).toBe(false);
+      expect(behavior.typicalResponseTime).toBe(5000);
+      expect(behavior.toolCompletionGrace).toBe(3000);
+    });
+
+    it('should have faster response time for highspeed variant', () => {
+      const standard = MODEL_BEHAVIORS['MiniMax-M2.7'];
+      const highspeed = MODEL_BEHAVIORS['MiniMax-M2.7-highspeed'];
+      expect(highspeed.typicalResponseTime).toBeLessThan(standard.typicalResponseTime);
+    });
+  });
+
+  describe('getModelBehavior()', () => {
+    it('should return exact match for MiniMax-M2.7', () => {
+      const behavior = getModelBehavior('MiniMax-M2.7');
+      expect(behavior).toBe(MODEL_BEHAVIORS['MiniMax-M2.7']);
+    });
+
+    it('should return exact match for MiniMax-M2.7-highspeed', () => {
+      const behavior = getModelBehavior('MiniMax-M2.7-highspeed');
+      expect(behavior).toBe(MODEL_BEHAVIORS['MiniMax-M2.7-highspeed']);
+    });
+
+    it('should return partial match for minimax/MiniMax-M2.7', () => {
+      const behavior = getModelBehavior('minimax/MiniMax-M2.7');
+      expect(behavior.typicalResponseTime).toBe(8000);
+    });
+
+    it('should return partial match for minimax/MiniMax-M2.7-highspeed', () => {
+      const behavior = getModelBehavior('minimax/MiniMax-M2.7-highspeed');
+      expect(behavior.typicalResponseTime).toBe(5000);
+    });
+  });
+
+  describe('calculateModelTimeout()', () => {
+    it('should calculate timeout for MiniMax-M2.7', () => {
+      const timeout = calculateModelTimeout(30000, 'MiniMax-M2.7');
+      expect(timeout).toBeGreaterThanOrEqual(24000); // At least 3x typicalResponseTime
+    });
+
+    it('should calculate shorter timeout for MiniMax-M2.7-highspeed', () => {
+      const timeoutStandard = calculateModelTimeout(30000, 'MiniMax-M2.7');
+      const timeoutHighspeed = calculateModelTimeout(30000, 'MiniMax-M2.7-highspeed');
+      expect(timeoutHighspeed).toBeLessThanOrEqual(timeoutStandard);
+    });
+
+    it('should respect minimum base timeout', () => {
+      const timeout = calculateModelTimeout(60000, 'MiniMax-M2.7');
+      expect(timeout).toBeGreaterThanOrEqual(60000);
+    });
+  });
+});

+ 138 - 0
evals/framework/src/sdk/__tests__/minimax-prompt-variant.test.ts

@@ -0,0 +1,138 @@
+/**
+ * Tests for MiniMax prompt variant
+ *
+ * Validates that the MiniMax prompt variant file exists,
+ * has correct metadata, and follows the variant conventions.
+ */
+
+import { describe, it, expect } from 'vitest';
+import { readFileSync, existsSync } from 'fs';
+import { join } from 'path';
+
+const PROMPTS_DIR = join(__dirname, '..', '..', '..', '..', '..', '.opencode', 'prompts', 'core', 'openagent');
+
+describe('MiniMax Prompt Variant', () => {
+  const variantPath = join(PROMPTS_DIR, 'minimax.md');
+
+  it('should exist as a prompt variant file', () => {
+    expect(existsSync(variantPath)).toBe(true);
+  });
+
+  describe('metadata', () => {
+    let content: string;
+
+    beforeAll(() => {
+      content = readFileSync(variantPath, 'utf-8');
+    });
+
+    it('should have model_family set to minimax', () => {
+      expect(content).toContain('model_family: "minimax"');
+    });
+
+    it('should recommend MiniMax-M2.7 as primary model', () => {
+      expect(content).toContain('minimax/MiniMax-M2.7');
+    });
+
+    it('should recommend MiniMax-M2.7-highspeed as alternative', () => {
+      expect(content).toContain('minimax/MiniMax-M2.7-highspeed');
+    });
+
+    it('should have YAML frontmatter delimiters', () => {
+      const frontmatterStart = content.indexOf('---');
+      const frontmatterEnd = content.indexOf('---', frontmatterStart + 3);
+      expect(frontmatterStart).toBeGreaterThanOrEqual(0);
+      expect(frontmatterEnd).toBeGreaterThan(frontmatterStart);
+    });
+
+    it('should include standard agent configuration', () => {
+      expect(content).toContain('mode: primary');
+      expect(content).toContain('temperature: 0.2');
+    });
+
+    it('should include tool permissions', () => {
+      expect(content).toContain('read: true');
+      expect(content).toContain('write: true');
+      expect(content).toContain('edit: true');
+      expect(content).toContain('bash: true');
+      expect(content).toContain('task: true');
+    });
+  });
+
+  describe('prompt content', () => {
+    let content: string;
+
+    beforeAll(() => {
+      content = readFileSync(variantPath, 'utf-8');
+    });
+
+    it('should include critical context requirement', () => {
+      expect(content).toContain('<critical_context_requirement>');
+    });
+
+    it('should include critical rules', () => {
+      expect(content).toContain('<critical_rules');
+      expect(content).toContain('approval_gate');
+      expect(content).toContain('stop_on_failure');
+      expect(content).toContain('report_first');
+      expect(content).toContain('confirm_cleanup');
+    });
+
+    it('should include workflow stages', () => {
+      expect(content).toContain('name="Analyze"');
+      expect(content).toContain('name="Approve"');
+      expect(content).toContain('name="Execute"');
+      expect(content).toContain('name="Validate"');
+      expect(content).toContain('name="Summarize"');
+      expect(content).toContain('name="Confirm"');
+    });
+
+    it('should include delegation rules', () => {
+      expect(content).toContain('<delegation_rules');
+    });
+
+    it('should include execution priority tiers', () => {
+      expect(content).toContain('<execution_priority>');
+      expect(content).toContain('Safety & Approval Gates');
+      expect(content).toContain('Core Workflow');
+      expect(content).toContain('Optimization');
+    });
+
+    it('should include context loading references', () => {
+      expect(content).toContain('code-quality.md');
+      expect(content).toContain('documentation.md');
+      expect(content).toContain('test-coverage.md');
+    });
+  });
+
+  describe('consistency with other variants', () => {
+    it('should have same structure as gpt.md variant', () => {
+      const gptPath = join(PROMPTS_DIR, 'gpt.md');
+      if (!existsSync(gptPath)) return; // Skip if gpt variant missing
+
+      const minimax = readFileSync(variantPath, 'utf-8');
+      const gpt = readFileSync(gptPath, 'utf-8');
+
+      // Both should have the same core sections
+      const coreSections = [
+        '<critical_context_requirement>',
+        '<critical_rules',
+        '<execution_priority>',
+        '<execution_paths>',
+        '<workflow>',
+        '<delegation_rules',
+        '<principles>',
+        '<static_context>',
+        '<constraints',
+      ];
+
+      for (const section of coreSections) {
+        const gptHas = gpt.includes(section);
+        const minimaxHas = minimax.includes(section);
+        expect(minimaxHas).toBe(gptHas);
+      }
+    });
+  });
+});
+
+// Import beforeAll for the describe blocks
+import { beforeAll } from 'vitest';

+ 12 - 0
evals/framework/src/sdk/model-behaviors.ts

@@ -73,6 +73,18 @@ export const MODEL_BEHAVIORS: Record<string, ModelBehavior> = {
     typicalResponseTime: 6000,
     typicalResponseTime: 6000,
     toolCompletionGrace: 3000,
     toolCompletionGrace: 3000,
   },
   },
+  'MiniMax-M2.7-highspeed': {
+    sendsCompletionText: true,
+    mayEndWithToolCalls: false,
+    typicalResponseTime: 5000,
+    toolCompletionGrace: 3000,
+  },
+  'MiniMax-M2.7': {
+    sendsCompletionText: true,
+    mayEndWithToolCalls: false,
+    typicalResponseTime: 8000,
+    toolCompletionGrace: 4000,
+  },
   // Default for unknown models
   // Default for unknown models
   'default': {
   'default': {
     sendsCompletionText: true,
     sendsCompletionText: true,