@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 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) are currently unavailable tool calling through nexos.ai does not work for these models.
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
- └─ fix-chatgpt.mjs: passthrough (no fixes needed)
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.2",
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",