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 +3 -1
- package/package.json +1 -1
- package/proxy/proxy.js +14 -11
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
|
|
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
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
|
|
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
|
-
|
|
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
|
|