@aliou/pi-neuralwatt 0.11.0 → 0.11.2

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.
@@ -6,9 +6,8 @@ import { NEURALWATT_MODELS } from "./public-models";
6
6
  export const ALIAS_MODEL_MAP = {
7
7
  "deepseek-ai/DeepSeek-V4-Flash": "deepseek-v4-flash",
8
8
  "zai-org/GLM-5.2-FP8": "glm-5.2",
9
- "moonshotai/Kimi-K2.6": "kimi-k2.6",
10
9
  "moonshotai/Kimi-K2.7-Code": "kimi-k2.7-code",
11
- "Qwen/Qwen3.5-397B-A17B-FP8": "qwen3.5-397b",
10
+ "moonshotai/Kimi-K3": "kimi-k3",
12
11
  "Qwen/Qwen3.6-35B-A3B": "qwen3.6-35b",
13
12
  "nvidia/Gemma-4-31B-IT-NVFP4": "gemma-4-31b",
14
13
  } as const;
@@ -1,7 +1,7 @@
1
1
  import type { ProviderModelConfig } from "@earendil-works/pi-coding-agent";
2
2
  import { fetchNeuralwattModels } from "../../../src/lib/neuralwatt-api";
3
3
  import type { NeuralwattApiModel } from "../../../src/types/models-api";
4
- import { buildNeuralwattModel, resolveMaxTokens } from "./build";
4
+ import { resolveMaxTokens } from "./build";
5
5
  import { NEURALWATT_MODELS } from "./public-models";
6
6
 
7
7
  // Pre-release models. Neuralwatt ships these to authorized accounts before they
@@ -9,30 +9,7 @@ import { NEURALWATT_MODELS } from "./public-models";
9
9
  // gated by includeEarlyAccessModels and hardcode entries so they remain
10
10
  // available from the offline catalog.
11
11
  // Move an entry to public-models.ts once Neuralwatt advertises it publicly.
12
- export const EARLY_ACCESS_NEURALWATT_MODELS: ProviderModelConfig[] = [
13
- // Kimi K3 - early-access MoonshotAI multimodal MoE.
14
- // Metadata is sourced from Neuralwatt's authenticated model catalog.
15
- buildNeuralwattModel(
16
- {
17
- cost: { input: 3, output: 15, cacheRead: 0.3 },
18
- vision: true,
19
- thinkingLevelMap: {
20
- minimal: null,
21
- low: null,
22
- medium: "medium",
23
- high: null,
24
- xhigh: null,
25
- },
26
- },
27
- {
28
- id: "kimi-k3",
29
- name: "Kimi K3",
30
- contextWindow: 1048560,
31
- maxOutputTokens: null,
32
- reasoning: true,
33
- },
34
- ),
35
- ];
12
+ export const EARLY_ACCESS_NEURALWATT_MODELS: ProviderModelConfig[] = [];
36
13
 
37
14
  // Per-ID overrides for known early-access models. The authenticated /v1/models
38
15
  // endpoint exposes pricing and capabilities, but some Pi-specific behavior
@@ -4,11 +4,22 @@ import { NEURALWATT_MODELS } from "./public-models";
4
4
  // Legacy model IDs that should resolve to a canonical public model.
5
5
  // These are phased out over time and are only included when `includeLegacyModelIds` is enabled.
6
6
  export const LEGACY_MODEL_ALIAS_MAP = {
7
+ // GLM 5.1 → GLM 5.2
7
8
  "glm-5.1": "glm-5.2",
8
9
  "glm-5.1-fast": "glm-5.2-fast",
9
10
  "zai-org/GLM-5.1-FP8": "glm-5.2",
10
- "moonshotai/Kimi-K2.5": "kimi-k2.6",
11
- "kimi-k2.5-fast": "kimi-k2.6-fast",
11
+ // Kimi K2.5 → Kimi K2.7 Code (K2.6 was retired 8/3, redirected to K2.7)
12
+ "moonshotai/Kimi-K2.5": "kimi-k2.7-code",
13
+ "kimi-k2.5-fast": "kimi-k2.7-code-fast",
14
+ // Kimi K2.6 retired 8/3, redirected to Kimi K2.7 Code
15
+ "kimi-k2.6": "kimi-k2.7-code",
16
+ "kimi-k2.6-fast": "kimi-k2.7-code-fast",
17
+ "kimi-k2.6-flex": "kimi-k2.7-code-flex",
18
+ "moonshotai/Kimi-K2.6": "kimi-k2.7-code",
19
+ // Qwen 3.5 retired 8/3, redirected to Qwen 3.6
20
+ "qwen3.5-397b": "qwen3.6-35b",
21
+ "qwen3.5-397b-fast": "qwen3.6-35b-fast",
22
+ "Qwen/Qwen3.5-397B-A17B-FP8": "qwen3.6-35b",
12
23
  } as const;
13
24
 
14
25
  export const LEGACY_NEURALWATT_MODEL_IDS = new Set<string>(
@@ -27,23 +27,29 @@ const GLM_THINKING: ThinkingLevelMap = {
27
27
  max: "max",
28
28
  };
29
29
 
30
- // Binary thinking control: expose a single known-good Pi level.
30
+ // Binary thinking control (Kimi K2.x, Qwen3.x): no graded `reasoning_effort`
31
+ // upstream, only a thinking on/off toggle. Expose a single known-good Pi
32
+ // level; "high" stands in for standard full thinking.
31
33
  const BINARY_THINKING: ThinkingLevelMap = {
32
34
  minimal: null,
33
35
  low: null,
34
- medium: "medium",
35
- high: null,
36
+ medium: null,
37
+ high: "high",
36
38
  xhigh: null,
37
39
  };
38
40
 
39
41
  const DEEPSEEK_V4_FLASH: NeuralwattModelFamily = {
40
- cost: { input: 0.104, output: 0.207, cacheRead: 0.026 },
42
+ cost: { input: 0.14, output: 0.28, cacheRead: 0.028 },
41
43
  vision: false,
44
+ // DeepSeek V4 Flash accepts reasoning_effort low/high/max (default high);
45
+ // there is no "medium" tier, so Pi's low/high/max map directly and
46
+ // minimal/medium/xhigh are unsupported holes.
47
+ // https://api-docs.deepseek.com/guides/thinking_mode/
42
48
  thinkingLevelMap: {
43
49
  off: "none",
44
- minimal: "low",
50
+ minimal: null,
45
51
  low: "low",
46
- medium: "medium",
52
+ medium: null,
47
53
  high: "high",
48
54
  xhigh: null,
49
55
  max: "max",
@@ -52,41 +58,47 @@ const DEEPSEEK_V4_FLASH: NeuralwattModelFamily = {
52
58
 
53
59
  // Google, served from NVIDIA's NVFP4 checkpoint.
54
60
  const GEMMA_4: NeuralwattModelFamily = {
55
- cost: { input: 0.144, output: 0.42, cacheRead: 0.036 },
61
+ cost: { input: 0.144, output: 0.42, cacheRead: 0.0144 },
56
62
  vision: true,
57
63
  };
58
64
 
59
65
  // ZhipuAI.
60
66
  const GLM_5_2: NeuralwattModelFamily = {
61
- cost: { input: 1.45, output: 4.5, cacheRead: 0.3625 },
67
+ cost: { input: 1.45, output: 4.5, cacheRead: 0.145 },
62
68
  vision: false,
63
69
  thinkingLevelMap: GLM_THINKING,
64
70
  };
65
71
 
66
- // MoonshotAI.
67
- const KIMI_K2_6: NeuralwattModelFamily = {
68
- cost: { input: 0.69, output: 3.22, cacheRead: 0.1725 },
72
+ // MoonshotAI. K3 is the largest open-weight model ever released, served in
73
+ // preview with limited concurrency. K3 always reasons (thinking cannot be
74
+ // disabled) and supports `reasoning_effort` values "low", "high", and "max"
75
+ // (default "max"). There is no "medium" tier upstream, so Pi's low/high/max
76
+ // map directly and `off`, `minimal`, `medium`, and `xhigh` are unsupported
77
+ // holes. The `-fast` endpoint is a shorthand to set thinking to off.
78
+ const KIMI_K3: NeuralwattModelFamily = {
79
+ cost: { input: 3, output: 15, cacheRead: 0.3 },
69
80
  vision: true,
70
- thinkingLevelMap: BINARY_THINKING,
81
+ thinkingLevelMap: {
82
+ off: null,
83
+ minimal: null,
84
+ low: "low",
85
+ medium: null,
86
+ high: "high",
87
+ xhigh: null,
88
+ max: "max",
89
+ },
71
90
  };
72
91
 
73
92
  // MoonshotAI.
74
93
  const KIMI_K2_7_CODE: NeuralwattModelFamily = {
75
- cost: { input: 0.95, output: 4.0, cacheRead: 0.2375 },
94
+ cost: { input: 0.95, output: 4.0, cacheRead: 0.095 },
76
95
  vision: true,
77
96
  thinkingLevelMap: { off: null, ...BINARY_THINKING },
78
97
  };
79
98
 
80
- // Qwen.
81
- const QWEN_3_5_397B: NeuralwattModelFamily = {
82
- cost: { input: 0.69, output: 4.14, cacheRead: 0.1725 },
83
- vision: false,
84
- thinkingLevelMap: BINARY_THINKING,
85
- };
86
-
87
99
  // Qwen.
88
100
  const QWEN_3_6_35B: NeuralwattModelFamily = {
89
- cost: { input: 0.29, output: 1.15, cacheRead: 0.0725 },
101
+ cost: { input: 0.29, output: 1.15, cacheRead: 0.029 },
90
102
  vision: true,
91
103
  thinkingLevelMap: BINARY_THINKING,
92
104
  };
@@ -174,30 +186,22 @@ const FAMILIES: [NeuralwattModelFamily, NeuralwattVariantSpec[]][] = [
174
186
  ],
175
187
  ],
176
188
  [
177
- KIMI_K2_6,
189
+ KIMI_K3,
178
190
  [
179
191
  {
180
- id: "kimi-k2.6",
181
- name: "Kimi K2.6",
182
- contextWindow: 262128,
192
+ id: "kimi-k3",
193
+ name: "Kimi K3",
194
+ contextWindow: 1048560,
183
195
  maxOutputTokens: null,
184
196
  reasoning: true,
185
197
  },
186
198
  {
187
- id: "kimi-k2.6-fast",
188
- name: "Kimi K2.6 Fast",
189
- contextWindow: 262128,
199
+ id: "kimi-k3-fast",
200
+ name: "Kimi K3 Fast",
201
+ contextWindow: 1048560,
190
202
  maxOutputTokens: null,
191
203
  reasoning: false,
192
204
  },
193
- {
194
- id: "kimi-k2.6-flex",
195
- name: "Kimi K2.6 (flex)",
196
- contextWindow: 262128,
197
- maxOutputTokens: null,
198
- reasoning: true,
199
- costMultiplier: FLEX_COST_MULTIPLIER,
200
- },
201
205
  ],
202
206
  ],
203
207
  [
@@ -227,25 +231,6 @@ const FAMILIES: [NeuralwattModelFamily, NeuralwattVariantSpec[]][] = [
227
231
  },
228
232
  ],
229
233
  ],
230
- [
231
- QWEN_3_5_397B,
232
- [
233
- {
234
- id: "qwen3.5-397b",
235
- name: "Qwen3.5 397B",
236
- contextWindow: 262128,
237
- maxOutputTokens: null,
238
- reasoning: true,
239
- },
240
- {
241
- id: "qwen3.5-397b-fast",
242
- name: "Qwen3.5 397B Fast",
243
- contextWindow: 262128,
244
- maxOutputTokens: null,
245
- reasoning: false,
246
- },
247
- ],
248
- ],
249
234
  [
250
235
  QWEN_3_6_35B,
251
236
  [
@@ -269,8 +254,9 @@ const FAMILIES: [NeuralwattModelFamily, NeuralwattVariantSpec[]][] = [
269
254
 
270
255
  // `-flex` variants are the Flex tier: same model, context window, output cap,
271
256
  // and prompt cache as the standard variant, admitted on spare capacity.
272
- // /v1/models does not advertise them (not even to an authenticated key), so they
273
- // stay hardcoded here and the drift check in models.test.ts skips them.
257
+ // The API now advertises flex variants but lists them at standard pricing;
258
+ // the 35% Flex discount is a billing-time concept applied here via
259
+ // `costMultiplier` rather than reflected in the catalog metadata.
274
260
  // https://portal.neuralwatt.com/docs/guides/flex-tier
275
261
 
276
262
  export const NEURALWATT_MODELS: ProviderModelConfig[] = FAMILIES.flatMap(
@@ -17,7 +17,8 @@ export default async function (pi: ExtensionAPI) {
17
17
  await configLoader.load();
18
18
 
19
19
  let enabled = configLoader.getConfig().quotaWarnings.enabled;
20
- let currentContext: ExtensionContext | undefined;
20
+ let currentProvider: string | undefined;
21
+ let unsubscribeQuotas: (() => void) | undefined;
21
22
 
22
23
  // Listen for config changes at runtime
23
24
  pi.events.on(NEURALWATT_CONFIG_UPDATED_EVENT, (data: unknown) => {
@@ -29,32 +30,44 @@ export default async function (pi: ExtensionAPI) {
29
30
  }
30
31
  });
31
32
 
32
- pi.events.on(NEURALWATT_QUOTAS_UPDATED_EVENT, (data: unknown) => {
33
+ // The quota handler runs on the shared event bus, so it must only touch a
34
+ // session ctx captured by a live session-scoped subscription: pi
35
+ // invalidates session-bound ctx after session replacement (newSession/
36
+ // fork/switchSession/reload), and dereferencing a stale ctx throws. We
37
+ // subscribe in session_start (capturing the fresh ctx in the closure) and
38
+ // unsubscribe in session_shutdown, before the ctx can go stale.
39
+ function handleQuotas(ctx: ExtensionContext, data: unknown): void {
33
40
  if (!enabled) return;
34
41
  if (!data || typeof data !== "object") return;
35
- if (!currentContext) return;
36
- if (currentContext.model?.provider !== "neuralwatt") return;
42
+ if (currentProvider !== "neuralwatt") return;
37
43
 
38
44
  const { quotas } = data as NeuralwattQuotasUpdatedPayload;
39
- checkQuotas(currentContext, quotas);
40
- });
45
+ checkQuotas(ctx, quotas);
46
+ }
41
47
 
42
48
  pi.on("session_start", async (_event, ctx) => {
43
- currentContext = ctx;
44
- if (ctx.model?.provider !== "neuralwatt") return;
49
+ unsubscribeQuotas?.();
50
+ currentProvider = ctx.model?.provider;
51
+ unsubscribeQuotas = pi.events.on(NEURALWATT_QUOTAS_UPDATED_EVENT, (data) =>
52
+ handleQuotas(ctx, data),
53
+ );
54
+
55
+ if (currentProvider !== "neuralwatt") return;
45
56
  clearAlertState();
46
57
  });
47
58
 
48
59
  pi.on("model_select", (_event, ctx) => {
49
- currentContext = ctx;
60
+ currentProvider = ctx.model?.provider;
50
61
  });
51
62
 
52
63
  pi.on("session_before_switch", (_event, ctx) => {
53
- currentContext = ctx;
64
+ currentProvider = ctx.model?.provider;
54
65
  });
55
66
 
56
67
  pi.on("session_shutdown", () => {
57
- currentContext = undefined;
68
+ unsubscribeQuotas?.();
69
+ unsubscribeQuotas = undefined;
70
+ currentProvider = undefined;
58
71
  clearAlertState();
59
72
  });
60
73
 
@@ -57,7 +57,7 @@ export default async function (pi: ExtensionAPI) {
57
57
  let enabled = configLoader.getConfig().subBarIntegration.enabled;
58
58
  let subCoreReady = false;
59
59
  let currentProvider: string | undefined;
60
- let currentContext: ExtensionContext | undefined;
60
+ let unsubscribeQuotas: (() => void) | undefined;
61
61
 
62
62
  // Listen for config changes at runtime
63
63
  pi.events.on(NEURALWATT_CONFIG_UPDATED_EVENT, (data: unknown) => {
@@ -82,32 +82,35 @@ export default async function (pi: ExtensionAPI) {
82
82
  pi.events.emit(NEURALWATT_QUOTAS_REQUEST_EVENT, undefined);
83
83
  }
84
84
 
85
- pi.events.on(NEURALWATT_QUOTAS_UPDATED_EVENT, (data: unknown) => {
85
+ // The quota handler runs on the shared event bus, so it must only touch a
86
+ // session ctx captured by a live session-scoped subscription: pi
87
+ // invalidates session-bound ctx after session replacement (newSession/
88
+ // fork/switchSession/reload), and dereferencing a stale ctx throws. We
89
+ // subscribe in session_start (capturing the fresh ctx in the closure) and
90
+ // unsubscribe in session_shutdown, before the ctx can go stale.
91
+ function handleQuotas(ctx: ExtensionContext, data: unknown): void {
86
92
  if (!isActive() || !subCoreReady || !enabled) return;
87
93
  if (!data || typeof data !== "object") return;
88
94
  const { quotas } = data as NeuralwattQuotasUpdatedPayload;
89
95
  emitUsage(quotas);
90
96
 
91
- if (currentContext) {
92
- currentContext.ui.setStatus(
93
- "neuralwatt-usage",
94
- formatStatus(quotas, currentContext.ui.theme),
95
- );
96
- }
97
- });
97
+ ctx.ui.setStatus("neuralwatt-usage", formatStatus(quotas, ctx.ui.theme));
98
+ }
98
99
 
99
100
  pi.events.on("sub-core:ready", () => {
100
101
  subCoreReady = true;
101
102
  });
102
103
 
103
104
  pi.on("session_start", async (_event, ctx) => {
105
+ unsubscribeQuotas?.();
104
106
  currentProvider = ctx.model?.provider;
105
- currentContext = ctx;
107
+ unsubscribeQuotas = pi.events.on(NEURALWATT_QUOTAS_UPDATED_EVENT, (data) =>
108
+ handleQuotas(ctx, data),
109
+ );
106
110
  });
107
111
 
108
112
  pi.on("model_select", async (_event, ctx) => {
109
113
  currentProvider = ctx.model?.provider;
110
- currentContext = ctx;
111
114
 
112
115
  if (subCoreReady && isActive() && enabled) {
113
116
  requestQuotas();
@@ -115,8 +118,9 @@ export default async function (pi: ExtensionAPI) {
115
118
  });
116
119
 
117
120
  pi.on("session_shutdown", () => {
121
+ unsubscribeQuotas?.();
122
+ unsubscribeQuotas = undefined;
118
123
  currentProvider = undefined;
119
- currentContext = undefined;
120
124
  });
121
125
 
122
126
  pi.events.on(NEURALWATT_EXTENSIONS_REQUEST_EVENT, () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aliou/pi-neuralwatt",
3
- "version": "0.11.0",
3
+ "version": "0.11.2",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "private": false,