opencode-thinking-fix 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -163,6 +163,8 @@ Then point OpenCode at it — in your `opencode.json`:
163
163
 
164
164
  Zero npm dependencies. It uses `http`, `https`, and `url` — nothing else.
165
165
 
166
+ **Interleaved thinking support:** GLM-5+ and MiniMax-M3 emit reasoning AFTER content in the same turn (interleaved thinking between tool calls). The proxy accumulates ALL reasoning across an entire assistant turn and flushes only on `finish_reason` — never on `delta.content` arrival. This prevents split/lost reasoning blocks.
167
+
166
168
  **Kimi K2.7 Code and OpenCode Go need this.** The rest of the models benefit from it but do not technically require it.
167
169
 
168
170
  ---
@@ -202,7 +204,7 @@ The plugin is the safety net. If the proxy goes down, the plugin still injects e
202
204
  | **Kimi K2.7 Code** | **Not enough alone** | **Required** | Needs real text |
203
205
  | GLM-5.x / Zhipu | Yes | Nice to have | Accepts `""` |
204
206
  | MiMo V2.5 / MiniMax | Yes | Nice to have | Accepts `""` (default mode embeds `<think>` in `content`) |
205
- | **MiniMax-M3** | Yes | **Recommended** | `reasoning_details[]` array format; ~40% quality loss if stripped |
207
+ | **MiniMax-M3** | Yes | **Recommended** | `reasoning_details[]` array; ~40% quality loss if stripped. Proxy injects `reasoning_split:true` to keep thinking separate from content. |
206
208
  | OpenCode Go | Yes | Required | Uses `reasoning` field |
207
209
  | Qwen, GPT, Claude, Gemini, Llama, Mistral | No | No | No reasoning_content |
208
210
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-thinking-fix",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Fix DeepSeek/Kimi/GLM/MiMo reasoning_content 400 errors in OpenCode. Plugin + proxy + watchdog.",
5
5
  "license": "MIT",
6
6
  "author": "tbosancheros39",
package/proxy/proxy.js CHANGED
@@ -172,7 +172,7 @@ function createStreamParser(sessionId, onComplete) {
172
172
  const delta = parsed.choices?.[0]?.delta
173
173
  if (!delta) continue
174
174
 
175
- // reasoning_content delta (DeepSeek/Kimi/GLM native)
175
+ // reasoning_content delta (DeepSeek/Kimi/GLM/MiniMax)
176
176
  if (typeof delta.reasoning_content === 'string') {
177
177
  reasoningBuffer += delta.reasoning_content
178
178
  inReasoning = true
@@ -194,16 +194,9 @@ function createStreamParser(sessionId, onComplete) {
194
194
  inReasoning = true
195
195
  }
196
196
 
197
- // When content starts after reasoning, the reasoning block is done
198
- if (typeof delta.content === 'string' && delta.content && inReasoning) {
199
- if (reasoningBuffer) {
200
- onComplete(assistantIndex, reasoningBuffer)
201
- reasoningBuffer = ''
202
- inReasoning = false
203
- }
204
- }
205
-
206
197
  // finish_reason means the assistant turn is complete
198
+ // Only flush here — NOT on content appearance (interleaved thinking
199
+ // emits reasoning AFTER content on GLM-5+ and MiniMax-M3)
207
200
  if (parsed.choices?.[0]?.finish_reason) {
208
201
  if (reasoningBuffer) {
209
202
  onComplete(assistantIndex, reasoningBuffer)
@@ -264,7 +257,17 @@ const server = http.createServer((req, res) => {
264
257
  // Patch request body if this is a reasoning provider
265
258
  let bodyToSend = rawBody
266
259
  if (shouldPatch && rawBody.length > 0) {
267
- const patched = patchRequestBody(rawBody.toString('utf8'), sessionId)
260
+ // Inject reasoning_split for MiniMax models (avoids <think> tags in content)
261
+ const isMiniMax = modelName.toLowerCase().startsWith('minimax') || modelName.toLowerCase().startsWith('mimo')
262
+ let bodyStr = rawBody.toString('utf8')
263
+ if (isMiniMax) {
264
+ try {
265
+ const bj = JSON.parse(bodyStr)
266
+ bj.reasoning_split = true
267
+ bodyStr = JSON.stringify(bj)
268
+ } catch { /* pass */ }
269
+ }
270
+ const patched = patchRequestBody(bodyStr, sessionId)
268
271
  bodyToSend = Buffer.from(patched, 'utf8')
269
272
  }
270
273