pi-makora-provider 1.7.0 → 1.8.0
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 +5 -5
- package/index.ts +187 -2
- package/models.json +1 -1
- package/package.json +1 -1
- package/patch.json +27 -20
package/README.md
CHANGED
|
@@ -21,13 +21,13 @@ _DeepSeek V4, Kimi K2.7 Code, GLM 5.2, Qwen 3.6 for [pi](https://github.com/eare
|
|
|
21
21
|
| DeepSeek V4 Flash | `deepseek-ai/DeepSeek-V4-Flash` | Yes | returns `reasoning` field |
|
|
22
22
|
| DeepSeek V4 Pro | `deepseek-ai/DeepSeek-V4-Pro` | Yes | returns `reasoning` field |
|
|
23
23
|
| Gemma 4 26B A4B | `google/gemma-4-26B-A4B` | No | |
|
|
24
|
-
| GLM 5.2 FP8 | `zai-org/GLM-5.2-FP8` | Yes |
|
|
25
|
-
| GLM 5.2 NVFP4 | `zai-org/GLM-5.2-NVFP4` | Yes |
|
|
26
|
-
| Kimi K2.7 Code | `moonshotai/Kimi-K2.7-Code` | Yes |
|
|
24
|
+
| GLM 5.2 FP8 | `zai-org/GLM-5.2-FP8` | Yes | off via top-level `reasoning_effort: "none"` (only lever GLM responds to; `enable_thinking`/`thinking`/chat_template_kwargs toggles are ignored); effort `high`/`max` only (minimal/low/medium clamp to `high`); multi-turn continuity via `clear_thinking` (false when thinking on = preserve, true when off = clear; `preserve_thinking` is inert for GLM) injected via onPayload; returns `reasoning` field |
|
|
25
|
+
| GLM 5.2 NVFP4 | `zai-org/GLM-5.2-NVFP4` | Yes | off via top-level `reasoning_effort: "none"` (only lever GLM responds to; `enable_thinking`/`thinking`/chat_template_kwargs toggles are ignored); effort `high`/`max` only (minimal/low/medium clamp to `high`); multi-turn continuity via `clear_thinking` (false when thinking on = preserve, true when off = clear; `preserve_thinking` is inert for GLM) injected via onPayload; returns `reasoning` field |
|
|
26
|
+
| Kimi K2.7 Code | `moonshotai/Kimi-K2.7-Code` | Yes | on/off via namespaced `chat_template_kwargs.thinking` (toggled with thinking switch); `preserve_thinking` (toggled) for multi-turn continuity; onPayload aliases each assistant message's `reasoning` → `reasoning_content` (Kimi's template reads `reasoning_content` but pi-ai sends `reasoning`); returns `reasoning` field. `reasoning_effort` is not emitted (Kimi's template reads namespaced `thinking`, not `reasoning_effort`) |
|
|
27
27
|
| Llama 3.3 70B FP8 | `amd/Llama-3.3-70B-Instruct-FP8-KV` | No | |
|
|
28
28
|
| Llama 3.3 70B Instruct | `meta-llama/Llama-3.3-70B-Instruct` | No | |
|
|
29
|
-
| Qwen 3.6 27B NVFP4 | `unsloth/Qwen3.6-27B-NVFP4` | Yes |
|
|
30
|
-
| Qwen 3.6 35B A3B NVFP4 | `unsloth/Qwen3.6-35B-A3B-NVFP4` | Yes |
|
|
29
|
+
| Qwen 3.6 27B NVFP4 | `unsloth/Qwen3.6-27B-NVFP4` | Yes | off via top-level `reasoning_effort: "none"`; `preserve_thinking` (toggled with thinking switch) injected via onPayload for multi-turn continuity; returns `reasoning` field |
|
|
30
|
+
| Qwen 3.6 35B A3B NVFP4 | `unsloth/Qwen3.6-35B-A3B-NVFP4` | Yes | off via top-level `reasoning_effort: "none"`; `preserve_thinking` (toggled with thinking switch) injected via onPayload for multi-turn continuity; returns `reasoning` field |
|
|
31
31
|
<!-- MODELS_TABLE_END -->
|
|
32
32
|
|
|
33
33
|
## Installation
|
package/index.ts
CHANGED
|
@@ -47,6 +47,9 @@
|
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
49
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
50
|
+
import type { SimpleStreamOptions, AssistantMessageEventStream } from "@earendil-works/pi-ai";
|
|
51
|
+
import { clampThinkingLevel } from "@earendil-works/pi-ai";
|
|
52
|
+
import { streamOpenAICompletions } from "@earendil-works/pi-ai/compat";
|
|
50
53
|
import modelsData from "./models.json" with { type: "json" };
|
|
51
54
|
import customModelsData from "./custom-models.json" with { type: "json" };
|
|
52
55
|
import patchData from "./patch.json" with { type: "json" };
|
|
@@ -91,6 +94,13 @@ interface JsonModel {
|
|
|
91
94
|
requiresToolResultName?: boolean;
|
|
92
95
|
requiresAssistantAfterToolResult?: boolean;
|
|
93
96
|
cacheControlFormat?: "anthropic";
|
|
97
|
+
/** When set, onPayload copies each assistant message's `reasoning` field into
|
|
98
|
+
* this field name before sending. Needed when a model's chat template reads
|
|
99
|
+
* prior reasoning from a different field than the one pi-ai sends it in.
|
|
100
|
+
* e.g. Kimi K2.7's template reads `reasoning_content`, but pi-ai sends
|
|
101
|
+
* `reasoning` (the field the model returns) — without the copy, preserve_thinking
|
|
102
|
+
* can't render the prior trace. */
|
|
103
|
+
assistantReasoningField?: string;
|
|
94
104
|
/** Extra keys merged into vLLM `chat_template_kwargs` on every request.
|
|
95
105
|
* Used for preserved-thinking flags like `preserve_thinking` / `clear_thinking`
|
|
96
106
|
* that some chat templates require for multi-turn reasoning continuity. */
|
|
@@ -192,6 +202,177 @@ function buildModels(
|
|
|
192
202
|
return Array.from(modelMap.values());
|
|
193
203
|
}
|
|
194
204
|
|
|
205
|
+
// Thinking-off + preserved-thinking via streamSimple
|
|
206
|
+
//
|
|
207
|
+
// Makora's reasoning models need BOTH a thinking on/off switch AND multi-turn
|
|
208
|
+
// reasoning continuity (`preserve_thinking`). pi-ai's built-in `thinkingFormat`
|
|
209
|
+
// branches are mutually exclusive: the `chat-template` branch emits
|
|
210
|
+
// `chat_template_kwargs` (so it can carry `preserve_thinking`) but never a
|
|
211
|
+
// top-level `reasoning_effort`; the OpenAI fallback emits `reasoning_effort`
|
|
212
|
+
// (the lever GLM 5.2 and Qwen 3.6 actually respond to for off) but never
|
|
213
|
+
// `chat_template_kwargs`. No single format emits both.
|
|
214
|
+
//
|
|
215
|
+
// Behavioral E2E (see test-thinking-triggers.ts / test-preserve-deterministic.ts):
|
|
216
|
+
// GLM 5.2 — off ONLY via top-level `reasoning_effort: "none"`;
|
|
217
|
+
// `enable_thinking`/`thinking`/chat_template_kwargs toggles are ignored.
|
|
218
|
+
// Multi-turn continuity uses `clear_thinking: false` (NOT preserve_thinking
|
|
219
|
+
// — that flag is inert for GLM); toggled with the thinking switch
|
|
220
|
+
// (false when on = preserve, true when off = clear).
|
|
221
|
+
// Qwen 3.6 — off via top-level `reasoning_effort: "none"` (or `enable_thinking`).
|
|
222
|
+
// Multi-turn continuity uses `preserve_thinking: true`; reads the
|
|
223
|
+
// `reasoning` field pi-ai sends. Toggled with the thinking switch.
|
|
224
|
+
// Kimi K2.7 — off via namespaced `chat_template_kwargs.thinking: false`.
|
|
225
|
+
// Multi-turn continuity uses `preserve_thinking: true`, BUT the
|
|
226
|
+
// template reads `reasoning_content` while pi-ai sends `reasoning`
|
|
227
|
+
// (Makora doesn't gateway-alias the fields) — so onPayload also
|
|
228
|
+
// copies each assistant message's `reasoning` → `reasoning_content`.
|
|
229
|
+
// preserve_thinking IS functional (deterministic E2E: Qwen 3.6 27B recalls
|
|
230
|
+
// 1.00 with it on, 0.00 off) — it gates whether the prior reasoning trace
|
|
231
|
+
// is rendered into the next turn's prompt.
|
|
232
|
+
//
|
|
233
|
+
// So this provider registers a `streamSimple` wrapper that delegates to pi-ai's
|
|
234
|
+
// `streamOpenAICompletions` (keeping all its streaming/tool-calling/caching) and
|
|
235
|
+
// uses pi-ai's `onPayload` hook — which runs AFTER `buildParams` — to inject the
|
|
236
|
+
// `chat_template_kwargs` that the chosen `thinkingFormat` branch can't reach.
|
|
237
|
+
// `buildParams` still owns `reasoning_effort` (on → mapped effort; off → "none");
|
|
238
|
+
// `onPayload` owns `chat_template_kwargs` (preserve_thinking + Kimi's `thinking`).
|
|
239
|
+
// Per-model config lives in `compat.chatTemplateKwargs` (patch.json), using the
|
|
240
|
+
// same `{ "$var": "thinking.enabled" }` schema pi-ai's chat-template format uses.
|
|
241
|
+
|
|
242
|
+
/** Resolve one `chatTemplateKwargs` value (scalar or `{ $var }`) against the
|
|
243
|
+
* current thinking state. Mirrors pi-ai's `resolveChatTemplateKwargValue` so
|
|
244
|
+
* onPayload-injected values match what the built-in chat-template format would
|
|
245
|
+
* produce — but injected after buildParams so they coexist with reasoning_effort. */
|
|
246
|
+
export function resolveChatTemplateKwarg(
|
|
247
|
+
value: unknown,
|
|
248
|
+
model: JsonModel,
|
|
249
|
+
thinkingOn: boolean,
|
|
250
|
+
reasoningEffort: string | undefined,
|
|
251
|
+
): unknown {
|
|
252
|
+
// Scalars pass through unchanged (e.g. static `preserve_thinking: true`).
|
|
253
|
+
if (value === null || typeof value !== "object") {
|
|
254
|
+
return value;
|
|
255
|
+
}
|
|
256
|
+
const spec = value as { $var?: string; omitWhenOff?: boolean; invert?: boolean };
|
|
257
|
+
if (spec.omitWhenOff && !thinkingOn) {
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
if (spec.$var === "thinking.enabled") {
|
|
261
|
+
return spec.invert ? !thinkingOn : thinkingOn;
|
|
262
|
+
}
|
|
263
|
+
if (spec.$var === "thinking.effort") {
|
|
264
|
+
const mapped = thinkingOn
|
|
265
|
+
? model.thinkingLevelMap?.[reasoningEffort as string]
|
|
266
|
+
: model.thinkingLevelMap?.off;
|
|
267
|
+
if (mapped === undefined) return reasoningEffort;
|
|
268
|
+
return typeof mapped === "string" ? mapped : undefined;
|
|
269
|
+
}
|
|
270
|
+
return undefined;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/** Custom streamSimple: delegate to pi-ai's OpenAI completions streamer and
|
|
274
|
+
* inject per-model `chat_template_kwargs` (preserve_thinking / clear_thinking +
|
|
275
|
+
* Kimi's thinking toggle) via the onPayload hook, and alias each assistant
|
|
276
|
+
* message's reasoning field when a template reads a different field name.
|
|
277
|
+
* Models with neither chatTemplateKwargs nor assistantReasoningField (DeepSeek,
|
|
278
|
+
* Llama, Gemma) pass through unchanged — onPayload is not registered. */
|
|
279
|
+
export function streamMakora(
|
|
280
|
+
model: any,
|
|
281
|
+
context: any,
|
|
282
|
+
options?: SimpleStreamOptions,
|
|
283
|
+
): AssistantMessageEventStream {
|
|
284
|
+
const apiKey = options?.apiKey || "";
|
|
285
|
+
if (!apiKey) {
|
|
286
|
+
throw new Error(
|
|
287
|
+
`No API key for Makora. Add it to ~/.pi/agent/auth.json under "makora", ` +
|
|
288
|
+
`set the MAKORA_OPTIMIZE_TOKEN env var, or use --api-key.`,
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// pi-ai's streamer reads `model.api` to pick the OpenAI completions client. Our
|
|
293
|
+
// provider registers under `api: "makora"` (so pi routes to this streamSimple);
|
|
294
|
+
// override to `openai-completions` here so streamOpenAICompletions uses the
|
|
295
|
+
// standard client. Per-model baseUrl overrides (per-slug endpoints) are kept.
|
|
296
|
+
const makoraModel = { ...model, api: "openai-completions", baseUrl: model.baseUrl || BASE_URL };
|
|
297
|
+
|
|
298
|
+
// pi hands streamSimple providers the raw thinking selection as
|
|
299
|
+
// `options.reasoning` (a ThinkingLevel). The raw streamOpenAICompletions only
|
|
300
|
+
// reads `options.reasoningEffort`, so replicate the clamp+convert pi-ai's own
|
|
301
|
+
// streamSimple wrapper does — otherwise reasoning_effort never reaches the
|
|
302
|
+
// body and thinking levels silently do nothing. "off" → undefined (off).
|
|
303
|
+
const clampedReasoning = options?.reasoning
|
|
304
|
+
? clampThinkingLevel(makoraModel, options.reasoning)
|
|
305
|
+
: undefined;
|
|
306
|
+
const reasoningEffort = clampedReasoning === "off" ? undefined : clampedReasoning;
|
|
307
|
+
const thinkingOn = reasoningEffort !== undefined;
|
|
308
|
+
const { reasoning: _reasoning, ...streamOptions } = options ?? {};
|
|
309
|
+
|
|
310
|
+
// Inject chat_template_kwargs after buildParams via onPayload. Any caller-
|
|
311
|
+
// supplied onPayload is chained first so it can inspect/replace the payload;
|
|
312
|
+
// our injection then merges into whatever chat_template_kwargs already exist.
|
|
313
|
+
// We also register onPayload when the model needs its prior-reasoning field
|
|
314
|
+
// aliased (assistantReasoningField) — e.g. Kimi's template reads
|
|
315
|
+
// `reasoning_content` but pi-ai sends `reasoning`; the copy makes the
|
|
316
|
+
// preserved trace visible to the template so preserve_thinking can render it.
|
|
317
|
+
const userOnPayload = (streamOptions as any).onPayload;
|
|
318
|
+
const extraKwargs = (makoraModel as JsonModel).compat?.chatTemplateKwargs;
|
|
319
|
+
const hasExtraKwargs =
|
|
320
|
+
!!extraKwargs && typeof extraKwargs === "object" && Object.keys(extraKwargs).length > 0;
|
|
321
|
+
const assistantReasoningField = (makoraModel as JsonModel).compat?.assistantReasoningField;
|
|
322
|
+
const needsFieldCopy = !!assistantReasoningField;
|
|
323
|
+
const onPayload =
|
|
324
|
+
hasExtraKwargs || needsFieldCopy || userOnPayload
|
|
325
|
+
? async (params: any, mdl: any) => {
|
|
326
|
+
let p = params;
|
|
327
|
+
if (userOnPayload) {
|
|
328
|
+
const next = await userOnPayload(p, mdl);
|
|
329
|
+
if (next !== undefined) p = next;
|
|
330
|
+
}
|
|
331
|
+
if (needsFieldCopy && thinkingOn) {
|
|
332
|
+
// Only alias the prior reasoning field when thinking is ON — when the
|
|
333
|
+
// user turns thinking off we must NOT carry prior reasoning forward
|
|
334
|
+
// (preserve_thinking is inert for Kimi's field rendering; the field's
|
|
335
|
+
// presence is what gates continuity). Kimi's template ignores the
|
|
336
|
+
// `reasoning` field, so skipping the copy leaves nothing to render.
|
|
337
|
+
const field = assistantReasoningField!;
|
|
338
|
+
const msgs = Array.isArray(p?.messages) ? p.messages : [];
|
|
339
|
+
p = {
|
|
340
|
+
...p,
|
|
341
|
+
messages: msgs.map((m: any) =>
|
|
342
|
+
m && m.role === "assistant" &&
|
|
343
|
+
typeof m.reasoning === "string" && m.reasoning.length > 0 &&
|
|
344
|
+
m[field] === undefined
|
|
345
|
+
? { ...m, [field]: m.reasoning }
|
|
346
|
+
: m
|
|
347
|
+
),
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
if (hasExtraKwargs) {
|
|
351
|
+
const resolved: Record<string, unknown> = {};
|
|
352
|
+
for (const [k, v] of Object.entries(extraKwargs!)) {
|
|
353
|
+
const r = resolveChatTemplateKwarg(v, makoraModel, thinkingOn, reasoningEffort as string | undefined);
|
|
354
|
+
if (r !== undefined) resolved[k] = r;
|
|
355
|
+
}
|
|
356
|
+
p = {
|
|
357
|
+
...p,
|
|
358
|
+
chat_template_kwargs: {
|
|
359
|
+
...(p?.chat_template_kwargs ?? {}),
|
|
360
|
+
...resolved,
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
return p;
|
|
365
|
+
}
|
|
366
|
+
: undefined;
|
|
367
|
+
|
|
368
|
+
return streamOpenAICompletions(makoraModel, context, {
|
|
369
|
+
...streamOptions,
|
|
370
|
+
reasoningEffort,
|
|
371
|
+
apiKey,
|
|
372
|
+
...(onPayload ? { onPayload } : {}),
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
195
376
|
// Extension Entry Point
|
|
196
377
|
|
|
197
378
|
const PROVIDER_ID = "makora";
|
|
@@ -206,12 +387,16 @@ const allMakoraModels = buildModels(
|
|
|
206
387
|
export default function (pi: ExtensionAPI) {
|
|
207
388
|
const models = allMakoraModels;
|
|
208
389
|
|
|
209
|
-
// apiKey resolution order: auth.json ("makora" key) → MAKORA_OPTIMIZE_TOKEN env var
|
|
390
|
+
// apiKey resolution order: auth.json ("makora" key) → MAKORA_OPTIMIZE_TOKEN env var.
|
|
391
|
+
// `api: "makora"` + `streamSimple` routes every Makora model through streamMakora
|
|
392
|
+
// (above), which delegates to pi-ai's OpenAI completions streamer and injects
|
|
393
|
+
// per-model chat_template_kwargs via onPayload.
|
|
210
394
|
pi.registerProvider(PROVIDER_ID, {
|
|
211
395
|
name: "Makora",
|
|
212
396
|
baseUrl: BASE_URL,
|
|
213
397
|
apiKey: "$MAKORA_OPTIMIZE_TOKEN",
|
|
214
|
-
api: "
|
|
398
|
+
api: "makora",
|
|
399
|
+
streamSimple: streamMakora,
|
|
215
400
|
models,
|
|
216
401
|
});
|
|
217
402
|
|
package/models.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-makora-provider",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Makora provider extension for pi - Access DeepSeek V4, GLM 5.2, Kimi K2.7 Code, Llama 3.3, Qwen 3.6, and more through the Makora inference API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
package/patch.json
CHANGED
|
@@ -32,31 +32,31 @@
|
|
|
32
32
|
},
|
|
33
33
|
"unsloth/Qwen3.6-27B-NVFP4": {
|
|
34
34
|
"reasoning": true,
|
|
35
|
-
"notes": "
|
|
35
|
+
"notes": "off via top-level `reasoning_effort: \"none\"`; `preserve_thinking` (toggled with thinking switch) injected via onPayload for multi-turn continuity; returns `reasoning` field",
|
|
36
36
|
"thinkingLevelMap": {
|
|
37
37
|
"minimal": "low",
|
|
38
|
-
"xhigh": "high"
|
|
38
|
+
"xhigh": "high",
|
|
39
|
+
"off": "none"
|
|
39
40
|
},
|
|
40
41
|
"compat": {
|
|
41
|
-
"thinkingFormat": "qwen-chat-template",
|
|
42
42
|
"supportsReasoningEffort": true,
|
|
43
43
|
"chatTemplateKwargs": {
|
|
44
|
-
"preserve_thinking":
|
|
44
|
+
"preserve_thinking": { "$var": "thinking.enabled" }
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"unsloth/Qwen3.6-35B-A3B-NVFP4": {
|
|
49
49
|
"reasoning": true,
|
|
50
|
-
"notes": "
|
|
50
|
+
"notes": "off via top-level `reasoning_effort: \"none\"`; `preserve_thinking` (toggled with thinking switch) injected via onPayload for multi-turn continuity; returns `reasoning` field",
|
|
51
51
|
"thinkingLevelMap": {
|
|
52
52
|
"minimal": "low",
|
|
53
|
-
"xhigh": "high"
|
|
53
|
+
"xhigh": "high",
|
|
54
|
+
"off": "none"
|
|
54
55
|
},
|
|
55
56
|
"compat": {
|
|
56
|
-
"thinkingFormat": "qwen-chat-template",
|
|
57
57
|
"supportsReasoningEffort": true,
|
|
58
58
|
"chatTemplateKwargs": {
|
|
59
|
-
"preserve_thinking":
|
|
59
|
+
"preserve_thinking": { "$var": "thinking.enabled" }
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
},
|
|
@@ -66,47 +66,54 @@
|
|
|
66
66
|
"text",
|
|
67
67
|
"image"
|
|
68
68
|
],
|
|
69
|
-
"notes": "
|
|
69
|
+
"notes": "on/off via namespaced `chat_template_kwargs.thinking` (toggled with thinking switch); `preserve_thinking` (toggled) for multi-turn continuity; onPayload aliases each assistant message's `reasoning` → `reasoning_content` (Kimi's template reads `reasoning_content` but pi-ai sends `reasoning`); returns `reasoning` field. `reasoning_effort` is not emitted (Kimi's template reads namespaced `thinking`, not `reasoning_effort`)",
|
|
70
70
|
"thinkingLevelMap": {
|
|
71
71
|
"minimal": "low",
|
|
72
72
|
"xhigh": "high"
|
|
73
73
|
},
|
|
74
74
|
"compat": {
|
|
75
|
-
"
|
|
76
|
-
"
|
|
75
|
+
"supportsReasoningEffort": false,
|
|
76
|
+
"assistantReasoningField": "reasoning_content",
|
|
77
77
|
"chatTemplateKwargs": {
|
|
78
|
-
"
|
|
78
|
+
"thinking": { "$var": "thinking.enabled" },
|
|
79
|
+
"preserve_thinking": { "$var": "thinking.enabled" }
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
},
|
|
82
83
|
"zai-org/GLM-5.2-FP8": {
|
|
83
84
|
"reasoning": true,
|
|
84
|
-
"notes": "
|
|
85
|
+
"notes": "off via top-level `reasoning_effort: \"none\"` (only lever GLM responds to; `enable_thinking`/`thinking`/chat_template_kwargs toggles are ignored); effort `high`/`max` only (minimal/low/medium clamp to `high`); multi-turn continuity via `clear_thinking` (false when thinking on = preserve, true when off = clear; `preserve_thinking` is inert for GLM) injected via onPayload; returns `reasoning` field",
|
|
85
86
|
"thinkingLevelMap": {
|
|
86
87
|
"minimal": null,
|
|
87
88
|
"low": null,
|
|
88
89
|
"medium": null,
|
|
89
90
|
"high": "high",
|
|
90
|
-
"xhigh": "max"
|
|
91
|
+
"xhigh": "max",
|
|
92
|
+
"off": "none"
|
|
91
93
|
},
|
|
92
94
|
"compat": {
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
+
"supportsReasoningEffort": true,
|
|
96
|
+
"chatTemplateKwargs": {
|
|
97
|
+
"clear_thinking": { "$var": "thinking.enabled", "invert": true }
|
|
98
|
+
}
|
|
95
99
|
}
|
|
96
100
|
},
|
|
97
101
|
"zai-org/GLM-5.2-NVFP4": {
|
|
98
102
|
"reasoning": true,
|
|
99
|
-
"notes": "
|
|
103
|
+
"notes": "off via top-level `reasoning_effort: \"none\"` (only lever GLM responds to; `enable_thinking`/`thinking`/chat_template_kwargs toggles are ignored); effort `high`/`max` only (minimal/low/medium clamp to `high`); multi-turn continuity via `clear_thinking` (false when thinking on = preserve, true when off = clear; `preserve_thinking` is inert for GLM) injected via onPayload; returns `reasoning` field",
|
|
100
104
|
"thinkingLevelMap": {
|
|
101
105
|
"minimal": null,
|
|
102
106
|
"low": null,
|
|
103
107
|
"medium": null,
|
|
104
108
|
"high": "high",
|
|
105
|
-
"xhigh": "max"
|
|
109
|
+
"xhigh": "max",
|
|
110
|
+
"off": "none"
|
|
106
111
|
},
|
|
107
112
|
"compat": {
|
|
108
|
-
"
|
|
109
|
-
"
|
|
113
|
+
"supportsReasoningEffort": true,
|
|
114
|
+
"chatTemplateKwargs": {
|
|
115
|
+
"clear_thinking": { "$var": "thinking.enabled", "invert": true }
|
|
116
|
+
}
|
|
110
117
|
}
|
|
111
118
|
}
|
|
112
119
|
}
|