@aliou/pi-neuralwatt 0.7.4 → 0.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.
Files changed (37) hide show
  1. package/README.md +4 -2
  2. package/{src/extensions → extensions}/command-quotas/command.ts +2 -2
  3. package/extensions/command-quotas/components/progress-bar.ts +38 -0
  4. package/{src/extensions → extensions}/command-quotas/components/quota-tabs.ts +4 -4
  5. package/{src/extensions → extensions}/command-quotas/components/quotas-display.ts +1 -1
  6. package/{src/extensions → extensions}/command-quotas/index.ts +3 -3
  7. package/extensions/provider/commands/settings/index.ts +246 -0
  8. package/{src/extensions → extensions}/provider/index.ts +28 -20
  9. package/{src/extensions → extensions}/provider/models/hidden.ts +3 -3
  10. package/{src/extensions → extensions}/provider/models/legacy.ts +2 -0
  11. package/{src/extensions → extensions}/provider/models/public-models.ts +132 -46
  12. package/{src/extensions → extensions}/provider/quota-store.ts +4 -4
  13. package/{src/extensions → extensions}/provider/sse-quotas.ts +1 -1
  14. package/{src/extensions → extensions}/quota-warnings/index.ts +6 -7
  15. package/{src/extensions → extensions}/quota-warnings/notifier.ts +2 -2
  16. package/{src/extensions → extensions}/sub-bar-integration/index.ts +9 -10
  17. package/{src/extensions → extensions}/sub-bar-integration/snapshot.ts +3 -3
  18. package/package.json +20 -14
  19. package/schema.json +50 -6
  20. package/src/config/defaults.ts +17 -0
  21. package/src/config/index.ts +9 -0
  22. package/src/config/loader.ts +74 -0
  23. package/src/config/migration/01-disable-legacy-model-ids-by-default.ts +44 -0
  24. package/src/config/migration/02-flat-to-nested-config.ts +149 -0
  25. package/src/config/migration/index.ts +16 -0
  26. package/src/config/types.ts +77 -0
  27. package/src/{types/quota-events.ts → events.ts} +25 -13
  28. package/src/lib/neuralwatt-api.ts +1 -1
  29. package/src/types/quota-result.ts +12 -0
  30. package/src/utils/quota-bar.ts +0 -38
  31. package/src/config.ts +0 -210
  32. /package/{src/lib/env.ts → extensions/_shared/auth.ts} +0 -0
  33. /package/{src/extensions → extensions}/provider/context-overflow.ts +0 -0
  34. /package/{src/extensions → extensions}/provider/models/cache.ts +0 -0
  35. /package/{src/extensions → extensions}/provider/models/index.ts +0 -0
  36. /package/{src/extensions → extensions}/provider/rate-limit-error.ts +0 -0
  37. /package/{src/extensions → extensions}/provider/stream-simple.ts +0 -0
@@ -18,6 +18,7 @@ export const NEURALWATT_MODELS: ProviderModelConfig[] = [
18
18
  contextWindow: 1048560,
19
19
  maxTokens: 65536,
20
20
  thinkingLevelMap: {
21
+ off: "none",
21
22
  minimal: null,
22
23
  low: null,
23
24
  medium: null,
@@ -64,6 +65,7 @@ export const NEURALWATT_MODELS: ProviderModelConfig[] = [
64
65
  contextWindow: 199984,
65
66
  maxTokens: 65536,
66
67
  thinkingLevelMap: {
68
+ off: "none",
67
69
  minimal: null,
68
70
  low: null,
69
71
  medium: null,
@@ -95,52 +97,6 @@ export const NEURALWATT_MODELS: ProviderModelConfig[] = [
95
97
  maxTokensField: "max_tokens",
96
98
  },
97
99
  },
98
- // Kimi K2.5 - MoonshotAI
99
- {
100
- id: "moonshotai/Kimi-K2.5",
101
- name: "Kimi K2.5",
102
- reasoning: true,
103
- input: ["text", "image"],
104
- cost: {
105
- input: 0.52,
106
- output: 2.59,
107
- cacheRead: 0.13,
108
- cacheWrite: 0,
109
- },
110
- contextWindow: 262128,
111
- maxTokens: 65536,
112
- thinkingLevelMap: {
113
- minimal: null,
114
- low: null,
115
- medium: "medium",
116
- high: null,
117
- xhigh: null,
118
- },
119
- compat: {
120
- supportsDeveloperRole: false,
121
- maxTokensField: "max_tokens",
122
- requiresReasoningContentOnAssistantMessages: true,
123
- },
124
- },
125
- // Kimi K2.5 Fast - MoonshotAI
126
- {
127
- id: "kimi-k2.5-fast",
128
- name: "Kimi K2.5 Fast",
129
- reasoning: false,
130
- input: ["text", "image"],
131
- cost: {
132
- input: 0.52,
133
- output: 2.59,
134
- cacheRead: 0.13,
135
- cacheWrite: 0,
136
- },
137
- contextWindow: 262128,
138
- maxTokens: 65536,
139
- compat: {
140
- supportsDeveloperRole: false,
141
- maxTokensField: "max_tokens",
142
- },
143
- },
144
100
  // Kimi K2.6 - MoonshotAI
145
101
  {
146
102
  id: "kimi-k2.6",
@@ -288,6 +244,136 @@ export const NEURALWATT_MODELS: ProviderModelConfig[] = [
288
244
  requiresReasoningContentOnAssistantMessages: true,
289
245
  },
290
246
  },
247
+ // GLM-5.2 Short Fast Flex - ZhipuAI (flex variant, reasoning disabled)
248
+ {
249
+ id: "glm-5.2-short-fast-flex",
250
+ name: "GLM-5.2 (short, fast, flex)",
251
+ reasoning: false,
252
+ input: ["text"],
253
+ cost: {
254
+ input: 1.45,
255
+ output: 4.5,
256
+ cacheRead: 0.3625,
257
+ cacheWrite: 0,
258
+ },
259
+ contextWindow: 199984,
260
+ maxTokens: 65536,
261
+ compat: {
262
+ supportsDeveloperRole: false,
263
+ maxTokensField: "max_tokens",
264
+ },
265
+ },
266
+ // GLM-5.2 Short Flex - ZhipuAI (flex variant)
267
+ {
268
+ id: "glm-5.2-short-flex",
269
+ name: "GLM-5.2 (short, flex)",
270
+ reasoning: true,
271
+ input: ["text"],
272
+ cost: {
273
+ input: 1.45,
274
+ output: 4.5,
275
+ cacheRead: 0.3625,
276
+ cacheWrite: 0,
277
+ },
278
+ contextWindow: 199984,
279
+ maxTokens: 65536,
280
+ thinkingLevelMap: {
281
+ off: "none",
282
+ minimal: null,
283
+ low: null,
284
+ medium: null,
285
+ high: "high",
286
+ xhigh: "max",
287
+ },
288
+ compat: {
289
+ supportsDeveloperRole: false,
290
+ maxTokensField: "max_tokens",
291
+ requiresReasoningContentOnAssistantMessages: true,
292
+ },
293
+ },
294
+ // Kimi K2.6 Flex - MoonshotAI (flex variant)
295
+ {
296
+ id: "kimi-k2.6-flex",
297
+ name: "Kimi K2.6 (flex)",
298
+ reasoning: true,
299
+ input: ["text", "image"],
300
+ cost: {
301
+ input: 0.69,
302
+ output: 3.22,
303
+ cacheRead: 0.1725,
304
+ cacheWrite: 0,
305
+ },
306
+ contextWindow: 262128,
307
+ maxTokens: 65536,
308
+ thinkingLevelMap: {
309
+ minimal: null,
310
+ low: null,
311
+ medium: "medium",
312
+ high: null,
313
+ xhigh: null,
314
+ },
315
+ compat: {
316
+ supportsDeveloperRole: false,
317
+ maxTokensField: "max_tokens",
318
+ requiresReasoningContentOnAssistantMessages: true,
319
+ },
320
+ },
321
+ // Kimi K2.7 Code Flex - MoonshotAI (flex variant)
322
+ {
323
+ id: "kimi-k2.7-code-flex",
324
+ name: "Kimi K2.7 Code (flex)",
325
+ reasoning: true,
326
+ input: ["text", "image"],
327
+ cost: {
328
+ input: 0.95,
329
+ output: 4.0,
330
+ cacheRead: 0.2375,
331
+ cacheWrite: 0,
332
+ },
333
+ contextWindow: 262128,
334
+ maxTokens: 65536,
335
+ thinkingLevelMap: {
336
+ off: null,
337
+ minimal: null,
338
+ low: null,
339
+ medium: "medium",
340
+ high: null,
341
+ xhigh: null,
342
+ },
343
+ compat: {
344
+ supportsDeveloperRole: false,
345
+ maxTokensField: "max_tokens",
346
+ requiresReasoningContentOnAssistantMessages: true,
347
+ },
348
+ },
349
+ // GLM-5.2 Flex - ZhipuAI (flex variant)
350
+ {
351
+ id: "glm-5.2-flex",
352
+ name: "GLM-5.2 (flex)",
353
+ reasoning: true,
354
+ input: ["text"],
355
+ cost: {
356
+ input: 1.45,
357
+ output: 4.5,
358
+ cacheRead: 0.3625,
359
+ cacheWrite: 0,
360
+ },
361
+ contextWindow: 1048560,
362
+ maxTokens: 65536,
363
+ thinkingLevelMap: {
364
+ off: "none",
365
+ minimal: null,
366
+ low: null,
367
+ medium: null,
368
+ high: "high",
369
+ xhigh: "max",
370
+ },
371
+ compat: {
372
+ supportsDeveloperRole: false,
373
+ maxTokensField: "max_tokens",
374
+ requiresReasoningContentOnAssistantMessages: true,
375
+ },
376
+ },
291
377
  // Qwen3.6 35B Fast - Qwen
292
378
  {
293
379
  id: "qwen3.6-35b-fast",
@@ -1,8 +1,8 @@
1
1
  import type { AuthStorage } from "@earendil-works/pi-coding-agent";
2
- import { getNeuralwattApiKey } from "../../lib/env";
3
- import { fetchQuotas } from "../../lib/neuralwatt-api";
4
- import type { NeuralwattQuotas } from "../../types/quota-api";
5
- import { parseQuotaHeaders } from "../../types/quota-events";
2
+ import { parseQuotaHeaders } from "../../src/events";
3
+ import { fetchQuotas } from "../../src/lib/neuralwatt-api";
4
+ import type { NeuralwattQuotas } from "../../src/types/quota-api";
5
+ import { getNeuralwattApiKey } from "../_shared/auth";
6
6
 
7
7
  export function buildQuotasFromHeaders(
8
8
  headers: Record<string, string>,
@@ -1,4 +1,4 @@
1
- import type { NeuralwattQuotas } from "../../types/quota-api";
1
+ import type { NeuralwattQuotas } from "../../src/types/quota-api";
2
2
 
3
3
  const JOULES_PER_KWH = 3_600_000;
4
4
 
@@ -2,29 +2,28 @@ import type {
2
2
  ExtensionAPI,
3
3
  ExtensionContext,
4
4
  } from "@earendil-works/pi-coding-agent";
5
+ import { configLoader } from "../../src/config";
5
6
  import {
6
- configLoader,
7
7
  NEURALWATT_CONFIG_UPDATED_EVENT,
8
8
  NEURALWATT_EXTENSIONS_REGISTER_EVENT,
9
9
  NEURALWATT_EXTENSIONS_REQUEST_EVENT,
10
- type NeuralwattConfigUpdatedPayload,
11
- } from "../../config";
12
- import {
13
10
  NEURALWATT_QUOTAS_UPDATED_EVENT,
11
+ type NeuralwattConfigUpdatedPayload,
14
12
  type NeuralwattQuotasUpdatedPayload,
15
- } from "../../types/quota-events";
13
+ } from "../../src/events";
16
14
  import { checkQuotas, clearAlertState } from "./notifier";
17
15
 
18
16
  export default async function (pi: ExtensionAPI) {
19
17
  await configLoader.load();
20
18
 
21
- let enabled = configLoader.getConfig().quotaWarnings;
19
+ let enabled = configLoader.getConfig().quotaWarnings.enabled;
22
20
  let currentProvider: string | undefined;
23
21
  let currentContext: ExtensionContext | undefined;
24
22
 
25
23
  // Listen for config changes at runtime
26
24
  pi.events.on(NEURALWATT_CONFIG_UPDATED_EVENT, (data: unknown) => {
27
- enabled = (data as NeuralwattConfigUpdatedPayload).config.quotaWarnings;
25
+ enabled = (data as NeuralwattConfigUpdatedPayload).config.quotaWarnings
26
+ .enabled;
28
27
 
29
28
  if (!enabled) {
30
29
  clearAlertState();
@@ -1,6 +1,6 @@
1
1
  import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
2
- import type { NeuralwattQuotas } from "../../types/quota-api";
3
- import { formatKwh, formatUsd } from "../../utils/quota-format";
2
+ import type { NeuralwattQuotas } from "../../src/types/quota-api";
3
+ import { formatKwh, formatUsd } from "../../src/utils/quota-format";
4
4
 
5
5
  export type WarningSeverity = "warning" | "critical";
6
6
 
@@ -4,24 +4,22 @@ import type {
4
4
  ExtensionContext,
5
5
  Theme,
6
6
  } from "@earendil-works/pi-coding-agent";
7
+ import { configLoader } from "../../src/config";
7
8
  import {
8
- configLoader,
9
9
  NEURALWATT_CONFIG_UPDATED_EVENT,
10
10
  NEURALWATT_EXTENSIONS_REGISTER_EVENT,
11
11
  NEURALWATT_EXTENSIONS_REQUEST_EVENT,
12
- type NeuralwattConfigUpdatedPayload,
13
- } from "../../config";
14
- import type { NeuralwattQuotas } from "../../types/quota-api";
15
- import {
16
12
  NEURALWATT_QUOTAS_REQUEST_EVENT,
17
13
  NEURALWATT_QUOTAS_UPDATED_EVENT,
14
+ type NeuralwattConfigUpdatedPayload,
18
15
  type NeuralwattQuotasUpdatedPayload,
19
- } from "../../types/quota-events";
16
+ } from "../../src/events";
17
+ import type { NeuralwattQuotas } from "../../src/types/quota-api";
20
18
  import {
21
19
  percentCreditsRemaining,
22
20
  percentEnergyRemaining,
23
- } from "../../utils/quota-bar";
24
- import { formatKwh, formatUsd } from "../../utils/quota-format";
21
+ } from "../../src/utils/quota-bar";
22
+ import { formatKwh, formatUsd } from "../../src/utils/quota-format";
25
23
  import { toUsageSnapshot } from "./snapshot";
26
24
 
27
25
  function formatStatus(quotas: NeuralwattQuotas, theme: Theme): string {
@@ -57,7 +55,7 @@ function formatStatus(quotas: NeuralwattQuotas, theme: Theme): string {
57
55
  export default async function (pi: ExtensionAPI) {
58
56
  await configLoader.load();
59
57
 
60
- let enabled = configLoader.getConfig().subBarIntegration;
58
+ let enabled = configLoader.getConfig().subBarIntegration.enabled;
61
59
  let subCoreReady = false;
62
60
  let currentProvider: string | undefined;
63
61
  let currentAuthStorage: AuthStorage | undefined;
@@ -65,7 +63,8 @@ export default async function (pi: ExtensionAPI) {
65
63
 
66
64
  // Listen for config changes at runtime
67
65
  pi.events.on(NEURALWATT_CONFIG_UPDATED_EVENT, (data: unknown) => {
68
- enabled = (data as NeuralwattConfigUpdatedPayload).config.subBarIntegration;
66
+ enabled = (data as NeuralwattConfigUpdatedPayload).config.subBarIntegration
67
+ .enabled;
69
68
  });
70
69
 
71
70
  function isActive(): boolean {
@@ -1,9 +1,9 @@
1
- import type { NeuralwattQuotas } from "../../types/quota-api";
1
+ import type { NeuralwattQuotas } from "../../src/types/quota-api";
2
2
  import {
3
3
  percentCreditsRemaining,
4
4
  percentEnergyRemaining,
5
- } from "../../utils/quota-bar";
6
- import { formatKwh } from "../../utils/quota-format";
5
+ } from "../../src/utils/quota-bar";
6
+ import { formatKwh } from "../../src/utils/quota-format";
7
7
 
8
8
  interface RateWindow {
9
9
  label: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aliou/pi-neuralwatt",
3
- "version": "0.7.4",
3
+ "version": "0.8.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "private": false,
@@ -15,10 +15,10 @@
15
15
  },
16
16
  "pi": {
17
17
  "extensions": [
18
- "./src/extensions/provider/index.ts",
19
- "./src/extensions/command-quotas/index.ts",
20
- "./src/extensions/quota-warnings/index.ts",
21
- "./src/extensions/sub-bar-integration/index.ts"
18
+ "./extensions/provider/index.ts",
19
+ "./extensions/command-quotas/index.ts",
20
+ "./extensions/quota-warnings/index.ts",
21
+ "./extensions/sub-bar-integration/index.ts"
22
22
  ],
23
23
  "video": "https://assets.aliou.me/github/aliou/pi-neuralwatt/demo.mp4"
24
24
  },
@@ -27,25 +27,28 @@
27
27
  },
28
28
  "files": [
29
29
  "src",
30
+ "extensions",
30
31
  "schema.json",
31
32
  "README.md",
32
- "!src/**/*.test.ts"
33
+ "!src/**/*.test.ts",
34
+ "!extensions/**/*.test.ts"
33
35
  ],
34
36
  "dependencies": {
35
- "@aliou/pi-utils-settings": "^0.17.0",
36
- "@aliou/pi-utils-ui": "^0.4.0",
37
- "@earendil-works/pi-ai": "$@earendil-works/pi-coding-agent"
37
+ "@aliou/pi-utils-settings": "^0.18.0",
38
+ "@aliou/pi-utils-ui": "^0.5.0"
38
39
  },
39
40
  "peerDependencies": {
41
+ "@earendil-works/pi-ai": "*",
40
42
  "@earendil-works/pi-coding-agent": "*",
41
43
  "@earendil-works/pi-tui": "*"
42
44
  },
43
45
  "devDependencies": {
44
- "@aliou/biome-plugins": "^0.8.1",
46
+ "@aliou/biome-plugins": "^0.11.0",
45
47
  "@biomejs/biome": "^2.4.15",
46
48
  "@changesets/cli": "^2.27.11",
47
- "@earendil-works/pi-coding-agent": "0.77.0",
48
- "@earendil-works/pi-tui": "0.77.0",
49
+ "@earendil-works/pi-ai": "0.80.3",
50
+ "@earendil-works/pi-coding-agent": "0.80.3",
51
+ "@earendil-works/pi-tui": "0.80.3",
49
52
  "@types/node": "^25.0.10",
50
53
  "husky": "^9.1.7",
51
54
  "ts-json-schema-generator": "^2.4.0",
@@ -64,8 +67,8 @@
64
67
  "format": "biome check --write",
65
68
  "test": "vitest run",
66
69
  "test:watch": "vitest",
67
- "gen:schema": "ts-json-schema-generator --path src/config.ts --type NeuralwattConfig --no-type-check -o schema.json",
68
- "check:schema": "ts-json-schema-generator --path src/config.ts --type NeuralwattConfig --no-type-check -o /tmp/schema-check.json && diff -q schema.json /tmp/schema-check.json",
70
+ "gen:schema": "ts-json-schema-generator --path src/config/types.ts --type NeuralwattConfig --no-type-check -o schema.json",
71
+ "check:schema": "ts-json-schema-generator --path src/config/types.ts --type NeuralwattConfig --no-type-check -o /tmp/schema-check.json && diff -q schema.json /tmp/schema-check.json",
69
72
  "check:lockfile": "pnpm install --frozen-lockfile --ignore-scripts",
70
73
  "prepare": "[ -d .git ] && husky || true",
71
74
  "changeset": "changeset",
@@ -74,6 +77,9 @@
74
77
  },
75
78
  "packageManager": "pnpm@10.26.1",
76
79
  "peerDependenciesMeta": {
80
+ "@earendil-works/pi-ai": {
81
+ "optional": true
82
+ },
77
83
  "@earendil-works/pi-coding-agent": {
78
84
  "optional": true
79
85
  },
package/schema.json CHANGED
@@ -3,6 +3,32 @@
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
4
  "definitions": {
5
5
  "NeuralwattConfig": {
6
+ "additionalProperties": false,
7
+ "properties": {
8
+ "$schema": {
9
+ "description": "$schema URL for editor autocomplete.",
10
+ "type": "string"
11
+ },
12
+ "provider": {
13
+ "$ref": "#/definitions/NeuralwattProviderConfig",
14
+ "description": "Provider/model behavior."
15
+ },
16
+ "quotaCommand": {
17
+ "$ref": "#/definitions/NeuralwattQuotaCommandConfig",
18
+ "description": "Quota command feature."
19
+ },
20
+ "quotaWarnings": {
21
+ "$ref": "#/definitions/NeuralwattQuotaWarningsConfig",
22
+ "description": "Quota warning feature."
23
+ },
24
+ "subBarIntegration": {
25
+ "$ref": "#/definitions/NeuralwattSubBarIntegrationConfig",
26
+ "description": "Sub-bar/status-bar integration feature."
27
+ }
28
+ },
29
+ "type": "object"
30
+ },
31
+ "NeuralwattProviderConfig": {
6
32
  "additionalProperties": false,
7
33
  "properties": {
8
34
  "includeHiddenModels": {
@@ -12,16 +38,34 @@
12
38
  "includeLegacyModelIds": {
13
39
  "description": "Include legacy Neuralwatt model IDs in the model picker.",
14
40
  "type": "boolean"
15
- },
16
- "quotaCommand": {
41
+ }
42
+ },
43
+ "type": "object"
44
+ },
45
+ "NeuralwattQuotaCommandConfig": {
46
+ "additionalProperties": false,
47
+ "properties": {
48
+ "enabled": {
17
49
  "description": "Show the quota command (/neuralwatt:quota).",
18
50
  "type": "boolean"
19
- },
20
- "quotaWarnings": {
51
+ }
52
+ },
53
+ "type": "object"
54
+ },
55
+ "NeuralwattQuotaWarningsConfig": {
56
+ "additionalProperties": false,
57
+ "properties": {
58
+ "enabled": {
21
59
  "description": "Show quota warnings when credits or energy are low.",
22
60
  "type": "boolean"
23
- },
24
- "subBarIntegration": {
61
+ }
62
+ },
63
+ "type": "object"
64
+ },
65
+ "NeuralwattSubBarIntegrationConfig": {
66
+ "additionalProperties": false,
67
+ "properties": {
68
+ "enabled": {
25
69
  "description": "Show usage in the sub-bar / status bar.",
26
70
  "type": "boolean"
27
71
  }
@@ -0,0 +1,17 @@
1
+ import type { ResolvedNeuralwattConfig } from "./types";
2
+
3
+ export const DEFAULT_CONFIG: ResolvedNeuralwattConfig = {
4
+ provider: {
5
+ includeLegacyModelIds: false,
6
+ includeHiddenModels: false,
7
+ },
8
+ quotaCommand: {
9
+ enabled: true,
10
+ },
11
+ quotaWarnings: {
12
+ enabled: true,
13
+ },
14
+ subBarIntegration: {
15
+ enabled: true,
16
+ },
17
+ };
@@ -0,0 +1,9 @@
1
+ export { DEFAULT_CONFIG } from "./defaults";
2
+ export { configLoader } from "./loader";
3
+ export { migrations } from "./migration";
4
+ export type {
5
+ NeuralwattConfig,
6
+ NeuralwattRawConfig,
7
+ PreviousNeuralwattConfig,
8
+ ResolvedNeuralwattConfig,
9
+ } from "./types";
@@ -0,0 +1,74 @@
1
+ import { buildSchemaUrl, ConfigLoader } from "@aliou/pi-utils-settings";
2
+ import packageJson from "../../package.json";
3
+ import { DEFAULT_CONFIG } from "./defaults";
4
+ import { migrations } from "./migration";
5
+ import type { NeuralwattRawConfig, ResolvedNeuralwattConfig } from "./types";
6
+
7
+ type ConfigRecord = Record<string, unknown>;
8
+
9
+ type MaybeEnabled = { enabled?: boolean };
10
+ type MaybeProvider = {
11
+ includeLegacyModelIds?: boolean;
12
+ includeHiddenModels?: boolean;
13
+ };
14
+
15
+ function featureEnabled(value: unknown, fallback: boolean): boolean {
16
+ if (typeof value === "boolean") return value;
17
+ if (value && typeof value === "object") {
18
+ const { enabled } = value as MaybeEnabled;
19
+ if (typeof enabled === "boolean") return enabled;
20
+ }
21
+ return fallback;
22
+ }
23
+
24
+ function normalizeResolvedConfig(
25
+ resolved: ResolvedNeuralwattConfig,
26
+ ): ResolvedNeuralwattConfig {
27
+ const record = resolved as unknown as ConfigRecord;
28
+ const provider =
29
+ record.provider && typeof record.provider === "object"
30
+ ? (record.provider as MaybeProvider)
31
+ : {};
32
+
33
+ return {
34
+ provider: {
35
+ includeLegacyModelIds:
36
+ provider.includeLegacyModelIds ??
37
+ (typeof record.includeLegacyModelIds === "boolean"
38
+ ? record.includeLegacyModelIds
39
+ : DEFAULT_CONFIG.provider.includeLegacyModelIds),
40
+ includeHiddenModels:
41
+ provider.includeHiddenModels ??
42
+ (typeof record.includeHiddenModels === "boolean"
43
+ ? record.includeHiddenModels
44
+ : DEFAULT_CONFIG.provider.includeHiddenModels),
45
+ },
46
+ quotaCommand: {
47
+ enabled: featureEnabled(
48
+ record.quotaCommand,
49
+ DEFAULT_CONFIG.quotaCommand.enabled,
50
+ ),
51
+ },
52
+ quotaWarnings: {
53
+ enabled: featureEnabled(
54
+ record.quotaWarnings,
55
+ DEFAULT_CONFIG.quotaWarnings.enabled,
56
+ ),
57
+ },
58
+ subBarIntegration: {
59
+ enabled: featureEnabled(
60
+ record.subBarIntegration,
61
+ DEFAULT_CONFIG.subBarIntegration.enabled,
62
+ ),
63
+ },
64
+ };
65
+ }
66
+
67
+ export const configLoader = new ConfigLoader<
68
+ NeuralwattRawConfig,
69
+ ResolvedNeuralwattConfig
70
+ >("neuralwatt", DEFAULT_CONFIG, {
71
+ migrations,
72
+ schemaUrl: buildSchemaUrl("@aliou/pi-neuralwatt", packageJson.version),
73
+ afterMerge: normalizeResolvedConfig,
74
+ });
@@ -0,0 +1,44 @@
1
+ import type { Migration } from "@aliou/pi-utils-settings";
2
+ import type { NeuralwattConfig, PreviousNeuralwattConfig } from "../types";
3
+
4
+ type MigrationConfig = PreviousNeuralwattConfig | NeuralwattConfig;
5
+
6
+ type MutableConfigRecord = Record<string, unknown>;
7
+
8
+ function hasOwn(record: MutableConfigRecord, key: string): boolean {
9
+ return Object.hasOwn(record, key);
10
+ }
11
+
12
+ function hasNestedConfig(config: MigrationConfig): boolean {
13
+ return Boolean(
14
+ ("provider" in config && config.provider) ||
15
+ (config.quotaCommand && typeof config.quotaCommand === "object") ||
16
+ (config.quotaWarnings && typeof config.quotaWarnings === "object") ||
17
+ (config.subBarIntegration &&
18
+ typeof config.subBarIntegration === "object"),
19
+ );
20
+ }
21
+
22
+ function isPreviousConfigWithoutLegacyDefault(
23
+ config: MigrationConfig,
24
+ ): config is PreviousNeuralwattConfig {
25
+ return (
26
+ !hasNestedConfig(config) &&
27
+ !hasOwn(config as MutableConfigRecord, "includeLegacyModelIds")
28
+ );
29
+ }
30
+
31
+ export const disableLegacyModelIdsByDefaultMigration: Migration<MigrationConfig> =
32
+ {
33
+ name: "disable-legacy-model-ids-by-default",
34
+ shouldRun: isPreviousConfigWithoutLegacyDefault,
35
+ message:
36
+ "[neuralwatt] legacy model IDs (ids including the provider and the quantization) are disabled by default. You can enable them with /neuralwatt:settings.",
37
+ run: (config) => {
38
+ const previous = config as PreviousNeuralwattConfig;
39
+ return {
40
+ ...previous,
41
+ includeLegacyModelIds: false,
42
+ };
43
+ },
44
+ };