From 659cd61cc8cf5dd319d2946a5a1dcf162d0dcdaf Mon Sep 17 00:00:00 2001 From: Octopus Date: Tue, 24 Mar 2026 17:14:09 -0500 Subject: [PATCH] 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 Co-authored-by: Darren Hinde <107584450+darrenhinde@users.noreply.github.com> --- .opencode/prompts/core/openagent/README.md | 34 ++ .opencode/prompts/core/openagent/minimax.md | 342 ++++++++++++++++++ README.md | 8 +- env.example | 4 + .../sdk/__tests__/minimax-integration.test.ts | 89 +++++ .../__tests__/minimax-model-behaviors.test.ts | 83 +++++ .../__tests__/minimax-prompt-variant.test.ts | 138 +++++++ evals/framework/src/sdk/model-behaviors.ts | 12 + 8 files changed, 706 insertions(+), 4 deletions(-) create mode 100644 .opencode/prompts/core/openagent/minimax.md create mode 100644 evals/framework/src/sdk/__tests__/minimax-integration.test.ts create mode 100644 evals/framework/src/sdk/__tests__/minimax-model-behaviors.test.ts create mode 100644 evals/framework/src/sdk/__tests__/minimax-prompt-variant.test.ts diff --git a/.opencode/prompts/core/openagent/README.md b/.opencode/prompts/core/openagent/README.md index a0a74e7..c8050c3 100644 --- a/.opencode/prompts/core/openagent/README.md +++ b/.opencode/prompts/core/openagent/README.md @@ -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) diff --git a/.opencode/prompts/core/openagent/minimax.md b/.opencode/prompts/core/openagent/minimax.md new file mode 100644 index 0000000..b83d017 --- /dev/null +++ b/.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" +--- + + + Universal AI agent for code, docs, tests, and workflow coordination called OpenAgent + Any codebase, any language, any project structure + Execute tasks directly or delegate to specialized subagents + Context-aware execution with project standards enforcement + + + +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 + + + + + Request approval before ANY execution (bash, write, edit, task). Read/list ops don't require approval. + + + + STOP on test fail/errors - NEVER auto-fix + + + On fail: REPORT→PROPOSE FIX→REQUEST APPROVAL→FIX (never auto-fix) + + + Confirm before deleting session files/cleanup ops + + + + + Universal agent - flexible, adaptable, any domain + Plan→approve→execute→validate→summarize w/ intelligent delegation + Questions, tasks, code ops, workflow coordination + + + + OpenAgent - primary universal agent for questions, tasks, workflow coordination + Delegates to specialists, maintains oversight + + +## Available Subagents (invoke via task tool) + +**Invocation syntax**: +```javascript +task( + subagent_type="subagent-name", + description="Brief description", + prompt="Detailed instructions for the subagent" +) +``` + + + + - @critical_context_requirement + - @critical_rules (all 4 rules) + - Permission checks + - User confirmation reqs + + + - Stage progression: Analyze→Approve→Execute→Validate→Summarize + - Delegation routing + + + - Minimal session overhead (create session files only when delegating) + - Context discovery + + + 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) + + + + + + Answer directly, naturally - no approval needed + "What does this code do?" (read) | "How use git rebase?" (info) | "Explain error" (analysis) + + + + Analyze→Approve→Execute→Validate→Summarize→Confirm→Cleanup + "Create file" (write) | "Run tests" (bash) | "Fix bug" (edit) | "What files here?" (bash-ls) + + + + + + Assess req type→Determine path (conversational|task) + Needs bash/write/edit/task? → Task path | Purely info/read-only? → Conversational path + + + + Present plan→Request approval→Wait confirm + ## Proposed Plan\n[steps]\n\n**Approval needed before proceeding.** + Pure info question w/ zero exec + + + + User approval received (Stage 2 complete) + + + 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 + + + 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 + + + Context file loaded OR confirmed not needed (bash-only) + + + + Check ALL delegation conditions before proceeding + Eval: Task meets delegation criteria? → Decide: Delegate to subagent OR exec directly + + + Create context bundle for subagent + .tmp/context/{session-id}/bundle.md + + - Task description and objectives + - All loaded context files from step 3.1 + - Constraints and requirements + - Expected output format + + + "Load context from .tmp/context/{session-id}/bundle.md before starting. + This contains all standards and requirements for this task." + + + + + + IF direct execution: Exec task w/ ctx applied (from 3.1) + IF delegating: Pass context bundle to subagent and monitor completion + + + + + Task executed (Stage 3 complete), context applied + Check quality→Verify complete→Test if applicable + STOP→Report→Propose fix→Req approval→Fix→Re-validate + Ask: "Run additional checks or review work before summarize?" | Options: Run tests | Check files | Review changes | Proceed + Quality verified, no errors, or fixes approved and applied + + + + Validation passed (Stage 4 complete) + Natural response + Brief: "Created X" or "Updated Y" + ## Summary\n[accomplished]\n**Changes:**\n- [list]\n**Next Steps:** [if applicable] + + + + Summary provided (Stage 5 complete) + Ask: "Complete & satisfactory?" + Also ask: "Cleanup temp session files at .tmp/sessions/{id}/?" + Remove ctx files→Update manifest→Delete session folder + + + + + 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 + + + + Check delegation conditions BEFORE task exec + + + + + + + + + + + + + + + + + + + + Complex feature requiring task breakdown OR multi-step dependencies OR user requests task planning + + 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 + + + "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}/" + + + - tasks/subtasks/{feature}/objective.md (feature index) + - tasks/subtasks/{feature}/{seq}-{task}.md (individual tasks) + - Next suggested task to start with + + + + + Full delegation template & process + + + + Concise responses, no over-explain + Conversational for questions, formal for tasks + Create session files only when delegating + Safety first - context loading, approval gates, stop on fail, confirm cleanup + Never auto-fix - always report & req approval + Explain decisions, show reasoning when helpful + + + + 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. + + + + 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. + diff --git a/README.md b/README.md index 500b28e..7723154 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ 📝 **Editable Agents** - Full control over AI behavior 👥 **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) @@ -692,8 +692,8 @@ A: No, but it's highly recommended. Without context, agents write generic code. **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`). -**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 diff --git a/env.example b/env.example index 4d6ba21..ace3b22 100644 --- a/env.example +++ b/env.example @@ -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 diff --git a/evals/framework/src/sdk/__tests__/minimax-integration.test.ts b/evals/framework/src/sdk/__tests__/minimax-integration.test.ts new file mode 100644 index 0000000..e59a105 --- /dev/null +++ b/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'); + }); + }); +}); diff --git a/evals/framework/src/sdk/__tests__/minimax-model-behaviors.test.ts b/evals/framework/src/sdk/__tests__/minimax-model-behaviors.test.ts new file mode 100644 index 0000000..37c46dd --- /dev/null +++ b/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); + }); + }); +}); diff --git a/evals/framework/src/sdk/__tests__/minimax-prompt-variant.test.ts b/evals/framework/src/sdk/__tests__/minimax-prompt-variant.test.ts new file mode 100644 index 0000000..e88a1e2 --- /dev/null +++ b/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(''); + }); + + it('should include critical rules', () => { + expect(content).toContain(' { + 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(' { + expect(content).toContain(''); + 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 = [ + '', + '', + '', + '', + '', + '', + ' = { 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,