@crazy-goat/nexos-provider 1.3.2 → 1.3.3
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 +19 -2
- package/fix-codestral.mjs +22 -0
- package/index.mjs +11 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ Fixes compatibility issues when using Gemini, Claude, and ChatGPT models through
|
|
|
9
9
|
- **Gemini**: appends missing `data: [DONE]` SSE signal (prevents hanging), inlines `$ref` in tool schemas (rejected by Vertex AI), fixes `finish_reason` for tool calls (`stop`→`tool_calls`)
|
|
10
10
|
- **Claude**: converts thinking params to snake_case (`budgetTokens`→`budget_tokens`), fixes `finish_reason` (`end_turn`→`stop`, prevents infinite retry loop), strips `thinking` object when disabled
|
|
11
11
|
- **ChatGPT**: no fixes needed — `reasoningEffort` is handled natively by opencode
|
|
12
|
+
- **Codestral**: sets `strict: false` in tool definitions when `strict` is `null` (Mistral API rejects `null` for this field)
|
|
12
13
|
|
|
13
14
|
## Setup
|
|
14
15
|
|
|
@@ -67,7 +68,7 @@ Add the provider to your `~/.config/opencode/opencode.json`:
|
|
|
67
68
|
|
|
68
69
|
> **Tip:** You can automatically generate the config with all available nexos.ai models using [opencode-nexos-models-config](https://github.com/crazy-goat/opencode-nexos-models-config).
|
|
69
70
|
|
|
70
|
-
> **Warning:** Gemini 3 models (Flash Preview, Pro Preview)
|
|
71
|
+
> **Warning:** Gemini 3 models (Flash Preview, Pro Preview) do not work with tool calling through nexos.ai — see [known-bugs/gemini3-tools](known-bugs/gemini3-tools/) for details.
|
|
71
72
|
|
|
72
73
|
### 3. Use it
|
|
73
74
|
|
|
@@ -112,7 +113,8 @@ opencode → createNexosAI → fetch wrapper → nexos.ai API
|
|
|
112
113
|
│
|
|
113
114
|
├─ fix-gemini.mjs: $ref inlining, finish_reason fix
|
|
114
115
|
├─ fix-claude.mjs: thinking params, end_turn→stop
|
|
115
|
-
|
|
116
|
+
├─ fix-chatgpt.mjs: passthrough (no fixes needed)
|
|
117
|
+
└─ fix-codestral.mjs: strict:null→false in tools
|
|
116
118
|
```
|
|
117
119
|
|
|
118
120
|
## Testing
|
|
@@ -139,6 +141,21 @@ opencode run "what is 2+2?" -m "nexos-ai/Gemini 2.5 Pro" --variant thinking-high
|
|
|
139
141
|
opencode run "what is 2+2?" -m "nexos-ai/GPT 5" --variant high
|
|
140
142
|
```
|
|
141
143
|
|
|
144
|
+
### Automated model check
|
|
145
|
+
|
|
146
|
+
Run `check-models/check-all.mjs` to test all available models:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
node check-models/check-all.mjs
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Test a single model:
|
|
153
|
+
```bash
|
|
154
|
+
node check-models/check-all.mjs "GPT 4.1"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Results are saved to `check-models/checks.md`.
|
|
158
|
+
|
|
142
159
|
## License
|
|
143
160
|
|
|
144
161
|
MIT
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function isCodestralModel(model) {
|
|
2
|
+
return typeof model === "string" && model.toLowerCase().includes("codestral");
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function fixCodestralRequest(body) {
|
|
6
|
+
if (!body.tools?.length) return body;
|
|
7
|
+
return {
|
|
8
|
+
...body,
|
|
9
|
+
tools: body.tools.map((tool) => {
|
|
10
|
+
if (tool.type !== "function" || !tool.function) return tool;
|
|
11
|
+
const fn = { ...tool.function };
|
|
12
|
+
if (fn.strict === null || fn.strict === undefined) {
|
|
13
|
+
fn.strict = false;
|
|
14
|
+
}
|
|
15
|
+
return { ...tool, function: fn };
|
|
16
|
+
}),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function fixCodestralStream(text) {
|
|
21
|
+
return text;
|
|
22
|
+
}
|
package/index.mjs
CHANGED
|
@@ -2,11 +2,13 @@ import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
|
2
2
|
import { isGeminiModel, fixGeminiRequest, fixGeminiThinkingRequest, fixGeminiStream } from "./fix-gemini.mjs";
|
|
3
3
|
import { fixClaudeRequest, fixClaudeStream } from "./fix-claude.mjs";
|
|
4
4
|
import { fixChatGPTRequest, fixChatGPTStream } from "./fix-chatgpt.mjs";
|
|
5
|
+
import { isCodestralModel, fixCodestralRequest, fixCodestralStream } from "./fix-codestral.mjs";
|
|
5
6
|
|
|
6
7
|
function fixStreamChunk(text) {
|
|
7
8
|
text = fixGeminiStream(text);
|
|
8
9
|
text = fixClaudeStream(text);
|
|
9
10
|
text = fixChatGPTStream(text);
|
|
11
|
+
text = fixCodestralStream(text);
|
|
10
12
|
return text;
|
|
11
13
|
}
|
|
12
14
|
|
|
@@ -42,13 +44,21 @@ function createNexosFetch(baseFetch) {
|
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
const gemini = isGeminiModel(requestBody.model);
|
|
47
|
+
const codestral = isCodestralModel(requestBody.model);
|
|
45
48
|
let needsStreamFix = gemini;
|
|
49
|
+
let bodyChanged = false;
|
|
46
50
|
|
|
47
51
|
if (gemini) {
|
|
48
52
|
requestBody = fixGeminiRequest(requestBody);
|
|
49
53
|
const geminiThinking = fixGeminiThinkingRequest(requestBody);
|
|
50
54
|
requestBody = geminiThinking.body;
|
|
51
55
|
if (geminiThinking.hadThinking) needsStreamFix = true;
|
|
56
|
+
bodyChanged = true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (codestral) {
|
|
60
|
+
requestBody = fixCodestralRequest(requestBody);
|
|
61
|
+
bodyChanged = true;
|
|
52
62
|
}
|
|
53
63
|
|
|
54
64
|
const claudeResult = fixClaudeRequest(requestBody);
|
|
@@ -59,7 +69,7 @@ function createNexosFetch(baseFetch) {
|
|
|
59
69
|
requestBody = fixChatGPTRequest(requestBody);
|
|
60
70
|
const chatgptChanged = requestBody !== beforeChatGPT;
|
|
61
71
|
|
|
62
|
-
if (gemini || claudeResult.hadThinking || chatgptChanged) {
|
|
72
|
+
if (gemini || codestral || claudeResult.hadThinking || chatgptChanged) {
|
|
63
73
|
init = { ...init, body: JSON.stringify(requestBody) };
|
|
64
74
|
}
|
|
65
75
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crazy-goat/nexos-provider",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
4
4
|
"description": "Custom AI SDK provider for nexos.ai Gemini models in opencode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.mjs",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"index.mjs",
|
|
12
12
|
"fix-gemini.mjs",
|
|
13
13
|
"fix-claude.mjs",
|
|
14
|
-
"fix-chatgpt.mjs"
|
|
14
|
+
"fix-chatgpt.mjs",
|
|
15
|
+
"fix-codestral.mjs"
|
|
15
16
|
],
|
|
16
17
|
"keywords": [
|
|
17
18
|
"opencode",
|