@victor-software-house/pi-openai-proxy 4.5.0 → 4.6.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/dist/config.d.mts +1 -1
- package/dist/config.mjs +1 -1
- package/dist/exposure.d.mts +9 -4
- package/dist/exposure.mjs +9 -8
- package/dist/index.mjs +20 -9
- package/dist/{schema-B2x0rLJN.d.mts → schema-CrOJW-mE.d.mts} +6 -6
- package/dist/{schema-IE4WK0Dj.mjs → schema-quaXHZsz.mjs} +0 -2
- package/extensions/proxy.ts +68 -24
- package/package.json +2 -2
package/dist/config.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
|
|
2
|
-
import { a as ZedSyncConfig, c as isModelExposureMode, d as normalizeConfig, f as saveConfigToFile, i as PublicModelIdMode, l as isPublicModelIdMode, n as ModelExposureMode, o as configToEnv, r as ProxyConfig, s as getConfigPath, t as DEFAULT_CONFIG, u as loadConfigFromFile } from "./schema-
|
|
2
|
+
import { a as ZedSyncConfig, c as isModelExposureMode, d as normalizeConfig, f as saveConfigToFile, i as PublicModelIdMode, l as isPublicModelIdMode, n as ModelExposureMode, o as configToEnv, r as ProxyConfig, s as getConfigPath, t as DEFAULT_CONFIG, u as loadConfigFromFile } from "./schema-CrOJW-mE.mjs";
|
|
3
3
|
export { DEFAULT_CONFIG, ModelExposureMode, ProxyConfig, PublicModelIdMode, ZedSyncConfig, configToEnv, getConfigPath, isModelExposureMode, isPublicModelIdMode, loadConfigFromFile, normalizeConfig, saveConfigToFile };
|
package/dist/config.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import { a as isPublicModelIdMode, c as saveConfigToFile, i as isModelExposureMode, n as configToEnv, o as loadConfigFromFile, r as getConfigPath, s as normalizeConfig, t as DEFAULT_CONFIG } from "./schema-
|
|
2
|
+
import { a as isPublicModelIdMode, c as saveConfigToFile, i as isModelExposureMode, n as configToEnv, o as loadConfigFromFile, r as getConfigPath, s as normalizeConfig, t as DEFAULT_CONFIG } from "./schema-quaXHZsz.mjs";
|
|
3
3
|
export { DEFAULT_CONFIG, configToEnv, getConfigPath, isModelExposureMode, isPublicModelIdMode, loadConfigFromFile, normalizeConfig, saveConfigToFile };
|
package/dist/exposure.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { i as PublicModelIdMode, n as ModelExposureMode } from "./schema-
|
|
2
|
+
import { i as PublicModelIdMode, n as ModelExposureMode } from "./schema-CrOJW-mE.mjs";
|
|
3
3
|
import { Api, Model } from "@mariozechner/pi-ai";
|
|
4
4
|
|
|
5
5
|
//#region src/openai/model-exposure.d.ts
|
|
@@ -16,7 +16,13 @@ interface ExposedModel {
|
|
|
16
16
|
interface ModelExposureConfig {
|
|
17
17
|
readonly publicModelIdMode: PublicModelIdMode;
|
|
18
18
|
readonly modelExposureMode: ModelExposureMode;
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Canonical model IDs from pi's global `enabledModels` setting.
|
|
21
|
+
* Read from `SettingsManager.getEnabledModels()` at request time.
|
|
22
|
+
* Undefined or empty means no filter (all available models exposed).
|
|
23
|
+
* Used only when modelExposureMode is "scoped".
|
|
24
|
+
*/
|
|
25
|
+
readonly enabledModels: readonly string[] | undefined;
|
|
20
26
|
readonly customModels: readonly string[];
|
|
21
27
|
readonly providerPrefixes: Readonly<Record<string, string>>;
|
|
22
28
|
}
|
|
@@ -38,12 +44,11 @@ type ModelExposureOutcome = ModelExposureResult | ModelExposureError;
|
|
|
38
44
|
* Compute the full model-exposure result from config and available models.
|
|
39
45
|
*
|
|
40
46
|
* @param available - Models with auth configured (pi's getAvailable())
|
|
41
|
-
* @param allRegistered - All registered models regardless of auth (pi's getAll())
|
|
42
47
|
* @param config - Model exposure configuration
|
|
43
48
|
*
|
|
44
49
|
* Call this at startup and whenever config or the model registry changes.
|
|
45
50
|
*/
|
|
46
|
-
declare function computeModelExposure(available: readonly Model<Api>[],
|
|
51
|
+
declare function computeModelExposure(available: readonly Model<Api>[], config: ModelExposureConfig): ModelExposureOutcome;
|
|
47
52
|
/**
|
|
48
53
|
* Resolve a model ID from an incoming request against the exposure result.
|
|
49
54
|
*
|
package/dist/exposure.mjs
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
//#region src/openai/model-exposure.ts
|
|
3
|
-
function filterExposedModels(available,
|
|
3
|
+
function filterExposedModels(available, config) {
|
|
4
4
|
switch (config.modelExposureMode) {
|
|
5
|
+
case "all": return [...available];
|
|
5
6
|
case "scoped": {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const enabled = config.enabledModels;
|
|
8
|
+
if (enabled === void 0 || enabled.length === 0) return [...available];
|
|
9
|
+
const allowed = new Set(enabled);
|
|
10
|
+
return available.filter((m) => allowed.has(`${m.provider}/${m.id}`));
|
|
9
11
|
}
|
|
10
|
-
case "all": return [...allRegistered];
|
|
11
12
|
case "custom": {
|
|
13
|
+
if (config.customModels.length === 0) return [...available];
|
|
12
14
|
const allowed = new Set(config.customModels);
|
|
13
15
|
return available.filter((m) => allowed.has(`${m.provider}/${m.id}`));
|
|
14
16
|
}
|
|
@@ -127,13 +129,12 @@ function validatePrefixUniqueness(models, prefixes, mode) {
|
|
|
127
129
|
* Compute the full model-exposure result from config and available models.
|
|
128
130
|
*
|
|
129
131
|
* @param available - Models with auth configured (pi's getAvailable())
|
|
130
|
-
* @param allRegistered - All registered models regardless of auth (pi's getAll())
|
|
131
132
|
* @param config - Model exposure configuration
|
|
132
133
|
*
|
|
133
134
|
* Call this at startup and whenever config or the model registry changes.
|
|
134
135
|
*/
|
|
135
|
-
function computeModelExposure(available,
|
|
136
|
-
const exposed = filterExposedModels(available,
|
|
136
|
+
function computeModelExposure(available, config) {
|
|
137
|
+
const exposed = filterExposedModels(available, config);
|
|
137
138
|
const prefixError = validatePrefixUniqueness(exposed, config.providerPrefixes, config.publicModelIdMode);
|
|
138
139
|
if (prefixError !== void 0) return {
|
|
139
140
|
ok: false,
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import { l as isRecord, o as loadConfigFromFile, r as getConfigPath } from "./schema-
|
|
2
|
+
import { l as isRecord, o as loadConfigFromFile, r as getConfigPath } from "./schema-quaXHZsz.mjs";
|
|
3
3
|
import { computeModelExposure, resolveExposedModel } from "./exposure.mjs";
|
|
4
4
|
import * as z from "zod";
|
|
5
|
-
import { AuthStorage, ModelRegistry } from "@mariozechner/pi-coding-agent";
|
|
5
|
+
import { AuthStorage, ModelRegistry, SettingsManager } from "@mariozechner/pi-coding-agent";
|
|
6
6
|
import { randomBytes } from "node:crypto";
|
|
7
7
|
import { Type } from "@sinclair/typebox";
|
|
8
8
|
import { completeSimple, streamSimple } from "@mariozechner/pi-ai";
|
|
@@ -38,7 +38,6 @@ function loadConfig(cli = {}) {
|
|
|
38
38
|
upstreamTimeoutMs,
|
|
39
39
|
publicModelIdMode: file.publicModelIdMode,
|
|
40
40
|
modelExposureMode: file.modelExposureMode,
|
|
41
|
-
scopedProviders: file.scopedProviders,
|
|
42
41
|
customModels: file.customModels,
|
|
43
42
|
providerPrefixes: file.providerPrefixes
|
|
44
43
|
};
|
|
@@ -47,19 +46,25 @@ function loadConfig(cli = {}) {
|
|
|
47
46
|
//#region src/pi/registry.ts
|
|
48
47
|
let registry;
|
|
49
48
|
let authStorage;
|
|
49
|
+
let settingsManager;
|
|
50
50
|
/**
|
|
51
|
-
* Initialize the registry. Call once at startup.
|
|
51
|
+
* Initialize the registry and settings. Call once at startup.
|
|
52
52
|
* Returns the load error if models.json failed to parse, or undefined on success.
|
|
53
53
|
*/
|
|
54
54
|
function initRegistry() {
|
|
55
55
|
authStorage = AuthStorage.create();
|
|
56
56
|
registry = new ModelRegistry(authStorage);
|
|
57
|
+
settingsManager = SettingsManager.create();
|
|
57
58
|
return registry.getError();
|
|
58
59
|
}
|
|
59
60
|
function getRegistry() {
|
|
60
61
|
if (registry === void 0) throw new Error("ModelRegistry not initialized. Call initRegistry() first.");
|
|
61
62
|
return registry;
|
|
62
63
|
}
|
|
64
|
+
function getSettingsManager() {
|
|
65
|
+
if (settingsManager === void 0) throw new Error("SettingsManager not initialized. Call initRegistry() first.");
|
|
66
|
+
return settingsManager;
|
|
67
|
+
}
|
|
63
68
|
/**
|
|
64
69
|
* Get all models available (have auth configured).
|
|
65
70
|
*/
|
|
@@ -67,10 +72,16 @@ function getAvailableModels() {
|
|
|
67
72
|
return getRegistry().getAvailable();
|
|
68
73
|
}
|
|
69
74
|
/**
|
|
70
|
-
* Get
|
|
75
|
+
* Get the `enabledModels` patterns from pi's global settings.
|
|
76
|
+
*
|
|
77
|
+
* These are the canonical model IDs (e.g. "anthropic/claude-sonnet-4-6")
|
|
78
|
+
* persisted by the `/scoped-models` TUI when the user presses Ctrl+S.
|
|
79
|
+
*
|
|
80
|
+
* Returns undefined when no filter is configured (all models enabled).
|
|
71
81
|
*/
|
|
72
|
-
function
|
|
73
|
-
|
|
82
|
+
function getEnabledModels() {
|
|
83
|
+
getSettingsManager().reload();
|
|
84
|
+
return getSettingsManager().getEnabledModels();
|
|
74
85
|
}
|
|
75
86
|
//#endregion
|
|
76
87
|
//#region src/server/errors.ts
|
|
@@ -1307,14 +1318,14 @@ function fileConfigReader() {
|
|
|
1307
1318
|
return {
|
|
1308
1319
|
publicModelIdMode: file.publicModelIdMode,
|
|
1309
1320
|
modelExposureMode: file.modelExposureMode,
|
|
1310
|
-
|
|
1321
|
+
enabledModels: getEnabledModels(),
|
|
1311
1322
|
customModels: file.customModels,
|
|
1312
1323
|
providerPrefixes: file.providerPrefixes
|
|
1313
1324
|
};
|
|
1314
1325
|
}
|
|
1315
1326
|
function createRoutes(config, configReader = fileConfigReader) {
|
|
1316
1327
|
function getExposure() {
|
|
1317
|
-
const outcome = computeModelExposure(getAvailableModels(),
|
|
1328
|
+
const outcome = computeModelExposure(getAvailableModels(), configReader());
|
|
1318
1329
|
if (!outcome.ok) throw new Error(`Model exposure configuration error: ${outcome.message}`);
|
|
1319
1330
|
return outcome;
|
|
1320
1331
|
}
|
|
@@ -12,10 +12,12 @@ import * as z from "zod";
|
|
|
12
12
|
type PublicModelIdMode = "collision-prefixed" | "universal" | "always-prefixed";
|
|
13
13
|
/**
|
|
14
14
|
* Which models are exposed on the public HTTP API.
|
|
15
|
+
* All modes only expose auth-configured models (pi's getAvailable()).
|
|
15
16
|
*
|
|
16
|
-
* - "all": every available model
|
|
17
|
-
* - "scoped":
|
|
18
|
-
* - "custom":
|
|
17
|
+
* - "all": every available model, no filter
|
|
18
|
+
* - "scoped": delegates to pi's global `enabledModels` setting (from `/scoped-models` Ctrl+S)
|
|
19
|
+
* - "custom": same per-model filtering as "scoped" but independently managed
|
|
20
|
+
* via the proxy's own `customModels` config
|
|
19
21
|
*/
|
|
20
22
|
type ModelExposureMode = "all" | "scoped" | "custom";
|
|
21
23
|
interface ProxyConfig {
|
|
@@ -35,10 +37,8 @@ interface ProxyConfig {
|
|
|
35
37
|
readonly lifetime: "detached" | "session";
|
|
36
38
|
/** How public model IDs are generated. Default: "collision-prefixed" */
|
|
37
39
|
readonly publicModelIdMode: PublicModelIdMode;
|
|
38
|
-
/** Which models are exposed. Default: "
|
|
40
|
+
/** Which models are exposed. Default: "scoped" */
|
|
39
41
|
readonly modelExposureMode: ModelExposureMode;
|
|
40
|
-
/** Provider keys to expose when modelExposureMode is "scoped". */
|
|
41
|
-
readonly scopedProviders: readonly string[];
|
|
42
42
|
/** Canonical model IDs to expose when modelExposureMode is "custom". */
|
|
43
43
|
readonly customModels: readonly string[];
|
|
44
44
|
/** Provider key -> custom public prefix label. Default prefix = provider key. */
|
|
@@ -36,7 +36,6 @@ const DEFAULT_CONFIG = {
|
|
|
36
36
|
lifetime: "detached",
|
|
37
37
|
publicModelIdMode: "collision-prefixed",
|
|
38
38
|
modelExposureMode: "scoped",
|
|
39
|
-
scopedProviders: [],
|
|
40
39
|
customModels: [],
|
|
41
40
|
providerPrefixes: {},
|
|
42
41
|
zed: {
|
|
@@ -93,7 +92,6 @@ function normalizeConfig(raw) {
|
|
|
93
92
|
lifetime: v["lifetime"] === "session" ? "session" : "detached",
|
|
94
93
|
publicModelIdMode: typeof rawPublicIdMode === "string" && isPublicModelIdMode(rawPublicIdMode) ? rawPublicIdMode : DEFAULT_CONFIG.publicModelIdMode,
|
|
95
94
|
modelExposureMode: typeof rawExposureMode === "string" && isModelExposureMode(rawExposureMode) ? rawExposureMode : DEFAULT_CONFIG.modelExposureMode,
|
|
96
|
-
scopedProviders: normalizeStringArray(v["scopedProviders"]),
|
|
97
95
|
customModels: normalizeStringArray(v["customModels"]),
|
|
98
96
|
providerPrefixes: normalizeStringRecord(v["providerPrefixes"]),
|
|
99
97
|
zed: parseZedSyncConfig(v["zed"])
|
package/extensions/proxy.ts
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
type ExtensionContext,
|
|
32
32
|
getSettingsListTheme,
|
|
33
33
|
ModelRegistry,
|
|
34
|
+
SettingsManager,
|
|
34
35
|
} from "@mariozechner/pi-coding-agent";
|
|
35
36
|
import {
|
|
36
37
|
type Component,
|
|
@@ -68,6 +69,17 @@ interface RuntimeStatus {
|
|
|
68
69
|
models: number;
|
|
69
70
|
}
|
|
70
71
|
|
|
72
|
+
interface ProbeBody {
|
|
73
|
+
data: unknown[];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function isProbeBody(value: unknown): value is ProbeBody {
|
|
77
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
78
|
+
if (!("data" in value)) return false;
|
|
79
|
+
const v: { data: unknown } = value;
|
|
80
|
+
return Array.isArray(v.data);
|
|
81
|
+
}
|
|
82
|
+
|
|
71
83
|
// ---------------------------------------------------------------------------
|
|
72
84
|
// Extension
|
|
73
85
|
// ---------------------------------------------------------------------------
|
|
@@ -83,22 +95,23 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
83
95
|
|
|
84
96
|
const cachedAuth = AuthStorage.create();
|
|
85
97
|
const cachedRegistry = new ModelRegistry(cachedAuth);
|
|
98
|
+
const settingsManager = SettingsManager.create();
|
|
86
99
|
|
|
87
100
|
function getAvailableModels(): Model<Api>[] {
|
|
88
101
|
cachedRegistry.refresh();
|
|
89
102
|
return cachedRegistry.getAvailable();
|
|
90
103
|
}
|
|
91
104
|
|
|
92
|
-
function
|
|
93
|
-
|
|
94
|
-
return
|
|
105
|
+
function getEnabledModels(): readonly string[] | undefined {
|
|
106
|
+
settingsManager.reload();
|
|
107
|
+
return settingsManager.getEnabledModels();
|
|
95
108
|
}
|
|
96
109
|
|
|
97
110
|
function buildExposureConfig(): ModelExposureConfig {
|
|
98
111
|
return {
|
|
99
112
|
publicModelIdMode: config.publicModelIdMode,
|
|
100
113
|
modelExposureMode: config.modelExposureMode,
|
|
101
|
-
|
|
114
|
+
enabledModels: getEnabledModels(),
|
|
102
115
|
customModels: config.customModels,
|
|
103
116
|
providerPrefixes: config.providerPrefixes,
|
|
104
117
|
};
|
|
@@ -124,6 +137,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
124
137
|
|
|
125
138
|
pi.on("session_start", async (_event, ctx) => {
|
|
126
139
|
config = loadConfigFromFile();
|
|
140
|
+
maybeAutoSyncZed(ctx);
|
|
127
141
|
await refreshStatus(ctx);
|
|
128
142
|
});
|
|
129
143
|
|
|
@@ -274,8 +288,12 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
274
288
|
headers,
|
|
275
289
|
});
|
|
276
290
|
if (res.ok) {
|
|
277
|
-
const body =
|
|
278
|
-
|
|
291
|
+
const body: unknown = await res.json();
|
|
292
|
+
let modelCount = 0;
|
|
293
|
+
if (isProbeBody(body)) {
|
|
294
|
+
modelCount = body.data.length;
|
|
295
|
+
}
|
|
296
|
+
return { reachable: true, models: modelCount };
|
|
279
297
|
}
|
|
280
298
|
} catch {
|
|
281
299
|
// not reachable
|
|
@@ -464,8 +482,11 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
464
482
|
`exposure: ${config.modelExposureMode}`,
|
|
465
483
|
];
|
|
466
484
|
|
|
467
|
-
if (config.modelExposureMode === "scoped"
|
|
468
|
-
|
|
485
|
+
if (config.modelExposureMode === "scoped") {
|
|
486
|
+
const enabledModels = getEnabledModels();
|
|
487
|
+
if (enabledModels !== undefined && enabledModels.length > 0) {
|
|
488
|
+
exposureLines.push(`enabled: ${String(enabledModels.length)} pi model(s)`);
|
|
489
|
+
}
|
|
469
490
|
}
|
|
470
491
|
if (config.modelExposureMode === "custom" && config.customModels.length > 0) {
|
|
471
492
|
exposureLines.push(`models: ${String(config.customModels.length)} custom`);
|
|
@@ -479,8 +500,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
479
500
|
|
|
480
501
|
// Public ID preview (first 5 exposed models)
|
|
481
502
|
const models = getAvailableModels();
|
|
482
|
-
const
|
|
483
|
-
const outcome = computeModelExposure(models, allModels, buildExposureConfig());
|
|
503
|
+
const outcome = computeModelExposure(models, buildExposureConfig());
|
|
484
504
|
if (outcome.ok && outcome.models.length > 0) {
|
|
485
505
|
const preview = outcome.models.slice(0, 5).map((m) => m.publicId);
|
|
486
506
|
const suffix =
|
|
@@ -500,8 +520,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
500
520
|
function showModels(ctx: ExtensionContext): void {
|
|
501
521
|
config = loadConfigFromFile();
|
|
502
522
|
const models = getAvailableModels();
|
|
503
|
-
const
|
|
504
|
-
const outcome = computeModelExposure(models, allModels, buildExposureConfig());
|
|
523
|
+
const outcome = computeModelExposure(models, buildExposureConfig());
|
|
505
524
|
|
|
506
525
|
if (!outcome.ok) {
|
|
507
526
|
ctx.ui.notify(`Model exposure error: ${outcome.message}`, "warning");
|
|
@@ -548,8 +567,6 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
548
567
|
const models = getAvailableModels();
|
|
549
568
|
const issues: string[] = [];
|
|
550
569
|
|
|
551
|
-
const allModels = getAllRegisteredModels();
|
|
552
|
-
|
|
553
570
|
// Check available models
|
|
554
571
|
if (models.length === 0) {
|
|
555
572
|
issues.push("No models have auth configured. The proxy will expose 0 models.");
|
|
@@ -569,7 +586,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
569
586
|
}
|
|
570
587
|
|
|
571
588
|
// Run the full exposure computation to catch ID/prefix errors
|
|
572
|
-
const outcome = computeModelExposure(models,
|
|
589
|
+
const outcome = computeModelExposure(models, buildExposureConfig());
|
|
573
590
|
if (!outcome.ok) {
|
|
574
591
|
issues.push(outcome.message);
|
|
575
592
|
}
|
|
@@ -592,8 +609,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
592
609
|
*/
|
|
593
610
|
function runZedSync(dryRun: boolean): { ok: boolean; message: string } {
|
|
594
611
|
const available = getAvailableModels();
|
|
595
|
-
const
|
|
596
|
-
const outcome = computeModelExposure(available, allModels, buildExposureConfig());
|
|
612
|
+
const outcome = computeModelExposure(available, buildExposureConfig());
|
|
597
613
|
if (!outcome.ok) {
|
|
598
614
|
return { ok: false, message: `Model exposure error: ${outcome.message}` };
|
|
599
615
|
}
|
|
@@ -709,12 +725,40 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
709
725
|
// Accesses private fields via bracket notation for provider jumping.
|
|
710
726
|
// Pinned to pi-tui behavior as of @mariozechner/pi-coding-agent ^0.62.0.
|
|
711
727
|
// Remove when SettingsList exposes a jumpTo/setSelectedIndex method.
|
|
728
|
+
|
|
729
|
+
// Isolated unsafe accessor for SettingsList private fields.
|
|
730
|
+
// Consolidated here so jumpProvider itself is fully type-safe.
|
|
731
|
+
function listGet(key: string): unknown {
|
|
732
|
+
return Reflect.get(list, key);
|
|
733
|
+
}
|
|
734
|
+
function listSet(key: string, value: unknown): void {
|
|
735
|
+
Reflect.set(list, key, value);
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
function getSettingsListItems(): SettingItem[] {
|
|
739
|
+
const rawSearch = listGet("searchEnabled");
|
|
740
|
+
const raw =
|
|
741
|
+
typeof rawSearch === "boolean" && rawSearch ? listGet("filteredItems") : listGet("items");
|
|
742
|
+
if (!Array.isArray(raw)) return [];
|
|
743
|
+
const result: SettingItem[] = [];
|
|
744
|
+
for (const item of raw) {
|
|
745
|
+
if (isSettingItem(item)) result.push(item);
|
|
746
|
+
}
|
|
747
|
+
return result;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
function isSettingItem(value: unknown): value is SettingItem {
|
|
751
|
+
if (value === null || typeof value !== "object") return false;
|
|
752
|
+
if (!("id" in value)) return false;
|
|
753
|
+
const v: { id: unknown } = value;
|
|
754
|
+
return typeof v.id === "string";
|
|
755
|
+
}
|
|
756
|
+
|
|
712
757
|
function jumpProvider(direction: "prev" | "next"): void {
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
const
|
|
716
|
-
|
|
717
|
-
) as SettingItem[];
|
|
758
|
+
const rawIdx = listGet("selectedIndex");
|
|
759
|
+
if (typeof rawIdx !== "number") return;
|
|
760
|
+
const idx = rawIdx;
|
|
761
|
+
const display = getSettingsListItems();
|
|
718
762
|
if (display.length === 0) return;
|
|
719
763
|
|
|
720
764
|
const current = display[idx];
|
|
@@ -750,7 +794,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
750
794
|
}
|
|
751
795
|
}
|
|
752
796
|
}
|
|
753
|
-
|
|
797
|
+
listSet("selectedIndex", target);
|
|
754
798
|
}
|
|
755
799
|
|
|
756
800
|
return {
|
|
@@ -878,7 +922,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
878
922
|
label: "Select models",
|
|
879
923
|
description: customModelsDescription(),
|
|
880
924
|
currentValue: customModelsDisplay(),
|
|
881
|
-
|
|
925
|
+
...(config.modelExposureMode === "custom" ? { submenu: buildModelSelectorSubmenu } : {}),
|
|
882
926
|
},
|
|
883
927
|
// --- Zed sync ---
|
|
884
928
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@victor-software-house/pi-openai-proxy",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.0",
|
|
4
4
|
"description": "OpenAI-compatible HTTP proxy for pi's multi-provider model registry",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Victor Software House",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"typecheck": "tsc --noEmit",
|
|
63
63
|
"lint": "bun run lint:biome && bun run lint:oxlint",
|
|
64
64
|
"lint:biome": "biome check .",
|
|
65
|
-
"lint:oxlint": "oxlint --import-plugin --type-aware --tsconfig=./tsconfig.json
|
|
65
|
+
"lint:oxlint": "oxlint --import-plugin --type-aware --tsconfig=./tsconfig.json .",
|
|
66
66
|
"lint:fix": "biome check --write .",
|
|
67
67
|
"format": "biome format --write .",
|
|
68
68
|
"test": "bun test",
|