@victor-software-house/pi-openai-proxy 4.0.5 → 4.1.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/index.mjs +18 -24
- package/extensions/proxy.ts +63 -13
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1283,31 +1283,25 @@ async function piStream(model, context, request, options) {
|
|
|
1283
1283
|
}
|
|
1284
1284
|
//#endregion
|
|
1285
1285
|
//#region src/server/routes.ts
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
*/
|
|
1289
|
-
function buildExposureConfig(config) {
|
|
1286
|
+
function fileConfigReader() {
|
|
1287
|
+
const file = loadConfigFromFile();
|
|
1290
1288
|
return {
|
|
1291
|
-
publicModelIdMode:
|
|
1292
|
-
modelExposureMode:
|
|
1293
|
-
scopedProviders:
|
|
1294
|
-
customModels:
|
|
1295
|
-
providerPrefixes:
|
|
1289
|
+
publicModelIdMode: file.publicModelIdMode,
|
|
1290
|
+
modelExposureMode: file.modelExposureMode,
|
|
1291
|
+
scopedProviders: file.scopedProviders,
|
|
1292
|
+
customModels: file.customModels,
|
|
1293
|
+
providerPrefixes: file.providerPrefixes
|
|
1296
1294
|
};
|
|
1297
1295
|
}
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
if (!outcome.ok) throw new Error(`Model exposure configuration error: ${outcome.message}`);
|
|
1305
|
-
return outcome;
|
|
1306
|
-
}
|
|
1307
|
-
function createRoutes(config) {
|
|
1296
|
+
function createRoutes(config, configReader = fileConfigReader) {
|
|
1297
|
+
function getExposure() {
|
|
1298
|
+
const outcome = computeModelExposure(getAvailableModels(), getAllModels(), configReader());
|
|
1299
|
+
if (!outcome.ok) throw new Error(`Model exposure configuration error: ${outcome.message}`);
|
|
1300
|
+
return outcome;
|
|
1301
|
+
}
|
|
1308
1302
|
const routes = new Hono();
|
|
1309
1303
|
routes.get("/v1/models", (c) => {
|
|
1310
|
-
const exposure = getExposure(
|
|
1304
|
+
const exposure = getExposure();
|
|
1311
1305
|
return c.json(buildModelList(exposure.models));
|
|
1312
1306
|
});
|
|
1313
1307
|
routes.get("/v1/models/*", (c) => {
|
|
@@ -1316,7 +1310,7 @@ function createRoutes(config) {
|
|
|
1316
1310
|
const modelIdEncoded = rawPath.slice(11);
|
|
1317
1311
|
if (modelIdEncoded.length === 0) return c.json(modelNotFound(""), 404);
|
|
1318
1312
|
const modelId = decodeURIComponent(modelIdEncoded);
|
|
1319
|
-
const resolved = resolveExposedModel(getExposure(
|
|
1313
|
+
const resolved = resolveExposedModel(getExposure(), modelId);
|
|
1320
1314
|
if (resolved === void 0) return c.json(modelNotFound(modelId), 404);
|
|
1321
1315
|
return c.json(toOpenAIModel(resolved));
|
|
1322
1316
|
});
|
|
@@ -1336,7 +1330,7 @@ function createRoutes(config) {
|
|
|
1336
1330
|
return c.json(invalidRequest(validation.message, validation.param ?? void 0), 400);
|
|
1337
1331
|
}
|
|
1338
1332
|
const request = validation.data;
|
|
1339
|
-
const resolved = resolveExposedModel(getExposure(
|
|
1333
|
+
const resolved = resolveExposedModel(getExposure(), request.model);
|
|
1340
1334
|
if (resolved === void 0) return c.json(modelNotFound(request.model), 404);
|
|
1341
1335
|
const model = resolved.model;
|
|
1342
1336
|
const canonicalModelId = resolved.canonicalId;
|
|
@@ -1422,13 +1416,13 @@ function createRoutes(config) {
|
|
|
1422
1416
|
}
|
|
1423
1417
|
//#endregion
|
|
1424
1418
|
//#region src/server/app.ts
|
|
1425
|
-
function createApp(config) {
|
|
1419
|
+
function createApp(config, configReader) {
|
|
1426
1420
|
const app = new Hono();
|
|
1427
1421
|
app.use("*", requestIdMiddleware());
|
|
1428
1422
|
app.use("*", disconnectMiddleware());
|
|
1429
1423
|
app.use("*", bodySizeLimitMiddleware(config));
|
|
1430
1424
|
app.use("/v1/*", proxyAuthMiddleware(config));
|
|
1431
|
-
app.route("/", createRoutes(config));
|
|
1425
|
+
app.route("/", createRoutes(config, configReader));
|
|
1432
1426
|
return app;
|
|
1433
1427
|
}
|
|
1434
1428
|
//#endregion
|
package/extensions/proxy.ts
CHANGED
|
@@ -614,6 +614,40 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
614
614
|
};
|
|
615
615
|
}
|
|
616
616
|
|
|
617
|
+
// --- Dynamic descriptions ---
|
|
618
|
+
|
|
619
|
+
const ID_MODE_DESCRIPTIONS: Record<string, string> = {
|
|
620
|
+
"collision-prefixed": "Short names; adds provider/ prefix only when models collide",
|
|
621
|
+
universal: "Short names only; fails if any model name is shared by two providers",
|
|
622
|
+
"always-prefixed": "Always provider/model-id for every model",
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
const EXPOSURE_MODE_DESCRIPTIONS: Record<string, string> = {
|
|
626
|
+
scoped: "Expose models from pi's configured auth (default)",
|
|
627
|
+
all: "Expose all registered models, including those without auth",
|
|
628
|
+
custom: "Expose only manually selected models",
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
function idModeDescription(): string {
|
|
632
|
+
return ID_MODE_DESCRIPTIONS[config.publicModelIdMode] ?? "";
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
function exposureModeDescription(): string {
|
|
636
|
+
return EXPOSURE_MODE_DESCRIPTIONS[config.modelExposureMode] ?? "";
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
function customModelsDescription(): string {
|
|
640
|
+
if (config.modelExposureMode === "custom") return "Press Enter to open model selector";
|
|
641
|
+
return "Switch exposure mode to 'custom' to select models";
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
function authDescription(): string {
|
|
645
|
+
if (config.authToken.length > 0) {
|
|
646
|
+
return `Token: ${config.authToken.slice(0, 8)}... (use /proxy show to copy)`;
|
|
647
|
+
}
|
|
648
|
+
return "Require bearer token for all requests";
|
|
649
|
+
}
|
|
650
|
+
|
|
617
651
|
function buildSettingItems(): SettingItem[] {
|
|
618
652
|
return [
|
|
619
653
|
// --- Server ---
|
|
@@ -641,10 +675,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
641
675
|
{
|
|
642
676
|
id: "authToken",
|
|
643
677
|
label: "Proxy auth",
|
|
644
|
-
description:
|
|
645
|
-
config.authToken.length > 0
|
|
646
|
-
? `Token: ${config.authToken.slice(0, 8)}... (use /proxy show to copy)`
|
|
647
|
-
: "Require bearer token for all requests",
|
|
678
|
+
description: authDescription(),
|
|
648
679
|
currentValue: config.authToken.length > 0 ? "enabled" : "disabled",
|
|
649
680
|
values: ["disabled", "enabled"],
|
|
650
681
|
},
|
|
@@ -672,32 +703,50 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
672
703
|
// --- Model exposure ---
|
|
673
704
|
{
|
|
674
705
|
id: "publicModelIdMode",
|
|
675
|
-
label: "
|
|
676
|
-
description:
|
|
706
|
+
label: "Model ID format",
|
|
707
|
+
description: idModeDescription(),
|
|
677
708
|
currentValue: config.publicModelIdMode,
|
|
678
709
|
values: ["collision-prefixed", "universal", "always-prefixed"],
|
|
679
710
|
},
|
|
680
711
|
{
|
|
681
712
|
id: "modelExposureMode",
|
|
682
713
|
label: "Exposure mode",
|
|
683
|
-
description:
|
|
684
|
-
"scoped = pi's available models, all = all registered, custom = manual selection",
|
|
714
|
+
description: exposureModeDescription(),
|
|
685
715
|
currentValue: config.modelExposureMode,
|
|
686
716
|
values: ["scoped", "all", "custom"],
|
|
687
717
|
},
|
|
688
718
|
{
|
|
689
719
|
id: "customModels",
|
|
690
720
|
label: "Select models",
|
|
691
|
-
description:
|
|
692
|
-
config.modelExposureMode === "custom"
|
|
693
|
-
? "Press Enter to open model selector"
|
|
694
|
-
: "Switch exposure mode to 'custom' to select models",
|
|
721
|
+
description: customModelsDescription(),
|
|
695
722
|
currentValue: customModelsDisplay(),
|
|
696
723
|
submenu: config.modelExposureMode === "custom" ? buildModelSelectorSubmenu : undefined,
|
|
697
724
|
},
|
|
698
725
|
];
|
|
699
726
|
}
|
|
700
727
|
|
|
728
|
+
/**
|
|
729
|
+
* Update descriptions on items that change dynamically based on the current value.
|
|
730
|
+
*/
|
|
731
|
+
function refreshDescriptions(items: SettingItem[]): void {
|
|
732
|
+
for (const item of items) {
|
|
733
|
+
switch (item.id) {
|
|
734
|
+
case "publicModelIdMode":
|
|
735
|
+
item.description = idModeDescription();
|
|
736
|
+
break;
|
|
737
|
+
case "modelExposureMode":
|
|
738
|
+
item.description = exposureModeDescription();
|
|
739
|
+
break;
|
|
740
|
+
case "customModels":
|
|
741
|
+
item.description = customModelsDescription();
|
|
742
|
+
break;
|
|
743
|
+
case "authToken":
|
|
744
|
+
item.description = authDescription();
|
|
745
|
+
break;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
701
750
|
const VALID_ID_MODES = new Set<string>(["collision-prefixed", "universal", "always-prefixed"]);
|
|
702
751
|
|
|
703
752
|
function isPublicModelIdMode(v: string): v is PublicModelIdMode {
|
|
@@ -821,8 +870,9 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
821
870
|
ctx.ui.notify(`Auth token: ${lastGeneratedToken}`, "info");
|
|
822
871
|
}
|
|
823
872
|
|
|
824
|
-
// Update display value in-place (
|
|
873
|
+
// Update display value and descriptions in-place (preserves selection)
|
|
825
874
|
settingsList.updateValue(id, getDisplayValue(id));
|
|
875
|
+
refreshDescriptions(items);
|
|
826
876
|
|
|
827
877
|
// When exposure mode changes, update the "Select models" item
|
|
828
878
|
if (id === "modelExposureMode") {
|
package/package.json
CHANGED