@victor-software-house/pi-openai-proxy 4.9.3 → 4.9.4

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 CHANGED
@@ -4,7 +4,6 @@ import { computeModelExposure, resolveExposedModel } from "./exposure.mjs";
4
4
  import * as z from "zod";
5
5
  import { AuthStorage, ModelRegistry, SettingsManager } from "@mariozechner/pi-coding-agent";
6
6
  import { randomBytes } from "node:crypto";
7
- import { Type } from "@sinclair/typebox";
8
7
  import { completeSimple, streamSimple } from "@mariozechner/pi-ai";
9
8
  import { Hono } from "hono";
10
9
  import { stream } from "hono/streaming";
@@ -53,8 +52,8 @@ let settingsManager;
53
52
  */
54
53
  function initRegistry() {
55
54
  authStorage = AuthStorage.create();
56
- registry = new ModelRegistry(authStorage);
57
- settingsManager = SettingsManager.create();
55
+ registry = ModelRegistry.create(authStorage);
56
+ settingsManager = SettingsManager.create(process.cwd());
58
57
  return registry.getError();
59
58
  }
60
59
  function getRegistry() {
@@ -89,9 +88,10 @@ async function getRequestAuth(model) {
89
88
  *
90
89
  * Returns undefined when no filter is configured (all models enabled).
91
90
  */
92
- function getEnabledModels() {
93
- getSettingsManager().reload();
94
- return getSettingsManager().getEnabledModels();
91
+ async function getEnabledModels() {
92
+ const manager = getSettingsManager();
93
+ await manager.reload();
94
+ return manager.getEnabledModels();
95
95
  }
96
96
  //#endregion
97
97
  //#region src/server/errors.ts
@@ -761,6 +761,328 @@ async function* streamToSSE(events, requestId, model, includeUsage) {
761
761
  yield encodeDone();
762
762
  }
763
763
  //#endregion
764
+ //#region node_modules/typebox/build/system/memory/metrics.mjs
765
+ /** TypeBox instantiation metrics */
766
+ const Metrics = {
767
+ assign: 0,
768
+ create: 0,
769
+ clone: 0,
770
+ discard: 0,
771
+ update: 0
772
+ };
773
+ //#endregion
774
+ //#region node_modules/typebox/build/guard/guard.mjs
775
+ /** Returns true if this value is an array */
776
+ function IsArray(value) {
777
+ return Array.isArray(value);
778
+ }
779
+ /** Returns true if this value is bigint */
780
+ function IsBigInt(value) {
781
+ return IsEqual(typeof value, "bigint");
782
+ }
783
+ /** Returns true if this value is a boolean */
784
+ function IsBoolean(value) {
785
+ return IsEqual(typeof value, "boolean");
786
+ }
787
+ /** Returns true if this value is null */
788
+ function IsNull(value) {
789
+ return IsEqual(value, null);
790
+ }
791
+ /** Returns true if this value is number */
792
+ function IsNumber(value) {
793
+ return Number.isFinite(value);
794
+ }
795
+ /** Returns true if this value is an object */
796
+ function IsObject(value) {
797
+ return IsEqual(typeof value, "object") && !IsNull(value);
798
+ }
799
+ /** Returns true if this value is string */
800
+ function IsString(value) {
801
+ return IsEqual(typeof value, "string");
802
+ }
803
+ function IsEqual(left, right) {
804
+ return left === right;
805
+ }
806
+ /** Returns true if the PropertyKey is Unsafe (ref: prototype-pollution). */
807
+ function IsUnsafePropertyKey(key) {
808
+ return IsEqual(key, "__proto__") || IsEqual(key, "constructor") || IsEqual(key, "prototype");
809
+ }
810
+ /** Returns true if this value has this property key */
811
+ function HasPropertyKey(value, key) {
812
+ return IsUnsafePropertyKey(key) ? Object.prototype.hasOwnProperty.call(value, key) : key in value;
813
+ }
814
+ /** Returns property keys for this object via `Object.getOwnPropertyKeys({ ... })` */
815
+ function Keys(value) {
816
+ return Object.getOwnPropertyNames(value);
817
+ }
818
+ //#endregion
819
+ //#region node_modules/typebox/build/system/memory/clone.mjs
820
+ function IsGuard(value) {
821
+ return IsObject(value) && HasPropertyKey(value, "~guard");
822
+ }
823
+ function FromGuard(value) {
824
+ return value;
825
+ }
826
+ function FromArray(value) {
827
+ return value.map((value) => FromValue(value));
828
+ }
829
+ function FromObject(value) {
830
+ const result = {};
831
+ const descriptors = Object.getOwnPropertyDescriptors(value);
832
+ for (const key of Object.keys(descriptors)) {
833
+ const descriptor = descriptors[key];
834
+ if (HasPropertyKey(descriptor, "value")) Object.defineProperty(result, key, {
835
+ ...descriptor,
836
+ value: FromValue(descriptor.value)
837
+ });
838
+ }
839
+ return result;
840
+ }
841
+ function FromRegExp(value) {
842
+ return new RegExp(value.source, value.flags);
843
+ }
844
+ function FromUnknown(value) {
845
+ return value;
846
+ }
847
+ function FromValue(value) {
848
+ return value instanceof RegExp ? FromRegExp(value) : IsGuard(value) ? FromGuard(value) : IsArray(value) ? FromArray(value) : IsObject(value) ? FromObject(value) : FromUnknown(value);
849
+ }
850
+ /**
851
+ * Clones a value using the TypeBox type cloning strategy. This function preserves non-enumerable
852
+ * properties from the source value. This is to ensure cloned types retain discriminable
853
+ * hidden properties.
854
+ */
855
+ function Clone(value) {
856
+ Metrics.clone += 1;
857
+ return FromValue(value);
858
+ }
859
+ //#endregion
860
+ //#region node_modules/typebox/build/system/settings/settings.mjs
861
+ const settings = {
862
+ immutableTypes: false,
863
+ maxErrors: 8,
864
+ useAcceleration: true,
865
+ exactOptionalPropertyTypes: false,
866
+ enumerableKind: false,
867
+ correctiveParse: false
868
+ };
869
+ /** Gets current system settings */
870
+ function Get() {
871
+ return settings;
872
+ }
873
+ //#endregion
874
+ //#region node_modules/typebox/build/system/memory/create.mjs
875
+ function MergeHidden(left, right) {
876
+ for (const key of Object.keys(right)) Object.defineProperty(left, key, {
877
+ configurable: true,
878
+ writable: true,
879
+ enumerable: false,
880
+ value: right[key]
881
+ });
882
+ return left;
883
+ }
884
+ function Merge(left, right) {
885
+ return {
886
+ ...left,
887
+ ...right
888
+ };
889
+ }
890
+ /**
891
+ * Creates an object with hidden, enumerable, and optional property sets. This function
892
+ * ensures types are instantiated according to configuration rules for enumerable and
893
+ * non-enumerable properties.
894
+ */
895
+ function Create(hidden, enumerable, options = {}) {
896
+ Metrics.create += 1;
897
+ const settings = Get();
898
+ const withOptions = Merge(enumerable, options);
899
+ const withHidden = settings.enumerableKind ? Merge(withOptions, hidden) : MergeHidden(withOptions, hidden);
900
+ return settings.immutableTypes ? Object.freeze(withHidden) : withHidden;
901
+ }
902
+ //#endregion
903
+ //#region node_modules/typebox/build/system/memory/update.mjs
904
+ /**
905
+ * Updates a value with new properties while preserving property enumerability. Use this function to modify
906
+ * existing types without altering their configuration.
907
+ */
908
+ function Update(current, hidden, enumerable) {
909
+ Metrics.update += 1;
910
+ const settings = Get();
911
+ const result = Clone(current);
912
+ for (const key of Object.keys(hidden)) Object.defineProperty(result, key, {
913
+ configurable: true,
914
+ writable: true,
915
+ enumerable: settings.enumerableKind,
916
+ value: hidden[key]
917
+ });
918
+ for (const key of Object.keys(enumerable)) Object.defineProperty(result, key, {
919
+ configurable: true,
920
+ enumerable: true,
921
+ writable: true,
922
+ value: enumerable[key]
923
+ });
924
+ return result;
925
+ }
926
+ //#endregion
927
+ //#region node_modules/typebox/build/type/types/schema.mjs
928
+ function IsSchema(value) {
929
+ return IsObject(value);
930
+ }
931
+ //#endregion
932
+ //#region node_modules/typebox/build/type/types/_optional.mjs
933
+ /** Adds Optional to the given type. */
934
+ function OptionalAdd(type) {
935
+ return Update(type, { "~optional": true }, {});
936
+ }
937
+ /** Applies an Optional modifier to the given type. */
938
+ function Optional(type) {
939
+ return OptionalAdd(type);
940
+ }
941
+ /** Returns true if the given value is TOptional */
942
+ function IsOptional(value) {
943
+ return IsSchema(value) && HasPropertyKey(value, "~optional");
944
+ }
945
+ //#endregion
946
+ //#region node_modules/typebox/build/type/types/array.mjs
947
+ /** Creates an Array type. */
948
+ function _Array_(items, options) {
949
+ return Create({ "~kind": "Array" }, {
950
+ type: "array",
951
+ items
952
+ }, options);
953
+ }
954
+ //#endregion
955
+ //#region node_modules/typebox/build/type/types/properties.mjs
956
+ /** Creates a RequiredArray derived from the given TProperties value. */
957
+ function RequiredArray(properties) {
958
+ return Keys(properties).filter((key) => !IsOptional(properties[key]));
959
+ }
960
+ //#endregion
961
+ //#region node_modules/typebox/build/type/types/object.mjs
962
+ /** Creates an Object type. */
963
+ function _Object_(properties, options = {}) {
964
+ const requiredKeys = RequiredArray(properties);
965
+ const required = requiredKeys.length > 0 ? { required: requiredKeys } : {};
966
+ return Create({ "~kind": "Object" }, {
967
+ type: "object",
968
+ ...required,
969
+ properties
970
+ }, options);
971
+ }
972
+ //#endregion
973
+ //#region node_modules/typebox/build/type/types/union.mjs
974
+ /** Creates a Union type. */
975
+ function Union(anyOf, options = {}) {
976
+ return Create({ "~kind": "Union" }, { anyOf }, options);
977
+ }
978
+ //#endregion
979
+ //#region node_modules/typebox/build/type/types/unknown.mjs
980
+ /** Creates an Unknown type. */
981
+ function Unknown(options) {
982
+ return Create({ ["~kind"]: "Unknown" }, {}, options);
983
+ }
984
+ //#endregion
985
+ //#region node_modules/typebox/build/system/hashing/hash.mjs
986
+ var ByteMarker;
987
+ (function(ByteMarker) {
988
+ ByteMarker[ByteMarker["Array"] = 0] = "Array";
989
+ ByteMarker[ByteMarker["BigInt"] = 1] = "BigInt";
990
+ ByteMarker[ByteMarker["Boolean"] = 2] = "Boolean";
991
+ ByteMarker[ByteMarker["Date"] = 3] = "Date";
992
+ ByteMarker[ByteMarker["Constructor"] = 4] = "Constructor";
993
+ ByteMarker[ByteMarker["Function"] = 5] = "Function";
994
+ ByteMarker[ByteMarker["Null"] = 6] = "Null";
995
+ ByteMarker[ByteMarker["Number"] = 7] = "Number";
996
+ ByteMarker[ByteMarker["Object"] = 8] = "Object";
997
+ ByteMarker[ByteMarker["RegExp"] = 9] = "RegExp";
998
+ ByteMarker[ByteMarker["String"] = 10] = "String";
999
+ ByteMarker[ByteMarker["Symbol"] = 11] = "Symbol";
1000
+ ByteMarker[ByteMarker["TypeArray"] = 12] = "TypeArray";
1001
+ ByteMarker[ByteMarker["Undefined"] = 13] = "Undefined";
1002
+ })(ByteMarker || (ByteMarker = {}));
1003
+ const [Prime, Size] = [BigInt("1099511628211"), BigInt("18446744073709551616")];
1004
+ Array.from({ length: 256 }).map((_, i) => BigInt(i));
1005
+ const F64 = new Float64Array(1);
1006
+ new DataView(F64.buffer);
1007
+ new Uint8Array(F64.buffer);
1008
+ new TextEncoder();
1009
+ //#endregion
1010
+ //#region node_modules/typebox/build/type/types/boolean.mjs
1011
+ /** Creates a Boolean type. */
1012
+ function Boolean(options) {
1013
+ return Create({ "~kind": "Boolean" }, { type: "boolean" }, options);
1014
+ }
1015
+ //#endregion
1016
+ //#region node_modules/typebox/build/type/types/integer.mjs
1017
+ const IntegerPattern = "-?(?:0|[1-9][0-9]*)";
1018
+ /** Creates a Integer type. */
1019
+ function Integer(options) {
1020
+ return Create({ "~kind": "Integer" }, { type: "integer" }, options);
1021
+ }
1022
+ //#endregion
1023
+ //#region node_modules/typebox/build/type/types/literal.mjs
1024
+ var InvalidLiteralValue = class extends Error {
1025
+ constructor(value) {
1026
+ super(`Invalid Literal value`);
1027
+ Object.defineProperty(this, "cause", {
1028
+ value: { value },
1029
+ writable: false,
1030
+ configurable: false,
1031
+ enumerable: false
1032
+ });
1033
+ }
1034
+ };
1035
+ function LiteralTypeName(value) {
1036
+ return IsBigInt(value) ? "bigint" : IsBoolean(value) ? "boolean" : IsNumber(value) ? "number" : IsString(value) ? "string" : (() => {
1037
+ throw new InvalidLiteralValue(value);
1038
+ })();
1039
+ }
1040
+ /** Creates a Literal type. */
1041
+ function Literal(value, options) {
1042
+ return Create({ "~kind": "Literal" }, {
1043
+ type: LiteralTypeName(value),
1044
+ const: value
1045
+ }, options);
1046
+ }
1047
+ //#endregion
1048
+ //#region node_modules/typebox/build/type/types/null.mjs
1049
+ /** Creates a Null type. */
1050
+ function Null(options) {
1051
+ return Create({ "~kind": "Null" }, { type: "null" }, options);
1052
+ }
1053
+ //#endregion
1054
+ //#region node_modules/typebox/build/type/types/number.mjs
1055
+ const NumberPattern = "-?(?:0|[1-9][0-9]*)(?:.[0-9]+)?";
1056
+ /** Creates a Number type. */
1057
+ function Number$1(options) {
1058
+ return Create({ "~kind": "Number" }, { type: "number" }, options);
1059
+ }
1060
+ //#endregion
1061
+ //#region node_modules/typebox/build/type/types/string.mjs
1062
+ /** Creates a String type. */
1063
+ function String$1(options) {
1064
+ return Create({ "~kind": "String" }, { type: "string" }, options);
1065
+ }
1066
+ //#endregion
1067
+ //#region node_modules/typebox/build/type/types/record.mjs
1068
+ const IntegerKey = `^${IntegerPattern}$`;
1069
+ `${NumberPattern}`;
1070
+ //#endregion
1071
+ //#region node_modules/typebox/build/type/script/token/internal/char.mjs
1072
+ function Range(start, end) {
1073
+ return Array.from({ length: end - start + 1 }, (_, i) => String.fromCharCode(start + i));
1074
+ }
1075
+ const Alpha = [...Range(97, 122), ...Range(65, 90)];
1076
+ const Digit = ["0", ...Range(49, 57)];
1077
+ [...Digit];
1078
+ [...[
1079
+ ...Alpha,
1080
+ "_",
1081
+ "$"
1082
+ ], ...Digit];
1083
+ [...Digit];
1084
+ new RegExp(IntegerKey);
1085
+ //#endregion
764
1086
  //#region src/openai/json-schema-to-typebox.ts
765
1087
  /**
766
1088
  * JSON Schema -> TypeBox conversion for OpenAI function tool parameters.
@@ -829,7 +1151,7 @@ function jsonSchemaToTypebox(schema, path = "") {
829
1151
  if (typeof rawType !== "string") {
830
1152
  if (Object.keys(schema).length === 0 || Object.keys(schema).length === 1 && description !== void 0) return {
831
1153
  ok: true,
832
- schema: Type.Unknown(opts)
1154
+ schema: Unknown(opts)
833
1155
  };
834
1156
  return {
835
1157
  ok: false,
@@ -841,23 +1163,23 @@ function jsonSchemaToTypebox(schema, path = "") {
841
1163
  case "object": return convertObject(schema, path, opts);
842
1164
  case "string": return {
843
1165
  ok: true,
844
- schema: Type.String(opts)
1166
+ schema: String$1(opts)
845
1167
  };
846
1168
  case "number": return {
847
1169
  ok: true,
848
- schema: Type.Number(opts)
1170
+ schema: Number$1(opts)
849
1171
  };
850
1172
  case "integer": return {
851
1173
  ok: true,
852
- schema: Type.Integer(opts)
1174
+ schema: Integer(opts)
853
1175
  };
854
1176
  case "boolean": return {
855
1177
  ok: true,
856
- schema: Type.Boolean(opts)
1178
+ schema: Boolean(opts)
857
1179
  };
858
1180
  case "null": return {
859
1181
  ok: true,
860
- schema: Type.Null(opts)
1182
+ schema: Null(opts)
861
1183
  };
862
1184
  case "array": return convertArray(schema, path, opts);
863
1185
  default: return {
@@ -894,7 +1216,7 @@ function convertAnyOf(branches, path, opts) {
894
1216
  }
895
1217
  return {
896
1218
  ok: true,
897
- schema: Type.Union(converted, opts)
1219
+ schema: Union(converted, opts)
898
1220
  };
899
1221
  }
900
1222
  function convertEnum(values, path, opts) {
@@ -912,10 +1234,9 @@ function convertEnum(values, path, opts) {
912
1234
  message: `Empty enum at ${path || "root"}`,
913
1235
  path
914
1236
  };
915
- const literals = stringValues.map((v) => Type.Literal(v));
916
1237
  return {
917
1238
  ok: true,
918
- schema: Type.Union(literals, opts)
1239
+ schema: Union(stringValues.map((v) => Literal(v)), opts)
919
1240
  };
920
1241
  }
921
1242
  function convertNullableType(typeArray, schema, path, opts) {
@@ -938,7 +1259,7 @@ function convertNullableType(typeArray, schema, path, opts) {
938
1259
  if (!innerResult.ok) return innerResult;
939
1260
  return {
940
1261
  ok: true,
941
- schema: Type.Union([innerResult.schema, Type.Null()], opts)
1262
+ schema: Union([innerResult.schema, Null()], opts)
942
1263
  };
943
1264
  }
944
1265
  function convertObject(schema, path, opts) {
@@ -952,7 +1273,7 @@ function convertObject(schema, path, opts) {
952
1273
  };
953
1274
  if (rawProperties === void 0) return {
954
1275
  ok: true,
955
- schema: Type.Object({}, opts)
1276
+ schema: _Object_({}, opts)
956
1277
  };
957
1278
  if (!isRecord(rawProperties)) return {
958
1279
  ok: false,
@@ -968,24 +1289,24 @@ function convertObject(schema, path, opts) {
968
1289
  const result = jsonSchemaToTypebox(propSchema, path.length > 0 ? `${path}.${key}` : key);
969
1290
  if (!result.ok) return result;
970
1291
  if (requiredSet.has(key)) typeboxProperties[key] = result.schema;
971
- else typeboxProperties[key] = Type.Optional(result.schema);
1292
+ else typeboxProperties[key] = Optional(result.schema);
972
1293
  }
973
1294
  return {
974
1295
  ok: true,
975
- schema: Type.Object(typeboxProperties, opts)
1296
+ schema: _Object_(typeboxProperties, opts)
976
1297
  };
977
1298
  }
978
1299
  function convertArray(schema, path, opts) {
979
1300
  const items = schema["items"];
980
1301
  if (items === void 0) return {
981
1302
  ok: true,
982
- schema: Type.Array(Type.Unknown(), opts)
1303
+ schema: _Array_(Unknown(), opts)
983
1304
  };
984
1305
  const itemResult = jsonSchemaToTypebox(items, path.length > 0 ? `${path}.items` : "items");
985
1306
  if (!itemResult.ok) return itemResult;
986
1307
  return {
987
1308
  ok: true,
988
- schema: Type.Array(itemResult.schema, opts)
1309
+ schema: _Array_(itemResult.schema, opts)
989
1310
  };
990
1311
  }
991
1312
  //#endregion
@@ -1008,7 +1329,7 @@ function convertTools(openaiTools) {
1008
1329
  param: result.path
1009
1330
  };
1010
1331
  parameters = result.schema;
1011
- } else parameters = Type.Object({});
1332
+ } else parameters = _Object_({});
1012
1333
  piTools.push({
1013
1334
  name: fn.name,
1014
1335
  description: fn.description ?? "",
@@ -1631,19 +1952,19 @@ async function piStream(model, context, request, options) {
1631
1952
  }
1632
1953
  //#endregion
1633
1954
  //#region src/server/routes.ts
1634
- function fileConfigReader() {
1955
+ async function fileConfigReader() {
1635
1956
  const file = loadConfigFromFile();
1636
1957
  return {
1637
1958
  publicModelIdMode: file.publicModelIdMode,
1638
1959
  modelExposureMode: file.modelExposureMode,
1639
- enabledModels: getEnabledModels(),
1960
+ enabledModels: await getEnabledModels(),
1640
1961
  customModels: file.customModels,
1641
1962
  providerPrefixes: file.providerPrefixes
1642
1963
  };
1643
1964
  }
1644
1965
  function createRoutes(config, configReader = fileConfigReader) {
1645
- function getExposure() {
1646
- const outcome = computeModelExposure(getAvailableModels(), configReader());
1966
+ async function getExposure() {
1967
+ const outcome = computeModelExposure(getAvailableModels(), await configReader());
1647
1968
  if (!outcome.ok) throw new Error(`Model exposure configuration error: ${outcome.message}`);
1648
1969
  return outcome;
1649
1970
  }
@@ -1657,17 +1978,17 @@ function createRoutes(config, configReader = fileConfigReader) {
1657
1978
  return mapped;
1658
1979
  }
1659
1980
  const routes = new Hono();
1660
- routes.get("/v1/models", (c) => {
1661
- const exposure = getExposure();
1981
+ routes.get("/v1/models", async (c) => {
1982
+ const exposure = await getExposure();
1662
1983
  return c.json(buildModelList(exposure.models));
1663
1984
  });
1664
- routes.get("/v1/models/*", (c) => {
1985
+ routes.get("/v1/models/*", async (c) => {
1665
1986
  const rawPath = c.req.path;
1666
1987
  if (!rawPath.startsWith("/v1/models/")) return c.json(modelNotFound(""), 404);
1667
1988
  const modelIdEncoded = rawPath.slice(11);
1668
1989
  if (modelIdEncoded.length === 0) return c.json(modelNotFound(""), 404);
1669
1990
  const modelId = decodeURIComponent(modelIdEncoded);
1670
- const resolved = resolveExposedModel(getExposure(), modelId);
1991
+ const resolved = resolveExposedModel(await getExposure(), modelId);
1671
1992
  if (resolved === void 0) return c.json(modelNotFound(modelId), 404);
1672
1993
  return c.json(toOpenAIModel(resolved));
1673
1994
  });
@@ -1687,7 +2008,7 @@ function createRoutes(config, configReader = fileConfigReader) {
1687
2008
  return c.json(invalidRequest(validation.message, validation.param ?? void 0), 400);
1688
2009
  }
1689
2010
  const request = validation.data;
1690
- const resolved = resolveExposedModel(getExposure(), request.model);
2011
+ const resolved = resolveExposedModel(await getExposure(), request.model);
1691
2012
  if (resolved === void 0) return c.json(modelNotFound(request.model), 404);
1692
2013
  const model = resolved.model;
1693
2014
  const canonicalModelId = resolved.canonicalId;
@@ -94,24 +94,24 @@ export default function proxyExtension(pi: ExtensionAPI): void {
94
94
  // --- Model registry access (cached, refreshed per call) ---
95
95
 
96
96
  const cachedAuth = AuthStorage.create();
97
- const cachedRegistry = new ModelRegistry(cachedAuth);
98
- const settingsManager = SettingsManager.create();
97
+ const cachedRegistry = ModelRegistry.create(cachedAuth);
98
+ const settingsManager = SettingsManager.create(process.cwd());
99
99
 
100
100
  function getAvailableModels(): Model<Api>[] {
101
101
  cachedRegistry.refresh();
102
102
  return cachedRegistry.getAvailable();
103
103
  }
104
104
 
105
- function getEnabledModels(): readonly string[] | undefined {
106
- settingsManager.reload();
105
+ async function getEnabledModels(): Promise<readonly string[] | undefined> {
106
+ await settingsManager.reload();
107
107
  return settingsManager.getEnabledModels();
108
108
  }
109
109
 
110
- function buildExposureConfig(): ModelExposureConfig {
110
+ async function buildExposureConfig(): Promise<ModelExposureConfig> {
111
111
  return {
112
112
  publicModelIdMode: config.publicModelIdMode,
113
113
  modelExposureMode: config.modelExposureMode,
114
- enabledModels: getEnabledModels(),
114
+ enabledModels: await getEnabledModels(),
115
115
  customModels: config.customModels,
116
116
  providerPrefixes: config.providerPrefixes,
117
117
  };
@@ -137,7 +137,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
137
137
 
138
138
  pi.on("session_start", async (_event, ctx) => {
139
139
  config = loadConfigFromFile();
140
- maybeAutoSyncZed(ctx);
140
+ await maybeAutoSyncZed(ctx);
141
141
  await refreshStatus(ctx);
142
142
  });
143
143
 
@@ -193,16 +193,16 @@ export default function proxyExtension(pi: ExtensionAPI): void {
193
193
  await showStatus(ctx);
194
194
  return;
195
195
  case "verify":
196
- verifyExposure(ctx);
196
+ await verifyExposure(ctx);
197
197
  return;
198
198
  case "models":
199
- showModels(ctx);
199
+ await showModels(ctx);
200
200
  return;
201
201
  case "zed-sync":
202
- handleZedSync(ctx, args);
202
+ await handleZedSync(ctx, args);
203
203
  return;
204
204
  case "show":
205
- showConfig(ctx);
205
+ await showConfig(ctx);
206
206
  return;
207
207
  case "path":
208
208
  ctx.ui.notify(getConfigPath(), "info");
@@ -460,7 +460,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
460
460
  await refreshStatus(ctx);
461
461
  }
462
462
 
463
- function showConfig(ctx: ExtensionContext): void {
463
+ async function showConfig(ctx: ExtensionContext): Promise<void> {
464
464
  config = loadConfigFromFile();
465
465
  const authDisplay =
466
466
  config.authToken.length > 0 ? `enabled (token: ${config.authToken})` : "disabled";
@@ -483,7 +483,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
483
483
  ];
484
484
 
485
485
  if (config.modelExposureMode === "scoped") {
486
- const enabledModels = getEnabledModels();
486
+ const enabledModels = await getEnabledModels();
487
487
  if (enabledModels !== undefined && enabledModels.length > 0) {
488
488
  exposureLines.push(`enabled: ${String(enabledModels.length)} pi model(s)`);
489
489
  }
@@ -500,7 +500,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
500
500
 
501
501
  // Public ID preview (first 5 exposed models)
502
502
  const models = getAvailableModels();
503
- const outcome = computeModelExposure(models, buildExposureConfig());
503
+ const outcome = computeModelExposure(models, await buildExposureConfig());
504
504
  if (outcome.ok && outcome.models.length > 0) {
505
505
  const preview = outcome.models.slice(0, 5).map((m) => m.publicId);
506
506
  const suffix =
@@ -517,10 +517,10 @@ export default function proxyExtension(pi: ExtensionAPI): void {
517
517
 
518
518
  // --- /proxy models ---
519
519
 
520
- function showModels(ctx: ExtensionContext): void {
520
+ async function showModels(ctx: ExtensionContext): Promise<void> {
521
521
  config = loadConfigFromFile();
522
522
  const models = getAvailableModels();
523
- const outcome = computeModelExposure(models, buildExposureConfig());
523
+ const outcome = computeModelExposure(models, await buildExposureConfig());
524
524
 
525
525
  if (!outcome.ok) {
526
526
  ctx.ui.notify(`Model exposure error: ${outcome.message}`, "warning");
@@ -562,7 +562,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
562
562
 
563
563
  // --- /proxy verify ---
564
564
 
565
- function verifyExposure(ctx: ExtensionContext): void {
565
+ async function verifyExposure(ctx: ExtensionContext): Promise<void> {
566
566
  config = loadConfigFromFile();
567
567
  const models = getAvailableModels();
568
568
  const issues: string[] = [];
@@ -586,7 +586,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
586
586
  }
587
587
 
588
588
  // Run the full exposure computation to catch ID/prefix errors
589
- const outcome = computeModelExposure(models, buildExposureConfig());
589
+ const outcome = computeModelExposure(models, await buildExposureConfig());
590
590
  if (!outcome.ok) {
591
591
  issues.push(outcome.message);
592
592
  }
@@ -607,9 +607,9 @@ export default function proxyExtension(pi: ExtensionAPI): void {
607
607
  /**
608
608
  * Run Zed sync and return the result. Shared by the command and auto-sync.
609
609
  */
610
- function runZedSync(dryRun: boolean): { ok: boolean; message: string } {
610
+ async function runZedSync(dryRun: boolean): Promise<{ ok: boolean; message: string }> {
611
611
  const available = getAvailableModels();
612
- const outcome = computeModelExposure(available, buildExposureConfig());
612
+ const outcome = computeModelExposure(available, await buildExposureConfig());
613
613
  if (!outcome.ok) {
614
614
  return { ok: false, message: `Model exposure error: ${outcome.message}` };
615
615
  }
@@ -634,19 +634,19 @@ export default function proxyExtension(pi: ExtensionAPI): void {
634
634
  return { ok: true, message: `${prefix}${result.summary} (${result.configPath})` };
635
635
  }
636
636
 
637
- function handleZedSync(ctx: ExtensionContext, args: string): void {
637
+ async function handleZedSync(ctx: ExtensionContext, args: string): Promise<void> {
638
638
  config = loadConfigFromFile();
639
639
  const dryRun = args.includes("--dry-run");
640
- const result = runZedSync(dryRun);
640
+ const result = await runZedSync(dryRun);
641
641
  ctx.ui.notify(`Zed sync: ${result.message}`, result.ok ? "info" : "error");
642
642
  }
643
643
 
644
644
  /**
645
645
  * Trigger auto-sync to Zed if enabled. Called after config save.
646
646
  */
647
- function maybeAutoSyncZed(ctx: ExtensionContext): void {
647
+ async function maybeAutoSyncZed(ctx: ExtensionContext): Promise<void> {
648
648
  if (!config.zed.autoSync) return;
649
- const result = runZedSync(false);
649
+ const result = await runZedSync(false);
650
650
  if (result.ok) {
651
651
  ctx.ui.notify(`Zed auto-sync: ${result.message}`, "info");
652
652
  }
@@ -1106,7 +1106,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
1106
1106
  settingsList.updateValue("customModels", customModelsDisplay());
1107
1107
  }
1108
1108
 
1109
- maybeAutoSyncZed(ctx);
1109
+ void maybeAutoSyncZed(ctx);
1110
1110
  tui.requestRender();
1111
1111
  },
1112
1112
  () => done(undefined),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@victor-software-house/pi-openai-proxy",
3
- "version": "4.9.3",
3
+ "version": "4.9.4",
4
4
  "description": "OpenAI-compatible HTTP proxy for pi's multi-provider model registry",
5
5
  "license": "MIT",
6
6
  "author": "Victor Software House",
@@ -72,9 +72,8 @@
72
72
  "prepublishOnly": "bun test && bun run build"
73
73
  },
74
74
  "dependencies": {
75
- "@mariozechner/pi-ai": "^0.63.1",
76
- "@mariozechner/pi-coding-agent": "^0.63.1",
77
- "@sinclair/typebox": "^0.34.0",
75
+ "@mariozechner/pi-ai": "^0.73.0",
76
+ "@mariozechner/pi-coding-agent": "^0.73.0",
78
77
  "citty": "^0.1.6",
79
78
  "hono": "^4.12.8",
80
79
  "jsonc-parser": "^3.3.1",
@@ -98,6 +97,7 @@
98
97
  "oxlint-tsgolint": "^0.17.1",
99
98
  "semantic-release": "^25.0.3",
100
99
  "tsdown": "^0.21.4",
100
+ "typebox": "^1.1.38",
101
101
  "typescript": "^5.9.3"
102
102
  }
103
103
  }