@aliou/pi-neuralwatt 0.16.1 → 0.16.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.
@@ -1,3 +1,4 @@
1
+ import type { StreamOptions } from "@earendil-works/pi-ai";
1
2
  import { stream, streamSimple } from "@earendil-works/pi-ai/compat";
2
3
  import {
3
4
  NEURALWATT_BASE_URL,
@@ -8,9 +9,56 @@ import type { NeuralwattModel } from "../models/catalog";
8
9
  import type { AnyStreamSimple } from "../stream-simple";
9
10
  import type { NeuralwattApiHandler } from "./types";
10
11
 
12
+ type OpenAiCompletionsBody = {
13
+ messages?: Array<Record<string, unknown>>;
14
+ [key: string]: unknown;
15
+ };
16
+
17
+ /**
18
+ * Neuralwatt streams chain-of-thought in the `reasoning` field, and pi-ai
19
+ * replays prior thinking under the field name it recorded from the stream —
20
+ * also `reasoning`. The served chat templates only render `reasoning_content`
21
+ * (verified against the Kimi K3 template), so replayed thinking never reaches
22
+ * the model. Rename the replayed field on the wire. This is a move, not a
23
+ * copy: sending an empty `reasoning_content` next to a populated `reasoning`
24
+ * makes the gateway prefer the empty field and silently drops the replay.
25
+ */
26
+ function makeReasoningReplayInjector(
27
+ upstream?: StreamOptions["onPayload"],
28
+ ): NonNullable<StreamOptions["onPayload"]> {
29
+ return async (payload, model) => {
30
+ const next = await upstream?.(payload, model);
31
+ const body = (next !== undefined ? next : payload) as OpenAiCompletionsBody;
32
+ const messages = body.messages;
33
+ if (!Array.isArray(messages)) return body;
34
+
35
+ return {
36
+ ...body,
37
+ messages: messages.map((message) => {
38
+ if (message?.role !== "assistant" || !("reasoning" in message)) {
39
+ return message;
40
+ }
41
+ const { reasoning, ...rest } = message;
42
+ // A pre-set non-empty reasoning_content wins; drop the duplicate.
43
+ return typeof rest.reasoning_content === "string" &&
44
+ rest.reasoning_content.length > 0
45
+ ? rest
46
+ : { ...rest, reasoning_content: reasoning };
47
+ }),
48
+ };
49
+ };
50
+ }
51
+
11
52
  export function createOpenAiCompletionsApi(options?: {
12
53
  streamSimple?: AnyStreamSimple;
13
54
  }): NeuralwattApiHandler {
55
+ const withReasoningReplay = (options?: {
56
+ onPayload?: StreamOptions["onPayload"];
57
+ }) => ({
58
+ ...options,
59
+ onPayload: makeReasoningReplayInjector(options?.onPayload),
60
+ });
61
+
14
62
  return {
15
63
  stampModels: (models: NeuralwattModel[]) =>
16
64
  models.map((model) => {
@@ -24,7 +72,12 @@ export function createOpenAiCompletionsApi(options?: {
24
72
  };
25
73
  }),
26
74
  stream: (model, context, streamOptions) =>
27
- stream(model, context, streamOptions as never),
28
- streamSimple: options?.streamSimple ?? streamSimple,
75
+ stream(model, context, withReasoningReplay(streamOptions) as never),
76
+ streamSimple: (model, context, simpleOptions) =>
77
+ (options?.streamSimple ?? streamSimple)(
78
+ model,
79
+ context,
80
+ withReasoningReplay(simpleOptions) as never,
81
+ ),
29
82
  };
30
83
  }
@@ -116,6 +116,62 @@ const KIMI_K2_7_CODE: NeuralwattModelFamily = {
116
116
  },
117
117
  };
118
118
 
119
+ // Xiaomi. MiMo-V2.6-Pro only has two reasoning behaviors: `high` (default)
120
+ // and `none`; the API aliases every other effort onto those, with `minimal`
121
+ // landing on `none`.
122
+ const MIMO_V2_6_PRO: NeuralwattModelFamily = {
123
+ cost: { input: 0.87, output: 1.74, cacheRead: 0.036 },
124
+ vision: true,
125
+ reasoningMetadata: {
126
+ supported_efforts: ["high", "none"],
127
+ mandatory: false,
128
+ effort_aliases: {
129
+ max: "high",
130
+ xhigh: "high",
131
+ medium: "high",
132
+ low: "high",
133
+ minimal: "none",
134
+ },
135
+ },
136
+ };
137
+
138
+ // Neuralwatt tracking alias: the current large model, today Kimi K3. The
139
+ // alias moves to newer models over time, so it snapshots K3's contract
140
+ // instead of sharing the KIMI_K3 family.
141
+ const NW_LARGE: NeuralwattModelFamily = {
142
+ cost: { input: 3, output: 15, cacheRead: 0.3 },
143
+ vision: true,
144
+ reasoningMetadata: {
145
+ supported_efforts: ["max", "high", "low", "none"],
146
+ mandatory: false,
147
+ effort_aliases: { xhigh: "max", medium: "high", minimal: "low" },
148
+ },
149
+ };
150
+
151
+ // Neuralwatt tracking alias: the current cheap, fast model, today DeepSeek
152
+ // V4.1 Flash. Same moving-alias caveat as NW_LARGE.
153
+ const NW_FLASH: NeuralwattModelFamily = {
154
+ cost: { input: 0.15, output: 0.6, cacheRead: 0.015 },
155
+ vision: true,
156
+ reasoningMetadata: {
157
+ supported_efforts: ["max", "xhigh", "high", "low", "none"],
158
+ mandatory: false,
159
+ effort_aliases: { medium: "high", minimal: "low" },
160
+ },
161
+ };
162
+
163
+ // Neuralwatt tracking alias: the current small model, today Qwen3.8-27B.
164
+ // Same moving-alias caveat as NW_LARGE.
165
+ const NW_SMALL: NeuralwattModelFamily = {
166
+ cost: { input: 0.45, output: 3.2, cacheRead: 0.25 },
167
+ vision: true,
168
+ reasoningMetadata: {
169
+ supported_efforts: ["xhigh", "medium", "low", "none"],
170
+ mandatory: false,
171
+ effort_aliases: { max: "xhigh", high: "xhigh", minimal: "low" },
172
+ },
173
+ };
174
+
119
175
  // Qwen. Qwen3.6 35B only advertises `high` and `none`.
120
176
  const QWEN_3_6_35B: NeuralwattModelFamily = {
121
177
  cost: { input: 0.29, output: 1.15, cacheRead: 0.029 },
@@ -192,6 +248,13 @@ const FAMILIES: [NeuralwattModelFamily, NeuralwattVariantSpec[]][] = [
192
248
  reasoning: true,
193
249
  costMultiplier: 0.65,
194
250
  },
251
+ {
252
+ id: "deepseek-v4.1-flash-speed",
253
+ name: "DeepSeek V4.1 Flash (Speed)",
254
+ contextWindow: 1048560,
255
+ maxOutputTokens: 393216,
256
+ reasoning: true,
257
+ },
195
258
  ],
196
259
  ],
197
260
  [
@@ -302,27 +365,99 @@ const FAMILIES: [NeuralwattModelFamily, NeuralwattVariantSpec[]][] = [
302
365
  },
303
366
  ],
304
367
  ],
368
+ [
369
+ MIMO_V2_6_PRO,
370
+ [
371
+ {
372
+ id: "mimo-v2.6-pro",
373
+ name: "MiMo-V2.6-Pro",
374
+ contextWindow: 1048560,
375
+ maxOutputTokens: 393216,
376
+ reasoning: true,
377
+ },
378
+ ],
379
+ ],
380
+ [
381
+ NW_LARGE,
382
+ [
383
+ {
384
+ id: "nw-large",
385
+ name: "Neuralwatt Large",
386
+ contextWindow: 1048560,
387
+ maxOutputTokens: null,
388
+ reasoning: true,
389
+ },
390
+ {
391
+ id: "nw-large-flex",
392
+ name: "Neuralwatt Large (flex)",
393
+ contextWindow: 1048560,
394
+ maxOutputTokens: null,
395
+ reasoning: true,
396
+ costMultiplier: 0.65,
397
+ },
398
+ ],
399
+ ],
400
+ [
401
+ NW_FLASH,
402
+ [
403
+ {
404
+ id: "nw-flash",
405
+ name: "Neuralwatt Flash",
406
+ contextWindow: 1048560,
407
+ maxOutputTokens: 393216,
408
+ reasoning: true,
409
+ },
410
+ {
411
+ id: "nw-flash-flex",
412
+ name: "Neuralwatt Flash (flex)",
413
+ contextWindow: 1048560,
414
+ maxOutputTokens: 393216,
415
+ reasoning: true,
416
+ costMultiplier: 0.65,
417
+ },
418
+ ],
419
+ ],
420
+ [
421
+ NW_SMALL,
422
+ [
423
+ {
424
+ id: "nw-small",
425
+ name: "Neuralwatt Small",
426
+ contextWindow: 262128,
427
+ maxOutputTokens: 131072,
428
+ reasoning: true,
429
+ },
430
+ {
431
+ id: "nw-small-flex",
432
+ name: "Neuralwatt Small (flex)",
433
+ contextWindow: 262128,
434
+ maxOutputTokens: 131072,
435
+ reasoning: true,
436
+ costMultiplier: 0.65,
437
+ },
438
+ ],
439
+ ],
305
440
  [
306
441
  QWEN_3_6_35B,
307
442
  [
308
443
  {
309
444
  id: "qwen3.6-35b",
310
445
  name: "Qwen3.6 35B",
311
- contextWindow: 131056,
446
+ contextWindow: 262128,
312
447
  maxOutputTokens: null,
313
448
  reasoning: true,
314
449
  },
315
450
  {
316
451
  id: "qwen3.6-35b-fast",
317
452
  name: "Qwen3.6 35B Fast",
318
- contextWindow: 131056,
453
+ contextWindow: 262128,
319
454
  maxOutputTokens: null,
320
455
  reasoning: false,
321
456
  },
322
457
  {
323
458
  id: "qwen3.6-35b-flex",
324
459
  name: "Qwen3.6 35B (flex)",
325
- contextWindow: 131056,
460
+ contextWindow: 262128,
326
461
  maxOutputTokens: null,
327
462
  reasoning: true,
328
463
  costMultiplier: 0.65,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aliou/pi-neuralwatt",
3
- "version": "0.16.1",
3
+ "version": "0.16.3",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "private": false,