@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 +352 -31
- package/extensions/proxy.ts +25 -25
- package/package.json +4 -4
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 =
|
|
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()
|
|
94
|
-
|
|
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:
|
|
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:
|
|
1166
|
+
schema: String$1(opts)
|
|
845
1167
|
};
|
|
846
1168
|
case "number": return {
|
|
847
1169
|
ok: true,
|
|
848
|
-
schema:
|
|
1170
|
+
schema: Number$1(opts)
|
|
849
1171
|
};
|
|
850
1172
|
case "integer": return {
|
|
851
1173
|
ok: true,
|
|
852
|
-
schema:
|
|
1174
|
+
schema: Integer(opts)
|
|
853
1175
|
};
|
|
854
1176
|
case "boolean": return {
|
|
855
1177
|
ok: true,
|
|
856
|
-
schema:
|
|
1178
|
+
schema: Boolean(opts)
|
|
857
1179
|
};
|
|
858
1180
|
case "null": return {
|
|
859
1181
|
ok: true,
|
|
860
|
-
schema:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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] =
|
|
1292
|
+
else typeboxProperties[key] = Optional(result.schema);
|
|
972
1293
|
}
|
|
973
1294
|
return {
|
|
974
1295
|
ok: true,
|
|
975
|
-
schema:
|
|
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:
|
|
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:
|
|
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 =
|
|
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;
|
package/extensions/proxy.ts
CHANGED
|
@@ -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 =
|
|
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
|
+
"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.
|
|
76
|
-
"@mariozechner/pi-coding-agent": "^0.
|
|
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
|
}
|