Skip to content

Commit fa7e6b8

Browse files
committed
fix(opencode): add MiniMax thinking modes
1 parent ea77fa1 commit fa7e6b8

6 files changed

Lines changed: 124 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ All notable changes to this project will be documented in this file.
77
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
88
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
99

10+
## [Unreleased]
11+
12+
### Fixed
13+
14+
- Added model-aware MiniMax thinking options in the OpenCode plugin without fixed token budgets.
15+
16+
### Tests
17+
18+
- Added coverage for MiniMax-M3 adaptive and disabled modes and MiniMax-M2.7 always-on behavior.
19+
1020
## [6.0.1] - 2026-07-22
1121

1222
### Security
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
const fs = require('fs');
2+
const Module = require('module');
3+
const path = require('path');
4+
const ts = require('typescript');
5+
6+
function loadAgentSysPlugin() {
7+
const pluginPath = path.join(__dirname, '../adapters/opencode-plugin/index.ts');
8+
const source = fs.readFileSync(pluginPath, 'utf-8');
9+
const compiled = ts.transpileModule(source, {
10+
compilerOptions: {
11+
module: ts.ModuleKind.CommonJS,
12+
target: ts.ScriptTarget.ES2020
13+
},
14+
fileName: pluginPath
15+
});
16+
const pluginModule = new Module(pluginPath, module);
17+
pluginModule.filename = pluginPath;
18+
pluginModule.paths = module.paths;
19+
pluginModule._compile(compiled.outputText, pluginPath);
20+
return pluginModule.exports.AgentSysPlugin;
21+
}
22+
23+
describe('OpenCode MiniMax thinking configuration', () => {
24+
let chatParams;
25+
26+
beforeAll(async () => {
27+
const plugin = await loadAgentSysPlugin()({ directory: process.cwd() });
28+
chatParams = plugin['chat.params'];
29+
});
30+
31+
it('uses adaptive thinking for MiniMax-M3 with a positive agent budget', async () => {
32+
const output = {};
33+
34+
await chatParams({
35+
agent: 'implementation-agent',
36+
model: { providerID: 'minimax', id: 'MiniMax-M3' }
37+
}, output);
38+
39+
expect(output.options.thinking).toEqual({ type: 'adaptive' });
40+
expect(output.options.thinking).not.toHaveProperty('budgetTokens');
41+
});
42+
43+
it('disables thinking for MiniMax-M3 with a zero agent budget', async () => {
44+
const output = {};
45+
46+
await chatParams({
47+
agent: 'simple-fixer',
48+
model: { providerID: 'minimax', id: 'MiniMax-M3' }
49+
}, output);
50+
51+
expect(output.options.thinking).toEqual({ type: 'disabled' });
52+
expect(output.options.thinking).not.toHaveProperty('budgetTokens');
53+
});
54+
55+
it('preserves the always-on defaults for MiniMax-M2.7', async () => {
56+
const output = { options: { existing: true } };
57+
58+
await chatParams({
59+
agent: 'implementation-agent',
60+
model: { providerID: 'minimax', id: 'MiniMax-M2.7' }
61+
}, output);
62+
63+
expect(output).toEqual({ options: { existing: true } });
64+
expect(output.options).not.toHaveProperty('thinking');
65+
});
66+
});

adapters/opencode-plugin/index.ts

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,26 @@ const AGENT_THINKING_CONFIG: Record<string, { budget: number; description: strin
4949
"skills-enhancer": { budget: 16000, description: "Skill prompt review" },
5050
}
5151

52+
// MiniMax model capabilities do not use fixed thinking token budgets.
53+
function applyMiniMaxThinking(
54+
modelID: string,
55+
budget: number,
56+
output: { options?: Record<string, unknown> }
57+
): void {
58+
const normalizedModelID = (modelID || "").toLowerCase()
59+
60+
if (normalizedModelID === "minimax-m3") {
61+
output.options = output.options || {}
62+
output.options.thinking = {
63+
type: budget > 0 ? "adaptive" : "disabled"
64+
}
65+
return
66+
}
67+
68+
// MiniMax-M2.7 keeps its default always-on thinking behavior.
69+
if (normalizedModelID === "minimax-m2.7") return
70+
}
71+
5272
// Project script patterns for failure detection
5373
const PROJECT_SCRIPT_PATTERNS: RegExp[] = [
5474
/\bnpm\s+test\b/,
@@ -143,25 +163,28 @@ export const AgentSysPlugin: Plugin = async (ctx) => {
143163
// Check if this is one of our agents
144164
const config = AGENT_THINKING_CONFIG[agentName]
145165

146-
if (config && config.budget > 0) {
166+
if (config) {
147167
// Detect provider and apply appropriate thinking config
148168
const providerID = input.model?.providerID || ""
169+
const modelID = input.model?.id || ""
149170

150-
if (providerID.includes("anthropic") || providerID.includes("bedrock")) {
171+
if (providerID.toLowerCase().includes("minimax")) {
172+
applyMiniMaxThinking(modelID, config.budget, output)
173+
} else if (config.budget > 0 && (providerID.includes("anthropic") || providerID.includes("bedrock"))) {
151174
// Anthropic-style thinking
152175
output.options = output.options || {}
153176
output.options.thinking = {
154177
type: "enabled",
155178
budgetTokens: config.budget
156179
}
157-
} else if (providerID.includes("openai") || providerID.includes("azure")) {
180+
} else if (config.budget > 0 && (providerID.includes("openai") || providerID.includes("azure"))) {
158181
// OpenAI-style reasoning
159182
output.options = output.options || {}
160183
const effort = config.budget >= 16000 ? "high" :
161184
config.budget >= 12000 ? "medium" : "low"
162185
output.options.reasoningEffort = effort
163186
output.options.reasoningSummary = "auto"
164-
} else if (providerID.includes("google")) {
187+
} else if (config.budget > 0 && providerID.includes("google")) {
165188
// Google Gemini thinking
166189
output.options = output.options || {}
167190
output.options.thinkingConfig = {

agent-docs/OPENCODE-REFERENCE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,9 @@ OpenCode supports thinking/reasoning across **multiple providers** with differen
513513
| **Google Gemini** | `low`, `high`, `max` | `thinkingConfig: { includeThoughts: true, thinkingBudget: 16000 }` |
514514
| **Amazon Bedrock** | `high`, `max` | `reasoningConfig: { type: "enabled", budgetTokens: 16000 }` |
515515
| **Groq** | `none`, `low`, `medium`, `high` | `includeThoughts: true, thinkingLevel: "high"` |
516+
| **MiniMax** | `adaptive`, `disabled` (MiniMax-M3); always on (MiniMax-M2.7) | `thinking: { type: "adaptive" }` or `thinking: { type: "disabled" }`; no fixed token budget |
517+
518+
The AgentSys hook selects `adaptive` for MiniMax-M3 agents with a positive thinking tier and `disabled` for zero-budget agents. It leaves MiniMax-M2.7 options unchanged because that model's thinking mode is always on.
516519

517520
### Configuring Extended Thinking
518521

package-lock.json

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@
8181
"node": ">=18.0.0"
8282
},
8383
"devDependencies": {
84-
"jest": "^29.7.0"
84+
"jest": "^29.7.0",
85+
"typescript": "^5.9.2"
8586
},
8687
"workspaces": [
8788
"lib"

0 commit comments

Comments
 (0)