@pentoshi/clai 2.0.52 → 2.0.54
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 +6 -3
- package/dist/agent/runner.js +100 -69
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/tool-call-parser.js +6 -1
- package/dist/agent/tool-call-parser.js.map +1 -1
- package/dist/commands/providers.js +2 -0
- package/dist/commands/providers.js.map +1 -1
- package/dist/commands/update.js +1 -1
- package/dist/llm/capabilities.js +5 -2
- package/dist/llm/capabilities.js.map +1 -1
- package/dist/llm/gemini.js +74 -22
- package/dist/llm/gemini.js.map +1 -1
- package/dist/llm/groq.d.ts +1 -0
- package/dist/llm/groq.js +14 -0
- package/dist/llm/groq.js.map +1 -1
- package/dist/llm/http.d.ts +10 -2
- package/dist/llm/http.js +107 -45
- package/dist/llm/http.js.map +1 -1
- package/dist/llm/nvidia.js +5 -1
- package/dist/llm/nvidia.js.map +1 -1
- package/dist/llm/provider.js +7 -1
- package/dist/llm/provider.js.map +1 -1
- package/dist/llm/qwen-cloud.d.ts +2 -0
- package/dist/llm/qwen-cloud.js +81 -0
- package/dist/llm/qwen-cloud.js.map +1 -0
- package/dist/llm/router.js +9 -3
- package/dist/llm/router.js.map +1 -1
- package/dist/prompts/index.d.ts +6 -0
- package/dist/prompts/index.js +49 -0
- package/dist/prompts/index.js.map +1 -1
- package/dist/repl/slash-commands.js +7 -0
- package/dist/repl/slash-commands.js.map +1 -1
- package/dist/repl.js +35 -34
- package/dist/repl.js.map +1 -1
- package/dist/store/config.js +1 -0
- package/dist/store/config.js.map +1 -1
- package/dist/tui/App.js +126 -71
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/hooks/useAgentRunner.d.ts +3 -1
- package/dist/tui/hooks/useAgentRunner.js +8 -3
- package/dist/tui/hooks/useAgentRunner.js.map +1 -1
- package/dist/types.d.ts +8 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/dist/llm/gemini.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { defaultModels, } from "./provider.js";
|
|
2
|
-
import { readJson, readStreamLines } from "./http.js";
|
|
2
|
+
import { ProviderError, readJson, readStreamLines } from "./http.js";
|
|
3
3
|
function geminiContents(messages) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
const contents = [];
|
|
5
|
+
for (const message of messages) {
|
|
6
|
+
if (message.role === "system")
|
|
7
|
+
continue;
|
|
7
8
|
const role = message.role === "assistant" ? "model" : "user";
|
|
8
9
|
const parts = [];
|
|
9
|
-
if (message.content)
|
|
10
|
+
if (message.content.trim())
|
|
10
11
|
parts.push({ text: message.content });
|
|
11
12
|
if (role === "user" && message.images) {
|
|
12
13
|
for (const img of message.images) {
|
|
@@ -15,44 +16,87 @@ function geminiContents(messages) {
|
|
|
15
16
|
});
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
|
-
//
|
|
19
|
+
// Never serialize an empty content part. Apart from being meaningless,
|
|
20
|
+
// Gemini can subsequently return empty candidates after an empty `model`
|
|
21
|
+
// turn. If a caller omitted an assistant turn, merge the adjacent user
|
|
22
|
+
// instructions instead to retain Gemini's alternating-role invariant.
|
|
19
23
|
if (parts.length === 0)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
continue;
|
|
25
|
+
const previous = contents.at(-1);
|
|
26
|
+
if (previous?.role === role) {
|
|
27
|
+
previous.parts.push(...parts);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
contents.push({ role, parts });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return contents;
|
|
23
34
|
}
|
|
24
35
|
function systemInstruction(messages) {
|
|
25
36
|
const system = messages.find((message) => message.role === "system");
|
|
26
37
|
return system ? { parts: [{ text: system.content }] } : undefined;
|
|
27
38
|
}
|
|
28
|
-
function
|
|
29
|
-
return /gemini-(?:
|
|
39
|
+
function isGemini3Model(model) {
|
|
40
|
+
return /gemini-3(?:[.-]|$)/i.test(model);
|
|
30
41
|
}
|
|
31
|
-
function
|
|
32
|
-
if (!reasoning
|
|
42
|
+
function geminiThinkingConfig(reasoning, model) {
|
|
43
|
+
if (!reasoning)
|
|
33
44
|
return undefined;
|
|
34
|
-
if (
|
|
45
|
+
if (isGemini3Model(model)) {
|
|
46
|
+
// Gemini 3 models use `thinkingLevel`, not Gemini 2.5's token budget.
|
|
47
|
+
// Flash-Lite supports `minimal`, which is the closest available recovery
|
|
48
|
+
// mode when the runner needs a visible answer instead of a long thought.
|
|
49
|
+
// 3.1 Pro does not support `minimal`, so `low` is its least costly mode.
|
|
50
|
+
const effort = reasoning?.effort ?? "medium";
|
|
51
|
+
const wantsMinimal = !reasoning?.enabled || effort === "none" || effort === "minimal";
|
|
52
|
+
const isPro = /gemini-3(?:\.\d)?-pro/i.test(model);
|
|
53
|
+
const thinkingLevel = wantsMinimal
|
|
54
|
+
? isPro
|
|
55
|
+
? "low"
|
|
56
|
+
: "minimal"
|
|
57
|
+
: effort === "low"
|
|
58
|
+
? "low"
|
|
59
|
+
: effort === "high" || effort === "xhigh"
|
|
60
|
+
? "high"
|
|
61
|
+
: "medium";
|
|
62
|
+
return {
|
|
63
|
+
thinkingLevel,
|
|
64
|
+
// On a recovery retry, keep Gemini's minimal internal reasoning but do
|
|
65
|
+
// not stream thought summaries back as an apparent empty completion.
|
|
66
|
+
...(reasoning?.enabled ? { includeThoughts: true } : {}),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (!/gemini-2\.5/i.test(model))
|
|
35
70
|
return undefined;
|
|
71
|
+
if (!reasoning?.enabled) {
|
|
72
|
+
// Flash and Flash-Lite support an explicit zero budget. Gemini 2.5 Pro
|
|
73
|
+
// cannot disable thinking, so omit the control rather than send an
|
|
74
|
+
// invalid value.
|
|
75
|
+
return /gemini-2\.5-(?:flash|flash-lite)/i.test(model)
|
|
76
|
+
? { thinkingBudget: 0 }
|
|
77
|
+
: undefined;
|
|
78
|
+
}
|
|
36
79
|
switch (reasoning.effort) {
|
|
37
80
|
case "low":
|
|
38
|
-
return 1_024;
|
|
81
|
+
return { thinkingBudget: 1_024, includeThoughts: true };
|
|
39
82
|
case "high":
|
|
40
|
-
|
|
83
|
+
case "xhigh":
|
|
84
|
+
return { thinkingBudget: 16_384, includeThoughts: true };
|
|
41
85
|
default:
|
|
42
|
-
return 4_096;
|
|
86
|
+
return { thinkingBudget: 4_096, includeThoughts: true };
|
|
43
87
|
}
|
|
44
88
|
}
|
|
45
89
|
export function geminiBody(request) {
|
|
46
90
|
const model = request.model ?? defaultModels.gemini;
|
|
47
|
-
const
|
|
48
|
-
const defaultMaxTokens =
|
|
91
|
+
const thinkingConfig = geminiThinkingConfig(request.thinking, model);
|
|
92
|
+
const defaultMaxTokens = request.thinking?.enabled ? 8_192 : 4_096;
|
|
49
93
|
const body = {
|
|
50
94
|
contents: geminiContents(request.messages),
|
|
51
95
|
generationConfig: {
|
|
52
96
|
temperature: request.temperature ?? 0.2,
|
|
53
97
|
maxOutputTokens: request.maxTokens ?? defaultMaxTokens,
|
|
54
|
-
...(
|
|
55
|
-
? { thinkingConfig
|
|
98
|
+
...(thinkingConfig !== undefined
|
|
99
|
+
? { thinkingConfig }
|
|
56
100
|
: {}),
|
|
57
101
|
},
|
|
58
102
|
};
|
|
@@ -109,7 +153,7 @@ export const geminiProvider = {
|
|
|
109
153
|
.join("")
|
|
110
154
|
.trim();
|
|
111
155
|
if (!text) {
|
|
112
|
-
throw new
|
|
156
|
+
throw new ProviderError("Gemini completed without a visible answer.");
|
|
113
157
|
}
|
|
114
158
|
const final = thought ? `<think>${thought}</think>${text}` : text;
|
|
115
159
|
return { text: final, provider: "gemini", model };
|
|
@@ -131,6 +175,7 @@ export const geminiProvider = {
|
|
|
131
175
|
throw new Error("Gemini returned no stream body");
|
|
132
176
|
}
|
|
133
177
|
let full = "";
|
|
178
|
+
let visible = "";
|
|
134
179
|
let inThought = false;
|
|
135
180
|
const enterThought = () => {
|
|
136
181
|
if (inThought)
|
|
@@ -155,6 +200,9 @@ export const geminiProvider = {
|
|
|
155
200
|
const payload = trimmed.slice(5).trim();
|
|
156
201
|
if (payload === "[DONE]") {
|
|
157
202
|
exitThought();
|
|
203
|
+
if (!visible.trim()) {
|
|
204
|
+
throw new ProviderError("Gemini completed without a visible answer.");
|
|
205
|
+
}
|
|
158
206
|
return { text: full, provider: "gemini", model };
|
|
159
207
|
}
|
|
160
208
|
try {
|
|
@@ -171,6 +219,7 @@ export const geminiProvider = {
|
|
|
171
219
|
else {
|
|
172
220
|
if (inThought)
|
|
173
221
|
exitThought();
|
|
222
|
+
visible += part.text;
|
|
174
223
|
full += part.text;
|
|
175
224
|
onToken(part.text);
|
|
176
225
|
}
|
|
@@ -181,6 +230,9 @@ export const geminiProvider = {
|
|
|
181
230
|
}
|
|
182
231
|
}
|
|
183
232
|
exitThought();
|
|
233
|
+
if (!visible.trim()) {
|
|
234
|
+
throw new ProviderError("Gemini completed without a visible answer.");
|
|
235
|
+
}
|
|
184
236
|
return { text: full, provider: "gemini", model };
|
|
185
237
|
},
|
|
186
238
|
};
|
package/dist/llm/gemini.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/llm/gemini.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,aAAa,GAGd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/llm/gemini.ts"],"names":[],"mappings":"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"}
|
package/dist/llm/groq.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type LlmProvider } from "./provider.js";
|
|
2
2
|
export declare const groqFallbackModels: string[];
|
|
3
|
+
export declare function groqInputTokenBudget(model: string): number | undefined;
|
|
3
4
|
export declare function groqMaxTokens(model: string, requested: number | undefined): number | undefined;
|
|
4
5
|
export declare const groqProvider: LlmProvider;
|
package/dist/llm/groq.js
CHANGED
|
@@ -12,6 +12,20 @@ export const groqFallbackModels = [
|
|
|
12
12
|
"groq/compound-mini",
|
|
13
13
|
"groq/compound",
|
|
14
14
|
];
|
|
15
|
+
/**
|
|
16
|
+
* Conservative input budgets for Groq models whose free-tier TPM limit is
|
|
17
|
+
* smaller than clai's normal agent prompt. Leave room for the current user
|
|
18
|
+
* message and protocol overhead instead of treating the published TPM number
|
|
19
|
+
* as usable prompt space.
|
|
20
|
+
*/
|
|
21
|
+
const groqInputTokenBudgets = [
|
|
22
|
+
{ pattern: /qwen\/qwen3-32b/i, tokens: 5_500 },
|
|
23
|
+
{ pattern: /openai\/gpt-oss-20b/i, tokens: 7_500 },
|
|
24
|
+
];
|
|
25
|
+
export function groqInputTokenBudget(model) {
|
|
26
|
+
return groqInputTokenBudgets.find(({ pattern }) => pattern.test(model))
|
|
27
|
+
?.tokens;
|
|
28
|
+
}
|
|
15
29
|
let cachedModels = null;
|
|
16
30
|
let lastFetchTime = 0;
|
|
17
31
|
const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour cache TTL
|
package/dist/llm/groq.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"groq.js","sourceRoot":"","sources":["../../src/llm/groq.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"groq.js","sourceRoot":"","sources":["../../src/llm/groq.ts"],"names":[],"mappings":"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"}
|
package/dist/llm/http.d.ts
CHANGED
|
@@ -6,9 +6,11 @@ export declare class ProviderError extends Error {
|
|
|
6
6
|
constructor(message: string, status?: number | undefined, body?: string | undefined, retryAfterSeconds?: number | undefined);
|
|
7
7
|
}
|
|
8
8
|
export declare function readJson<T>(response: Response): Promise<T>;
|
|
9
|
+
/** Default no-byte watchdog for provider streams. */
|
|
10
|
+
export declare const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 30000;
|
|
9
11
|
/**
|
|
10
12
|
* Shared SSE/JSONL stream reader. Wraps a fetch response body in:
|
|
11
|
-
* - an idle watchdog (default
|
|
13
|
+
* - an idle watchdog (default 30s, configurable per call) that aborts
|
|
12
14
|
* when no bytes arrive,
|
|
13
15
|
* - a hard total-byte cap (default 16MB) so a runaway provider can't
|
|
14
16
|
* grow our memory unbounded,
|
|
@@ -71,8 +73,14 @@ export declare function openAiCompatibleStream(options: {
|
|
|
71
73
|
onToken: (token: string) => void;
|
|
72
74
|
reasoning?: ReasoningPreference | undefined;
|
|
73
75
|
reasoningStyle?: ReasoningStyle | undefined;
|
|
74
|
-
/** Abort a stream that produces no bytes for this long. Default
|
|
76
|
+
/** Abort a stream that produces no bytes for this long. Default 30s. */
|
|
75
77
|
idleTimeoutMs?: number | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* Allow a slower cold start before the first SSE byte. Once streaming has
|
|
80
|
+
* begun, `idleTimeoutMs` takes over so a wedged connection still aborts
|
|
81
|
+
* promptly. Defaults to the regular idle timeout.
|
|
82
|
+
*/
|
|
83
|
+
initialIdleTimeoutMs?: number | undefined;
|
|
76
84
|
}): Promise<string>;
|
|
77
85
|
export declare function openAiCompatiblePing(baseUrl: string, apiKey: string, headers?: Record<string, string> | undefined): Promise<void>;
|
|
78
86
|
export {};
|
package/dist/llm/http.js
CHANGED
|
@@ -49,7 +49,7 @@ function statusCodeHint(status) {
|
|
|
49
49
|
return " — the provider rejected the request body (model name or parameter mismatch)";
|
|
50
50
|
}
|
|
51
51
|
if (status === 413) {
|
|
52
|
-
return " — request
|
|
52
|
+
return " — request exceeded the provider input limit; retry with a compact prompt or pick another model";
|
|
53
53
|
}
|
|
54
54
|
if (status >= 500 && status < 600) {
|
|
55
55
|
return " — upstream provider error; try again or switch with `/provider`";
|
|
@@ -159,10 +159,51 @@ async function readBodyCapped(response, maxBytes) {
|
|
|
159
159
|
}
|
|
160
160
|
return collected;
|
|
161
161
|
}
|
|
162
|
+
/** Default no-byte watchdog for provider streams. */
|
|
163
|
+
export const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 30_000;
|
|
164
|
+
/**
|
|
165
|
+
* Read one chunk without allowing a wedged ReadableStream implementation to
|
|
166
|
+
* hide a caller abort. `reader.cancel()` is best-effort: some sockets do not
|
|
167
|
+
* settle an already-pending `read()` promptly, so the abort signal also races
|
|
168
|
+
* the read and rejects the awaiting request immediately.
|
|
169
|
+
*/
|
|
170
|
+
function readWithAbort(reader, signal) {
|
|
171
|
+
if (signal.aborted) {
|
|
172
|
+
return Promise.reject(signal.reason ?? new Error("Stream aborted"));
|
|
173
|
+
}
|
|
174
|
+
return new Promise((resolve, reject) => {
|
|
175
|
+
let settled = false;
|
|
176
|
+
const cleanup = () => signal.removeEventListener("abort", abort);
|
|
177
|
+
const succeed = (value) => {
|
|
178
|
+
if (settled)
|
|
179
|
+
return;
|
|
180
|
+
settled = true;
|
|
181
|
+
cleanup();
|
|
182
|
+
resolve(value);
|
|
183
|
+
};
|
|
184
|
+
const fail = (error) => {
|
|
185
|
+
if (settled)
|
|
186
|
+
return;
|
|
187
|
+
settled = true;
|
|
188
|
+
cleanup();
|
|
189
|
+
reject(error);
|
|
190
|
+
};
|
|
191
|
+
const abort = () => {
|
|
192
|
+
fail(signal.reason ?? new Error("Stream aborted"));
|
|
193
|
+
};
|
|
194
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
195
|
+
try {
|
|
196
|
+
void reader.read().then(succeed, fail);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
fail(error);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
162
203
|
export async function* readStreamLines(response, options = {}) {
|
|
163
204
|
if (!response.body)
|
|
164
205
|
return;
|
|
165
|
-
const idleTimeoutMs = options.idleTimeoutMs ??
|
|
206
|
+
const idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS;
|
|
166
207
|
const maxBytes = options.maxBytes ?? 16 * 1024 * 1024;
|
|
167
208
|
const idleController = new AbortController();
|
|
168
209
|
let idleTimer;
|
|
@@ -176,7 +217,7 @@ export async function* readStreamLines(response, options = {}) {
|
|
|
176
217
|
}, idleTimeoutMs);
|
|
177
218
|
};
|
|
178
219
|
resetIdleTimer();
|
|
179
|
-
const onCallerAbort = () => idleController.abort();
|
|
220
|
+
const onCallerAbort = () => idleController.abort(options.signal?.reason);
|
|
180
221
|
options.signal?.addEventListener("abort", onCallerAbort, { once: true });
|
|
181
222
|
// If either signal is already aborted, bail before starting the loop.
|
|
182
223
|
if (idleController.signal.aborted) {
|
|
@@ -205,7 +246,17 @@ export async function* readStreamLines(response, options = {}) {
|
|
|
205
246
|
}
|
|
206
247
|
break;
|
|
207
248
|
}
|
|
208
|
-
|
|
249
|
+
let readResult;
|
|
250
|
+
try {
|
|
251
|
+
readResult = await readWithAbort(reader, idleController.signal);
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
if (idleFired) {
|
|
255
|
+
throw new ProviderError(`Provider stream stalled — no data for ${Math.round(idleTimeoutMs / 1000)}s.`);
|
|
256
|
+
}
|
|
257
|
+
throw error;
|
|
258
|
+
}
|
|
259
|
+
const { done, value } = readResult;
|
|
209
260
|
if (done) {
|
|
210
261
|
if (idleFired) {
|
|
211
262
|
throw new ProviderError(`Provider stream stalled — no data for ${Math.round(idleTimeoutMs / 1000)}s.`);
|
|
@@ -234,12 +285,9 @@ export async function* readStreamLines(response, options = {}) {
|
|
|
234
285
|
clearTimeout(idleTimer);
|
|
235
286
|
options.signal?.removeEventListener("abort", onCallerAbort);
|
|
236
287
|
idleController.signal.removeEventListener("abort", cancelReaderOnAbort);
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
catch {
|
|
241
|
-
// best-effort
|
|
242
|
-
}
|
|
288
|
+
// Do not await cancellation here. A wedged transport can leave
|
|
289
|
+
// `reader.cancel()` pending too; the caller's abort must still return.
|
|
290
|
+
void reader.cancel().catch(() => undefined);
|
|
243
291
|
try {
|
|
244
292
|
reader.releaseLock();
|
|
245
293
|
}
|
|
@@ -334,9 +382,12 @@ export function buildReasoningPayload(reasoning, style, model) {
|
|
|
334
382
|
return { reasoning_effort: enabled ? "default" : "none" };
|
|
335
383
|
}
|
|
336
384
|
if (/openai\/gpt-oss-(?:20b|120b)/.test(m)) {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
385
|
+
// GPT-OSS cannot disable reasoning effort, but it can hide reasoning
|
|
386
|
+
// from the response. Retrying an empty visible answer must not silently
|
|
387
|
+
// fall back to the provider's medium default effort.
|
|
388
|
+
return enabled
|
|
389
|
+
? { reasoning_effort: clampEffort(effort), include_reasoning: true }
|
|
390
|
+
: { reasoning_effort: "low", include_reasoning: false };
|
|
340
391
|
}
|
|
341
392
|
return {};
|
|
342
393
|
}
|
|
@@ -398,8 +449,15 @@ export function buildReasoningPayload(reasoning, style, model) {
|
|
|
398
449
|
chat_template_kwargs: { enable_thinking: enabled },
|
|
399
450
|
};
|
|
400
451
|
case "effort-only":
|
|
401
|
-
|
|
402
|
-
|
|
452
|
+
// NVIDIA GPT-OSS accepts only low/medium/high, so a retry cannot
|
|
453
|
+
// fully disable it. Keep it at the lowest supported effort instead
|
|
454
|
+
// of omitting the field and reverting to NVIDIA's medium default.
|
|
455
|
+
if (!enabled && /gpt-oss/i.test(model ?? "")) {
|
|
456
|
+
return { reasoning_effort: "low" };
|
|
457
|
+
}
|
|
458
|
+
if (!enabled && /qwen3|mistral-/i.test(model ?? "")) {
|
|
459
|
+
return { reasoning_effort: "none" };
|
|
460
|
+
}
|
|
403
461
|
return { reasoning_effort: clampEffort(effort) };
|
|
404
462
|
case "none":
|
|
405
463
|
default:
|
|
@@ -418,7 +476,9 @@ function buildChatBody(options) {
|
|
|
418
476
|
// thinking is on, 2K otherwise — keep small for fast non-reasoning
|
|
419
477
|
// paths so kimi-k2.6 etc. respond instantly).
|
|
420
478
|
const reasoningOn = Boolean(options.reasoning?.enabled);
|
|
421
|
-
|
|
479
|
+
// Kimchi exposes this model as `minimax-m3`; NVIDIA uses the longer
|
|
480
|
+
// `minimaxai/minimax-m3` ID. Both require the same sampling settings.
|
|
481
|
+
const isMinimaxM3 = /minimax-m3/i.test(options.model);
|
|
422
482
|
const defaultMaxTokens = isMinimaxM3 ? 8_192 : reasoningOn ? 8_192 : 4_096;
|
|
423
483
|
const defaultTemperature = isMinimaxM3 ? 1.0 : 0.2;
|
|
424
484
|
const body = {
|
|
@@ -493,20 +553,24 @@ export async function openAiCompatibleComplete(options) {
|
|
|
493
553
|
export async function openAiCompatibleStream(options) {
|
|
494
554
|
// Combine the caller's abort signal with an idle watchdog so a stuck
|
|
495
555
|
// connection on a thinking model can't wedge the REPL forever.
|
|
496
|
-
const idleTimeoutMs = options.idleTimeoutMs ??
|
|
556
|
+
const idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS;
|
|
557
|
+
const initialIdleTimeoutMs = options.initialIdleTimeoutMs ?? idleTimeoutMs;
|
|
497
558
|
const idleController = new AbortController();
|
|
498
559
|
let idleTimer;
|
|
499
560
|
let idleFired = false;
|
|
561
|
+
let sawStreamBytes = false;
|
|
562
|
+
let activeIdleTimeoutMs = initialIdleTimeoutMs;
|
|
500
563
|
const resetIdleTimer = () => {
|
|
501
564
|
if (idleTimer)
|
|
502
565
|
clearTimeout(idleTimer);
|
|
566
|
+
activeIdleTimeoutMs = sawStreamBytes ? idleTimeoutMs : initialIdleTimeoutMs;
|
|
503
567
|
idleTimer = setTimeout(() => {
|
|
504
568
|
idleFired = true;
|
|
505
569
|
idleController.abort();
|
|
506
|
-
},
|
|
570
|
+
}, activeIdleTimeoutMs);
|
|
507
571
|
};
|
|
508
572
|
resetIdleTimer();
|
|
509
|
-
const onCallerAbort = () => idleController.abort();
|
|
573
|
+
const onCallerAbort = () => idleController.abort(options.signal?.reason);
|
|
510
574
|
options.signal?.addEventListener("abort", onCallerAbort, { once: true });
|
|
511
575
|
const supportsVision = modelSupportsVision(options.provider.toLowerCase(), options.model);
|
|
512
576
|
const requestBody = buildChatBody({
|
|
@@ -543,7 +607,7 @@ export async function openAiCompatibleStream(options) {
|
|
|
543
607
|
clearTimeout(idleTimer);
|
|
544
608
|
options.signal?.removeEventListener("abort", onCallerAbort);
|
|
545
609
|
if (idleFired) {
|
|
546
|
-
throw new ProviderError(`${options.provider} request timed out before any response (${Math.round(
|
|
610
|
+
throw new ProviderError(`${options.provider} request timed out before any response (${Math.round(activeIdleTimeoutMs / 1000)}s)`);
|
|
547
611
|
}
|
|
548
612
|
throw error;
|
|
549
613
|
}
|
|
@@ -629,13 +693,14 @@ export async function openAiCompatibleStream(options) {
|
|
|
629
693
|
if (idleController.signal.aborted) {
|
|
630
694
|
throw new Error("Stream aborted");
|
|
631
695
|
}
|
|
632
|
-
const { done, value } = await reader.
|
|
696
|
+
const { done, value } = await readWithAbort(reader, idleController.signal);
|
|
633
697
|
options.signal?.throwIfAborted();
|
|
634
698
|
if (idleController.signal.aborted) {
|
|
635
699
|
throw new Error("Stream aborted");
|
|
636
700
|
}
|
|
637
701
|
if (done)
|
|
638
702
|
break;
|
|
703
|
+
sawStreamBytes = true;
|
|
639
704
|
resetIdleTimer();
|
|
640
705
|
buffer += decoder.decode(value, { stream: true });
|
|
641
706
|
const lines = buffer.split("\n");
|
|
@@ -648,14 +713,16 @@ export async function openAiCompatibleStream(options) {
|
|
|
648
713
|
if (payload === "[DONE]") {
|
|
649
714
|
exitReasoning();
|
|
650
715
|
cleanup();
|
|
651
|
-
if (!visible.trim()
|
|
652
|
-
reasoningSeen.trim()
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
// a
|
|
658
|
-
|
|
716
|
+
if (!visible.trim()) {
|
|
717
|
+
const cause = reasoningSeen.trim()
|
|
718
|
+
? finishReason === "length"
|
|
719
|
+
? "hit the max_tokens limit while still thinking"
|
|
720
|
+
: "completed after reasoning without a visible answer"
|
|
721
|
+
: "completed without a visible answer";
|
|
722
|
+
// Do not return a reasoning-only completion to the agent. It
|
|
723
|
+
// would poison recovery history and cause no-op retry loops.
|
|
724
|
+
// Router-level fallback can now try a healthy provider instead.
|
|
725
|
+
throw new ProviderError(`${options.provider} ${cause}.`);
|
|
659
726
|
}
|
|
660
727
|
return full;
|
|
661
728
|
}
|
|
@@ -690,15 +757,13 @@ export async function openAiCompatibleStream(options) {
|
|
|
690
757
|
}
|
|
691
758
|
exitReasoning();
|
|
692
759
|
cleanup();
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
if (!visible.trim() && reasoningSeen.trim() && finishReason === "length") {
|
|
701
|
-
throw new ProviderError(`${options.provider} hit the max_tokens limit while still thinking (no visible answer). Try /variants off, lower the effort, or raise max_tokens.`);
|
|
760
|
+
if (!visible.trim()) {
|
|
761
|
+
const cause = reasoningSeen.trim()
|
|
762
|
+
? finishReason === "length"
|
|
763
|
+
? "hit the max_tokens limit while still thinking"
|
|
764
|
+
: "completed after reasoning without a visible answer"
|
|
765
|
+
: "completed without a visible answer";
|
|
766
|
+
throw new ProviderError(`${options.provider} ${cause}.`);
|
|
702
767
|
}
|
|
703
768
|
return full;
|
|
704
769
|
}
|
|
@@ -708,12 +773,9 @@ export async function openAiCompatibleStream(options) {
|
|
|
708
773
|
// stream is already errored (eg from the same abort that triggered
|
|
709
774
|
// this catch). Swallow it so it never escalates to an unhandled
|
|
710
775
|
// rejection that kills the whole REPL.
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
catch {
|
|
715
|
-
// best-effort cleanup
|
|
716
|
-
}
|
|
776
|
+
// Do not await cancellation here. Some stalled sockets never settle the
|
|
777
|
+
// pending cancel promise, and waiting for it would negate the abort race.
|
|
778
|
+
void reader.cancel().catch(() => undefined);
|
|
717
779
|
try {
|
|
718
780
|
reader.releaseLock();
|
|
719
781
|
}
|
|
@@ -721,7 +783,7 @@ export async function openAiCompatibleStream(options) {
|
|
|
721
783
|
// already released
|
|
722
784
|
}
|
|
723
785
|
if (idleFired) {
|
|
724
|
-
throw new ProviderError(`${options.provider} stream stalled — no data for ${Math.round(
|
|
786
|
+
throw new ProviderError(`${options.provider} stream stalled — no data for ${Math.round(activeIdleTimeoutMs / 1000)}s. Try a smaller model or disable thinking with /variants off.`);
|
|
725
787
|
}
|
|
726
788
|
throw error;
|
|
727
789
|
}
|