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>
This commit is contained in:
Octopus 2026-03-24 17:14:09 -05:00 committed by GitHub
parent 2fa39e97bd
commit 659cd61cc8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 706 additions and 4 deletions

View file

@ -29,6 +29,7 @@ open ../results/index.html
| `gemini` | Gemini | ✅ | ✅ | ✅ | ✅ | ✅ | 7/7 (100%) | ✅ Stable |
| `grok` | Grok | ✅ | ✅ | ✅ | ✅ | ✅ | 7/7 (100%) | ✅ Stable |
| `llama` | Llama/OSS | ✅ | ✅ | ✅ | ✅ | ✅ | 7/7 (100%) | ✅ Stable |
| `minimax` | MiniMax | - | - | - | - | - | - | 🚧 Needs Testing |
**Legend:**
- ✅ 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
### Quick Smoke Test (1 test, ~30s)

View file

@ -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>

View file

@ -15,7 +15,7 @@
👥 **Team-Ready** - Everyone uses the same patterns
**Multi-language:** TypeScript • Python • Go • Rust • C# • Any language*
**Model Agnostic:** Claude • GPT • Gemini • Local models
**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)
@ -693,7 +693,7 @@ A: No, but it's highly recommended. Without context, agents write generic code.
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.
A: Any model from any provider (Claude, GPT, Gemini, MiniMax, local models). No vendor lock-in.
### For Teams

View file

@ -22,3 +22,7 @@ TELEGRAM_ENABLED=true
# Gemini API Configuration
# Get your API key from https://makersuite.google.com/app/apikey
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

View file

@ -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');
});
});
});

View file

@ -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);
});
});
});

View file

@ -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';

View file

@ -73,6 +73,18 @@ export const MODEL_BEHAVIORS: Record<string, ModelBehavior> = {
typicalResponseTime: 6000,
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': {
sendsCompletionText: true,