@victor-software-house/pi-openai-proxy 4.9.3 → 4.9.5
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/README.md +11 -10
- package/dist/index.mjs +350 -31
- package/extensions/proxy.ts +78 -33
- package/package.json +24 -22
package/README.md
CHANGED
|
@@ -20,10 +20,10 @@ A local OpenAI-compatible HTTP proxy built on [pi](https://github.com/badlogic/p
|
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
22
|
# Install globally
|
|
23
|
-
|
|
23
|
+
pnpm add -g @victor-software-house/pi-openai-proxy
|
|
24
24
|
|
|
25
|
-
# Or run directly
|
|
26
|
-
|
|
25
|
+
# Or run directly
|
|
26
|
+
pnpm dlx @victor-software-house/pi-openai-proxy
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
## Quickstart
|
|
@@ -339,17 +339,18 @@ The extension detects externally running instances and shows their status via `/
|
|
|
339
339
|
## Dev Workflow
|
|
340
340
|
|
|
341
341
|
```bash
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
342
|
+
pnpm install # Install dependencies
|
|
343
|
+
pnpm run dev # Run in development
|
|
344
|
+
pnpm run build # Build for npm (tsdown)
|
|
345
|
+
pnpm run typecheck # TypeScript strict check
|
|
346
|
+
pnpm run lint # Biome + oxlint (strict)
|
|
347
|
+
pnpm test # Run all tests
|
|
348
348
|
```
|
|
349
349
|
|
|
350
350
|
### Tooling
|
|
351
351
|
|
|
352
|
-
- **
|
|
352
|
+
- **pnpm** — package manager and script runner
|
|
353
|
+
- **Bun** — runtime and test runner
|
|
353
354
|
- **tsdown** — npm build (ESM + .d.ts)
|
|
354
355
|
- **Biome** — format + lint
|
|
355
356
|
- **oxlint** — type-aware lint with strict rules (`.oxlintrc.json`)
|
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,326 @@ async function* streamToSSE(events, requestId, model, includeUsage) {
|
|
|
761
761
|
yield encodeDone();
|
|
762
762
|
}
|
|
763
763
|
//#endregion
|
|
764
|
+
//#region node_modules/.pnpm/typebox@1.1.38/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/.pnpm/typebox@1.1.38/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/.pnpm/typebox@1.1.38/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/.pnpm/typebox@1.1.38/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/.pnpm/typebox@1.1.38/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/.pnpm/typebox@1.1.38/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/.pnpm/typebox@1.1.38/node_modules/typebox/build/type/types/schema.mjs
|
|
928
|
+
function IsSchema(value) {
|
|
929
|
+
return IsObject(value);
|
|
930
|
+
}
|
|
931
|
+
//#endregion
|
|
932
|
+
//#region node_modules/.pnpm/typebox@1.1.38/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/.pnpm/typebox@1.1.38/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/.pnpm/typebox@1.1.38/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/.pnpm/typebox@1.1.38/node_modules/typebox/build/type/types/object.mjs
|
|
962
|
+
/** Creates an Object type. */
|
|
963
|
+
function _Object_(properties, options = {}) {
|
|
964
|
+
const requiredKeys = RequiredArray(properties);
|
|
965
|
+
return Create({ "~kind": "Object" }, {
|
|
966
|
+
type: "object",
|
|
967
|
+
...requiredKeys.length > 0 ? { required: requiredKeys } : {},
|
|
968
|
+
properties
|
|
969
|
+
}, options);
|
|
970
|
+
}
|
|
971
|
+
//#endregion
|
|
972
|
+
//#region node_modules/.pnpm/typebox@1.1.38/node_modules/typebox/build/type/types/union.mjs
|
|
973
|
+
/** Creates a Union type. */
|
|
974
|
+
function Union(anyOf, options = {}) {
|
|
975
|
+
return Create({ "~kind": "Union" }, { anyOf }, options);
|
|
976
|
+
}
|
|
977
|
+
//#endregion
|
|
978
|
+
//#region node_modules/.pnpm/typebox@1.1.38/node_modules/typebox/build/type/types/unknown.mjs
|
|
979
|
+
/** Creates an Unknown type. */
|
|
980
|
+
function Unknown(options) {
|
|
981
|
+
return Create({ ["~kind"]: "Unknown" }, {}, options);
|
|
982
|
+
}
|
|
983
|
+
//#endregion
|
|
984
|
+
//#region node_modules/.pnpm/typebox@1.1.38/node_modules/typebox/build/system/hashing/hash.mjs
|
|
985
|
+
var ByteMarker;
|
|
986
|
+
(function(ByteMarker) {
|
|
987
|
+
ByteMarker[ByteMarker["Array"] = 0] = "Array";
|
|
988
|
+
ByteMarker[ByteMarker["BigInt"] = 1] = "BigInt";
|
|
989
|
+
ByteMarker[ByteMarker["Boolean"] = 2] = "Boolean";
|
|
990
|
+
ByteMarker[ByteMarker["Date"] = 3] = "Date";
|
|
991
|
+
ByteMarker[ByteMarker["Constructor"] = 4] = "Constructor";
|
|
992
|
+
ByteMarker[ByteMarker["Function"] = 5] = "Function";
|
|
993
|
+
ByteMarker[ByteMarker["Null"] = 6] = "Null";
|
|
994
|
+
ByteMarker[ByteMarker["Number"] = 7] = "Number";
|
|
995
|
+
ByteMarker[ByteMarker["Object"] = 8] = "Object";
|
|
996
|
+
ByteMarker[ByteMarker["RegExp"] = 9] = "RegExp";
|
|
997
|
+
ByteMarker[ByteMarker["String"] = 10] = "String";
|
|
998
|
+
ByteMarker[ByteMarker["Symbol"] = 11] = "Symbol";
|
|
999
|
+
ByteMarker[ByteMarker["TypeArray"] = 12] = "TypeArray";
|
|
1000
|
+
ByteMarker[ByteMarker["Undefined"] = 13] = "Undefined";
|
|
1001
|
+
})(ByteMarker || (ByteMarker = {}));
|
|
1002
|
+
Array.from({ length: 256 }).map((_, i) => BigInt(i));
|
|
1003
|
+
const F64 = new Float64Array(1);
|
|
1004
|
+
new DataView(F64.buffer);
|
|
1005
|
+
new Uint8Array(F64.buffer);
|
|
1006
|
+
new TextEncoder();
|
|
1007
|
+
//#endregion
|
|
1008
|
+
//#region node_modules/.pnpm/typebox@1.1.38/node_modules/typebox/build/type/types/boolean.mjs
|
|
1009
|
+
/** Creates a Boolean type. */
|
|
1010
|
+
function Boolean(options) {
|
|
1011
|
+
return Create({ "~kind": "Boolean" }, { type: "boolean" }, options);
|
|
1012
|
+
}
|
|
1013
|
+
//#endregion
|
|
1014
|
+
//#region node_modules/.pnpm/typebox@1.1.38/node_modules/typebox/build/type/types/integer.mjs
|
|
1015
|
+
const IntegerPattern = "-?(?:0|[1-9][0-9]*)";
|
|
1016
|
+
/** Creates a Integer type. */
|
|
1017
|
+
function Integer(options) {
|
|
1018
|
+
return Create({ "~kind": "Integer" }, { type: "integer" }, options);
|
|
1019
|
+
}
|
|
1020
|
+
//#endregion
|
|
1021
|
+
//#region node_modules/.pnpm/typebox@1.1.38/node_modules/typebox/build/type/types/literal.mjs
|
|
1022
|
+
var InvalidLiteralValue = class extends Error {
|
|
1023
|
+
constructor(value) {
|
|
1024
|
+
super(`Invalid Literal value`);
|
|
1025
|
+
Object.defineProperty(this, "cause", {
|
|
1026
|
+
value: { value },
|
|
1027
|
+
writable: false,
|
|
1028
|
+
configurable: false,
|
|
1029
|
+
enumerable: false
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1033
|
+
function LiteralTypeName(value) {
|
|
1034
|
+
return IsBigInt(value) ? "bigint" : IsBoolean(value) ? "boolean" : IsNumber(value) ? "number" : IsString(value) ? "string" : (() => {
|
|
1035
|
+
throw new InvalidLiteralValue(value);
|
|
1036
|
+
})();
|
|
1037
|
+
}
|
|
1038
|
+
/** Creates a Literal type. */
|
|
1039
|
+
function Literal(value, options) {
|
|
1040
|
+
return Create({ "~kind": "Literal" }, {
|
|
1041
|
+
type: LiteralTypeName(value),
|
|
1042
|
+
const: value
|
|
1043
|
+
}, options);
|
|
1044
|
+
}
|
|
1045
|
+
//#endregion
|
|
1046
|
+
//#region node_modules/.pnpm/typebox@1.1.38/node_modules/typebox/build/type/types/null.mjs
|
|
1047
|
+
/** Creates a Null type. */
|
|
1048
|
+
function Null(options) {
|
|
1049
|
+
return Create({ "~kind": "Null" }, { type: "null" }, options);
|
|
1050
|
+
}
|
|
1051
|
+
//#endregion
|
|
1052
|
+
//#region node_modules/.pnpm/typebox@1.1.38/node_modules/typebox/build/type/types/number.mjs
|
|
1053
|
+
const NumberPattern = "-?(?:0|[1-9][0-9]*)(?:.[0-9]+)?";
|
|
1054
|
+
/** Creates a Number type. */
|
|
1055
|
+
function Number$1(options) {
|
|
1056
|
+
return Create({ "~kind": "Number" }, { type: "number" }, options);
|
|
1057
|
+
}
|
|
1058
|
+
//#endregion
|
|
1059
|
+
//#region node_modules/.pnpm/typebox@1.1.38/node_modules/typebox/build/type/types/string.mjs
|
|
1060
|
+
/** Creates a String type. */
|
|
1061
|
+
function String$1(options) {
|
|
1062
|
+
return Create({ "~kind": "String" }, { type: "string" }, options);
|
|
1063
|
+
}
|
|
1064
|
+
//#endregion
|
|
1065
|
+
//#region node_modules/.pnpm/typebox@1.1.38/node_modules/typebox/build/type/types/record.mjs
|
|
1066
|
+
const IntegerKey = `^${IntegerPattern}$`;
|
|
1067
|
+
`${NumberPattern}`;
|
|
1068
|
+
//#endregion
|
|
1069
|
+
//#region node_modules/.pnpm/typebox@1.1.38/node_modules/typebox/build/type/script/token/internal/char.mjs
|
|
1070
|
+
function Range(start, end) {
|
|
1071
|
+
return Array.from({ length: end - start + 1 }, (_, i) => String.fromCharCode(start + i));
|
|
1072
|
+
}
|
|
1073
|
+
const Alpha = [...Range(97, 122), ...Range(65, 90)];
|
|
1074
|
+
const Digit = ["0", ...Range(49, 57)];
|
|
1075
|
+
[...Digit];
|
|
1076
|
+
[...[
|
|
1077
|
+
...Alpha,
|
|
1078
|
+
"_",
|
|
1079
|
+
"$"
|
|
1080
|
+
], ...Digit];
|
|
1081
|
+
[...Digit];
|
|
1082
|
+
new RegExp(IntegerKey);
|
|
1083
|
+
//#endregion
|
|
764
1084
|
//#region src/openai/json-schema-to-typebox.ts
|
|
765
1085
|
/**
|
|
766
1086
|
* JSON Schema -> TypeBox conversion for OpenAI function tool parameters.
|
|
@@ -829,7 +1149,7 @@ function jsonSchemaToTypebox(schema, path = "") {
|
|
|
829
1149
|
if (typeof rawType !== "string") {
|
|
830
1150
|
if (Object.keys(schema).length === 0 || Object.keys(schema).length === 1 && description !== void 0) return {
|
|
831
1151
|
ok: true,
|
|
832
|
-
schema:
|
|
1152
|
+
schema: Unknown(opts)
|
|
833
1153
|
};
|
|
834
1154
|
return {
|
|
835
1155
|
ok: false,
|
|
@@ -841,23 +1161,23 @@ function jsonSchemaToTypebox(schema, path = "") {
|
|
|
841
1161
|
case "object": return convertObject(schema, path, opts);
|
|
842
1162
|
case "string": return {
|
|
843
1163
|
ok: true,
|
|
844
|
-
schema:
|
|
1164
|
+
schema: String$1(opts)
|
|
845
1165
|
};
|
|
846
1166
|
case "number": return {
|
|
847
1167
|
ok: true,
|
|
848
|
-
schema:
|
|
1168
|
+
schema: Number$1(opts)
|
|
849
1169
|
};
|
|
850
1170
|
case "integer": return {
|
|
851
1171
|
ok: true,
|
|
852
|
-
schema:
|
|
1172
|
+
schema: Integer(opts)
|
|
853
1173
|
};
|
|
854
1174
|
case "boolean": return {
|
|
855
1175
|
ok: true,
|
|
856
|
-
schema:
|
|
1176
|
+
schema: Boolean(opts)
|
|
857
1177
|
};
|
|
858
1178
|
case "null": return {
|
|
859
1179
|
ok: true,
|
|
860
|
-
schema:
|
|
1180
|
+
schema: Null(opts)
|
|
861
1181
|
};
|
|
862
1182
|
case "array": return convertArray(schema, path, opts);
|
|
863
1183
|
default: return {
|
|
@@ -894,7 +1214,7 @@ function convertAnyOf(branches, path, opts) {
|
|
|
894
1214
|
}
|
|
895
1215
|
return {
|
|
896
1216
|
ok: true,
|
|
897
|
-
schema:
|
|
1217
|
+
schema: Union(converted, opts)
|
|
898
1218
|
};
|
|
899
1219
|
}
|
|
900
1220
|
function convertEnum(values, path, opts) {
|
|
@@ -912,10 +1232,9 @@ function convertEnum(values, path, opts) {
|
|
|
912
1232
|
message: `Empty enum at ${path || "root"}`,
|
|
913
1233
|
path
|
|
914
1234
|
};
|
|
915
|
-
const literals = stringValues.map((v) => Type.Literal(v));
|
|
916
1235
|
return {
|
|
917
1236
|
ok: true,
|
|
918
|
-
schema:
|
|
1237
|
+
schema: Union(stringValues.map((v) => Literal(v)), opts)
|
|
919
1238
|
};
|
|
920
1239
|
}
|
|
921
1240
|
function convertNullableType(typeArray, schema, path, opts) {
|
|
@@ -938,7 +1257,7 @@ function convertNullableType(typeArray, schema, path, opts) {
|
|
|
938
1257
|
if (!innerResult.ok) return innerResult;
|
|
939
1258
|
return {
|
|
940
1259
|
ok: true,
|
|
941
|
-
schema:
|
|
1260
|
+
schema: Union([innerResult.schema, Null()], opts)
|
|
942
1261
|
};
|
|
943
1262
|
}
|
|
944
1263
|
function convertObject(schema, path, opts) {
|
|
@@ -952,7 +1271,7 @@ function convertObject(schema, path, opts) {
|
|
|
952
1271
|
};
|
|
953
1272
|
if (rawProperties === void 0) return {
|
|
954
1273
|
ok: true,
|
|
955
|
-
schema:
|
|
1274
|
+
schema: _Object_({}, opts)
|
|
956
1275
|
};
|
|
957
1276
|
if (!isRecord(rawProperties)) return {
|
|
958
1277
|
ok: false,
|
|
@@ -968,24 +1287,24 @@ function convertObject(schema, path, opts) {
|
|
|
968
1287
|
const result = jsonSchemaToTypebox(propSchema, path.length > 0 ? `${path}.${key}` : key);
|
|
969
1288
|
if (!result.ok) return result;
|
|
970
1289
|
if (requiredSet.has(key)) typeboxProperties[key] = result.schema;
|
|
971
|
-
else typeboxProperties[key] =
|
|
1290
|
+
else typeboxProperties[key] = Optional(result.schema);
|
|
972
1291
|
}
|
|
973
1292
|
return {
|
|
974
1293
|
ok: true,
|
|
975
|
-
schema:
|
|
1294
|
+
schema: _Object_(typeboxProperties, opts)
|
|
976
1295
|
};
|
|
977
1296
|
}
|
|
978
1297
|
function convertArray(schema, path, opts) {
|
|
979
1298
|
const items = schema["items"];
|
|
980
1299
|
if (items === void 0) return {
|
|
981
1300
|
ok: true,
|
|
982
|
-
schema:
|
|
1301
|
+
schema: _Array_(Unknown(), opts)
|
|
983
1302
|
};
|
|
984
1303
|
const itemResult = jsonSchemaToTypebox(items, path.length > 0 ? `${path}.items` : "items");
|
|
985
1304
|
if (!itemResult.ok) return itemResult;
|
|
986
1305
|
return {
|
|
987
1306
|
ok: true,
|
|
988
|
-
schema:
|
|
1307
|
+
schema: _Array_(itemResult.schema, opts)
|
|
989
1308
|
};
|
|
990
1309
|
}
|
|
991
1310
|
//#endregion
|
|
@@ -1008,7 +1327,7 @@ function convertTools(openaiTools) {
|
|
|
1008
1327
|
param: result.path
|
|
1009
1328
|
};
|
|
1010
1329
|
parameters = result.schema;
|
|
1011
|
-
} else parameters =
|
|
1330
|
+
} else parameters = _Object_({});
|
|
1012
1331
|
piTools.push({
|
|
1013
1332
|
name: fn.name,
|
|
1014
1333
|
description: fn.description ?? "",
|
|
@@ -1631,19 +1950,19 @@ async function piStream(model, context, request, options) {
|
|
|
1631
1950
|
}
|
|
1632
1951
|
//#endregion
|
|
1633
1952
|
//#region src/server/routes.ts
|
|
1634
|
-
function fileConfigReader() {
|
|
1953
|
+
async function fileConfigReader() {
|
|
1635
1954
|
const file = loadConfigFromFile();
|
|
1636
1955
|
return {
|
|
1637
1956
|
publicModelIdMode: file.publicModelIdMode,
|
|
1638
1957
|
modelExposureMode: file.modelExposureMode,
|
|
1639
|
-
enabledModels: getEnabledModels(),
|
|
1958
|
+
enabledModels: await getEnabledModels(),
|
|
1640
1959
|
customModels: file.customModels,
|
|
1641
1960
|
providerPrefixes: file.providerPrefixes
|
|
1642
1961
|
};
|
|
1643
1962
|
}
|
|
1644
1963
|
function createRoutes(config, configReader = fileConfigReader) {
|
|
1645
|
-
function getExposure() {
|
|
1646
|
-
const outcome = computeModelExposure(getAvailableModels(), configReader());
|
|
1964
|
+
async function getExposure() {
|
|
1965
|
+
const outcome = computeModelExposure(getAvailableModels(), await configReader());
|
|
1647
1966
|
if (!outcome.ok) throw new Error(`Model exposure configuration error: ${outcome.message}`);
|
|
1648
1967
|
return outcome;
|
|
1649
1968
|
}
|
|
@@ -1657,17 +1976,17 @@ function createRoutes(config, configReader = fileConfigReader) {
|
|
|
1657
1976
|
return mapped;
|
|
1658
1977
|
}
|
|
1659
1978
|
const routes = new Hono();
|
|
1660
|
-
routes.get("/v1/models", (c) => {
|
|
1661
|
-
const exposure = getExposure();
|
|
1979
|
+
routes.get("/v1/models", async (c) => {
|
|
1980
|
+
const exposure = await getExposure();
|
|
1662
1981
|
return c.json(buildModelList(exposure.models));
|
|
1663
1982
|
});
|
|
1664
|
-
routes.get("/v1/models/*", (c) => {
|
|
1983
|
+
routes.get("/v1/models/*", async (c) => {
|
|
1665
1984
|
const rawPath = c.req.path;
|
|
1666
1985
|
if (!rawPath.startsWith("/v1/models/")) return c.json(modelNotFound(""), 404);
|
|
1667
1986
|
const modelIdEncoded = rawPath.slice(11);
|
|
1668
1987
|
if (modelIdEncoded.length === 0) return c.json(modelNotFound(""), 404);
|
|
1669
1988
|
const modelId = decodeURIComponent(modelIdEncoded);
|
|
1670
|
-
const resolved = resolveExposedModel(getExposure(), modelId);
|
|
1989
|
+
const resolved = resolveExposedModel(await getExposure(), modelId);
|
|
1671
1990
|
if (resolved === void 0) return c.json(modelNotFound(modelId), 404);
|
|
1672
1991
|
return c.json(toOpenAIModel(resolved));
|
|
1673
1992
|
});
|
|
@@ -1687,7 +2006,7 @@ function createRoutes(config, configReader = fileConfigReader) {
|
|
|
1687
2006
|
return c.json(invalidRequest(validation.message, validation.param ?? void 0), 400);
|
|
1688
2007
|
}
|
|
1689
2008
|
const request = validation.data;
|
|
1690
|
-
const resolved = resolveExposedModel(getExposure(), request.model);
|
|
2009
|
+
const resolved = resolveExposedModel(await getExposure(), request.model);
|
|
1691
2010
|
if (resolved === void 0) return c.json(modelNotFound(request.model), 404);
|
|
1692
2011
|
const model = resolved.model;
|
|
1693
2012
|
const canonicalModelId = resolved.canonicalId;
|
package/extensions/proxy.ts
CHANGED
|
@@ -20,8 +20,10 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import { type ChildProcess, spawn } from "node:child_process";
|
|
23
|
-
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
24
|
-
import {
|
|
23
|
+
import { constants, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
24
|
+
import { access } from "node:fs/promises";
|
|
25
|
+
import { homedir } from "node:os";
|
|
26
|
+
import { delimiter, dirname, join, resolve } from "node:path";
|
|
25
27
|
import { fileURLToPath } from "node:url";
|
|
26
28
|
import type { Api, Model } from "@mariozechner/pi-ai";
|
|
27
29
|
import {
|
|
@@ -94,24 +96,24 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
94
96
|
// --- Model registry access (cached, refreshed per call) ---
|
|
95
97
|
|
|
96
98
|
const cachedAuth = AuthStorage.create();
|
|
97
|
-
const cachedRegistry =
|
|
98
|
-
const settingsManager = SettingsManager.create();
|
|
99
|
+
const cachedRegistry = ModelRegistry.create(cachedAuth);
|
|
100
|
+
const settingsManager = SettingsManager.create(process.cwd());
|
|
99
101
|
|
|
100
102
|
function getAvailableModels(): Model<Api>[] {
|
|
101
103
|
cachedRegistry.refresh();
|
|
102
104
|
return cachedRegistry.getAvailable();
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
function getEnabledModels(): readonly string[] | undefined {
|
|
106
|
-
settingsManager.reload();
|
|
107
|
+
async function getEnabledModels(): Promise<readonly string[] | undefined> {
|
|
108
|
+
await settingsManager.reload();
|
|
107
109
|
return settingsManager.getEnabledModels();
|
|
108
110
|
}
|
|
109
111
|
|
|
110
|
-
function buildExposureConfig(): ModelExposureConfig {
|
|
112
|
+
async function buildExposureConfig(): Promise<ModelExposureConfig> {
|
|
111
113
|
return {
|
|
112
114
|
publicModelIdMode: config.publicModelIdMode,
|
|
113
115
|
modelExposureMode: config.modelExposureMode,
|
|
114
|
-
enabledModels: getEnabledModels(),
|
|
116
|
+
enabledModels: await getEnabledModels(),
|
|
115
117
|
customModels: config.customModels,
|
|
116
118
|
providerPrefixes: config.providerPrefixes,
|
|
117
119
|
};
|
|
@@ -129,6 +131,41 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
129
131
|
return "pi-proxy";
|
|
130
132
|
}
|
|
131
133
|
|
|
134
|
+
async function isExecutable(path: string): Promise<boolean> {
|
|
135
|
+
try {
|
|
136
|
+
await access(path, constants.X_OK);
|
|
137
|
+
return true;
|
|
138
|
+
} catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function resolveBunExecutable(): Promise<string> {
|
|
144
|
+
if ("bun" in process.versions) return process.execPath;
|
|
145
|
+
|
|
146
|
+
const bunInstall = process.env["BUN_INSTALL"];
|
|
147
|
+
const pathEntries = (process.env["PATH"] ?? "")
|
|
148
|
+
.split(delimiter)
|
|
149
|
+
.filter((entry) => entry.length > 0);
|
|
150
|
+
const candidates = [
|
|
151
|
+
process.env["PI_OPENAI_PROXY_BUN"],
|
|
152
|
+
bunInstall === undefined ? undefined : join(bunInstall, "bin", "bun"),
|
|
153
|
+
...pathEntries.map((entry) => join(entry, "bun")),
|
|
154
|
+
join(homedir(), ".bun", "bin", "bun"),
|
|
155
|
+
join(homedir(), ".local", "share", "mise", "installs", "bun", "latest", "bin", "bun"),
|
|
156
|
+
"/opt/homebrew/bin/bun",
|
|
157
|
+
"/usr/local/bin/bun",
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
for (const candidate of candidates) {
|
|
161
|
+
if (candidate !== undefined && (await isExecutable(candidate))) return candidate;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
throw new Error(
|
|
165
|
+
"Bun runtime not found. Install Bun or set PI_OPENAI_PROXY_BUN to the Bun executable path.",
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
132
169
|
function proxyUrl(): string {
|
|
133
170
|
return `http://${config.host}:${String(config.port)}`;
|
|
134
171
|
}
|
|
@@ -137,7 +174,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
137
174
|
|
|
138
175
|
pi.on("session_start", async (_event, ctx) => {
|
|
139
176
|
config = loadConfigFromFile();
|
|
140
|
-
maybeAutoSyncZed(ctx);
|
|
177
|
+
await maybeAutoSyncZed(ctx);
|
|
141
178
|
await refreshStatus(ctx);
|
|
142
179
|
});
|
|
143
180
|
|
|
@@ -193,16 +230,16 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
193
230
|
await showStatus(ctx);
|
|
194
231
|
return;
|
|
195
232
|
case "verify":
|
|
196
|
-
verifyExposure(ctx);
|
|
233
|
+
await verifyExposure(ctx);
|
|
197
234
|
return;
|
|
198
235
|
case "models":
|
|
199
|
-
showModels(ctx);
|
|
236
|
+
await showModels(ctx);
|
|
200
237
|
return;
|
|
201
238
|
case "zed-sync":
|
|
202
|
-
handleZedSync(ctx, args);
|
|
239
|
+
await handleZedSync(ctx, args);
|
|
203
240
|
return;
|
|
204
241
|
case "show":
|
|
205
|
-
showConfig(ctx);
|
|
242
|
+
await showConfig(ctx);
|
|
206
243
|
return;
|
|
207
244
|
case "path":
|
|
208
245
|
ctx.ui.notify(getConfigPath(), "info");
|
|
@@ -343,9 +380,9 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
343
380
|
const bin = findProxyBinary();
|
|
344
381
|
|
|
345
382
|
if (config.lifetime === "detached") {
|
|
346
|
-
startDetached(bin, proxyEnv);
|
|
383
|
+
await startDetached(bin, proxyEnv);
|
|
347
384
|
} else {
|
|
348
|
-
startSessionTied(ctx, bin, proxyEnv);
|
|
385
|
+
await startSessionTied(ctx, bin, proxyEnv);
|
|
349
386
|
}
|
|
350
387
|
|
|
351
388
|
const ready = await waitForReady(3000);
|
|
@@ -366,9 +403,9 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
366
403
|
}
|
|
367
404
|
}
|
|
368
405
|
|
|
369
|
-
function startDetached(bin: string, env: Record<string, string>): void {
|
|
406
|
+
async function startDetached(bin: string, env: Record<string, string>): Promise<void> {
|
|
370
407
|
const usesBun = bin.endsWith(".mjs");
|
|
371
|
-
const cmd = usesBun ?
|
|
408
|
+
const cmd = usesBun ? await resolveBunExecutable() : bin;
|
|
372
409
|
const cmdArgs = usesBun ? ["run", bin] : [];
|
|
373
410
|
|
|
374
411
|
const child = spawn(cmd, cmdArgs, {
|
|
@@ -377,6 +414,10 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
377
414
|
env: { ...process.env, ...env },
|
|
378
415
|
});
|
|
379
416
|
|
|
417
|
+
child.once("error", () => {
|
|
418
|
+
if (child.pid !== undefined) removePid();
|
|
419
|
+
});
|
|
420
|
+
|
|
380
421
|
if (child.pid === undefined) {
|
|
381
422
|
throw new Error("No PID returned from spawn");
|
|
382
423
|
}
|
|
@@ -385,14 +426,18 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
385
426
|
writePid(child.pid);
|
|
386
427
|
}
|
|
387
428
|
|
|
388
|
-
function startSessionTied(
|
|
429
|
+
async function startSessionTied(
|
|
430
|
+
ctx: ExtensionContext,
|
|
431
|
+
bin: string,
|
|
432
|
+
env: Record<string, string>,
|
|
433
|
+
): Promise<void> {
|
|
389
434
|
if (sessionProcess !== undefined) {
|
|
390
435
|
ctx.ui.notify("Session proxy already running", "info");
|
|
391
436
|
return;
|
|
392
437
|
}
|
|
393
438
|
|
|
394
439
|
const usesBun = bin.endsWith(".mjs");
|
|
395
|
-
const cmd = usesBun ?
|
|
440
|
+
const cmd = usesBun ? await resolveBunExecutable() : bin;
|
|
396
441
|
const cmdArgs = usesBun ? ["run", bin] : [];
|
|
397
442
|
|
|
398
443
|
sessionProcess = spawn(cmd, cmdArgs, {
|
|
@@ -460,7 +505,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
460
505
|
await refreshStatus(ctx);
|
|
461
506
|
}
|
|
462
507
|
|
|
463
|
-
function showConfig(ctx: ExtensionContext): void {
|
|
508
|
+
async function showConfig(ctx: ExtensionContext): Promise<void> {
|
|
464
509
|
config = loadConfigFromFile();
|
|
465
510
|
const authDisplay =
|
|
466
511
|
config.authToken.length > 0 ? `enabled (token: ${config.authToken})` : "disabled";
|
|
@@ -483,7 +528,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
483
528
|
];
|
|
484
529
|
|
|
485
530
|
if (config.modelExposureMode === "scoped") {
|
|
486
|
-
const enabledModels = getEnabledModels();
|
|
531
|
+
const enabledModels = await getEnabledModels();
|
|
487
532
|
if (enabledModels !== undefined && enabledModels.length > 0) {
|
|
488
533
|
exposureLines.push(`enabled: ${String(enabledModels.length)} pi model(s)`);
|
|
489
534
|
}
|
|
@@ -500,7 +545,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
500
545
|
|
|
501
546
|
// Public ID preview (first 5 exposed models)
|
|
502
547
|
const models = getAvailableModels();
|
|
503
|
-
const outcome = computeModelExposure(models, buildExposureConfig());
|
|
548
|
+
const outcome = computeModelExposure(models, await buildExposureConfig());
|
|
504
549
|
if (outcome.ok && outcome.models.length > 0) {
|
|
505
550
|
const preview = outcome.models.slice(0, 5).map((m) => m.publicId);
|
|
506
551
|
const suffix =
|
|
@@ -517,10 +562,10 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
517
562
|
|
|
518
563
|
// --- /proxy models ---
|
|
519
564
|
|
|
520
|
-
function showModels(ctx: ExtensionContext): void {
|
|
565
|
+
async function showModels(ctx: ExtensionContext): Promise<void> {
|
|
521
566
|
config = loadConfigFromFile();
|
|
522
567
|
const models = getAvailableModels();
|
|
523
|
-
const outcome = computeModelExposure(models, buildExposureConfig());
|
|
568
|
+
const outcome = computeModelExposure(models, await buildExposureConfig());
|
|
524
569
|
|
|
525
570
|
if (!outcome.ok) {
|
|
526
571
|
ctx.ui.notify(`Model exposure error: ${outcome.message}`, "warning");
|
|
@@ -562,7 +607,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
562
607
|
|
|
563
608
|
// --- /proxy verify ---
|
|
564
609
|
|
|
565
|
-
function verifyExposure(ctx: ExtensionContext): void {
|
|
610
|
+
async function verifyExposure(ctx: ExtensionContext): Promise<void> {
|
|
566
611
|
config = loadConfigFromFile();
|
|
567
612
|
const models = getAvailableModels();
|
|
568
613
|
const issues: string[] = [];
|
|
@@ -586,7 +631,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
586
631
|
}
|
|
587
632
|
|
|
588
633
|
// Run the full exposure computation to catch ID/prefix errors
|
|
589
|
-
const outcome = computeModelExposure(models, buildExposureConfig());
|
|
634
|
+
const outcome = computeModelExposure(models, await buildExposureConfig());
|
|
590
635
|
if (!outcome.ok) {
|
|
591
636
|
issues.push(outcome.message);
|
|
592
637
|
}
|
|
@@ -607,9 +652,9 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
607
652
|
/**
|
|
608
653
|
* Run Zed sync and return the result. Shared by the command and auto-sync.
|
|
609
654
|
*/
|
|
610
|
-
function runZedSync(dryRun: boolean): { ok: boolean; message: string } {
|
|
655
|
+
async function runZedSync(dryRun: boolean): Promise<{ ok: boolean; message: string }> {
|
|
611
656
|
const available = getAvailableModels();
|
|
612
|
-
const outcome = computeModelExposure(available, buildExposureConfig());
|
|
657
|
+
const outcome = computeModelExposure(available, await buildExposureConfig());
|
|
613
658
|
if (!outcome.ok) {
|
|
614
659
|
return { ok: false, message: `Model exposure error: ${outcome.message}` };
|
|
615
660
|
}
|
|
@@ -634,19 +679,19 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
634
679
|
return { ok: true, message: `${prefix}${result.summary} (${result.configPath})` };
|
|
635
680
|
}
|
|
636
681
|
|
|
637
|
-
function handleZedSync(ctx: ExtensionContext, args: string): void {
|
|
682
|
+
async function handleZedSync(ctx: ExtensionContext, args: string): Promise<void> {
|
|
638
683
|
config = loadConfigFromFile();
|
|
639
684
|
const dryRun = args.includes("--dry-run");
|
|
640
|
-
const result = runZedSync(dryRun);
|
|
685
|
+
const result = await runZedSync(dryRun);
|
|
641
686
|
ctx.ui.notify(`Zed sync: ${result.message}`, result.ok ? "info" : "error");
|
|
642
687
|
}
|
|
643
688
|
|
|
644
689
|
/**
|
|
645
690
|
* Trigger auto-sync to Zed if enabled. Called after config save.
|
|
646
691
|
*/
|
|
647
|
-
function maybeAutoSyncZed(ctx: ExtensionContext): void {
|
|
692
|
+
async function maybeAutoSyncZed(ctx: ExtensionContext): Promise<void> {
|
|
648
693
|
if (!config.zed.autoSync) return;
|
|
649
|
-
const result = runZedSync(false);
|
|
694
|
+
const result = await runZedSync(false);
|
|
650
695
|
if (result.ok) {
|
|
651
696
|
ctx.ui.notify(`Zed auto-sync: ${result.message}`, "info");
|
|
652
697
|
}
|
|
@@ -1106,7 +1151,7 @@ export default function proxyExtension(pi: ExtensionAPI): void {
|
|
|
1106
1151
|
settingsList.updateValue("customModels", customModelsDisplay());
|
|
1107
1152
|
}
|
|
1108
1153
|
|
|
1109
|
-
maybeAutoSyncZed(ctx);
|
|
1154
|
+
void maybeAutoSyncZed(ctx);
|
|
1110
1155
|
tui.requestRender();
|
|
1111
1156
|
},
|
|
1112
1157
|
() => 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.5",
|
|
4
4
|
"description": "OpenAI-compatible HTTP proxy for pi's multi-provider model registry",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Victor Software House",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"engines": {
|
|
29
29
|
"node": ">=20"
|
|
30
30
|
},
|
|
31
|
+
"packageManager": "pnpm@11.0.0-dev.1005",
|
|
31
32
|
"type": "module",
|
|
32
33
|
"exports": {
|
|
33
34
|
".": {
|
|
@@ -60,7 +61,7 @@
|
|
|
60
61
|
"build": "tsdown",
|
|
61
62
|
"start": "bun dist/index.mjs",
|
|
62
63
|
"typecheck": "tsc --noEmit",
|
|
63
|
-
"lint": "
|
|
64
|
+
"lint": "pnpm run lint:biome && pnpm run lint:oxlint",
|
|
64
65
|
"lint:biome": "biome check .",
|
|
65
66
|
"lint:oxlint": "oxlint --import-plugin --type-aware --tsconfig=./tsconfig.json .",
|
|
66
67
|
"lint:fix": "biome check --write .",
|
|
@@ -68,36 +69,37 @@
|
|
|
68
69
|
"test": "bun test",
|
|
69
70
|
"test:ci": "bun test test/unit/ test/integration/",
|
|
70
71
|
"prepare": "tsdown",
|
|
71
|
-
"prepack": "
|
|
72
|
-
"prepublishOnly": "
|
|
72
|
+
"prepack": "pnpm run build",
|
|
73
|
+
"prepublishOnly": "pnpm test && pnpm run build"
|
|
73
74
|
},
|
|
74
75
|
"dependencies": {
|
|
75
|
-
"@mariozechner/pi-ai": "^0.
|
|
76
|
-
"@mariozechner/pi-coding-agent": "^0.
|
|
77
|
-
"@
|
|
78
|
-
"citty": "^0.
|
|
79
|
-
"hono": "^4.12.
|
|
76
|
+
"@mariozechner/pi-ai": "^0.73.0",
|
|
77
|
+
"@mariozechner/pi-coding-agent": "^0.73.0",
|
|
78
|
+
"@mariozechner/pi-tui": "^0.73.0",
|
|
79
|
+
"citty": "^0.2.2",
|
|
80
|
+
"hono": "^4.12.18",
|
|
80
81
|
"jsonc-parser": "^3.3.1",
|
|
81
|
-
"zod": "^4.3
|
|
82
|
+
"zod": "^4.4.3"
|
|
82
83
|
},
|
|
83
84
|
"devDependencies": {
|
|
84
|
-
"@biomejs/biome": "^2.4.
|
|
85
|
-
"@commitlint/cli": "^20.5.
|
|
86
|
-
"@commitlint/config-conventional": "^20.5.
|
|
85
|
+
"@biomejs/biome": "^2.4.14",
|
|
86
|
+
"@commitlint/cli": "^20.5.3",
|
|
87
|
+
"@commitlint/config-conventional": "^20.5.3",
|
|
87
88
|
"@limegrass/eslint-plugin-import-alias": "^1.6.1",
|
|
88
89
|
"@semantic-release/changelog": "^6.0.3",
|
|
89
90
|
"@semantic-release/git": "^10.0.1",
|
|
90
91
|
"@semantic-release/github": "^12.0.6",
|
|
91
92
|
"@semantic-release/npm": "^13.1.5",
|
|
92
|
-
"@types/bun": "^1.3.
|
|
93
|
-
"@types/node": "^25.
|
|
94
|
-
"eslint-plugin-zod": "^3.
|
|
95
|
-
"lefthook": "^2.1.
|
|
96
|
-
"openai": "^6.
|
|
97
|
-
"oxlint": "^1.
|
|
98
|
-
"oxlint-tsgolint": "^0.
|
|
93
|
+
"@types/bun": "^1.3.13",
|
|
94
|
+
"@types/node": "^25.6.0",
|
|
95
|
+
"eslint-plugin-zod": "^3.12.0",
|
|
96
|
+
"lefthook": "^2.1.6",
|
|
97
|
+
"openai": "^6.36.0",
|
|
98
|
+
"oxlint": "^1.63.0",
|
|
99
|
+
"oxlint-tsgolint": "^0.22.1",
|
|
99
100
|
"semantic-release": "^25.0.3",
|
|
100
|
-
"tsdown": "^0.21.
|
|
101
|
-
"
|
|
101
|
+
"tsdown": "^0.21.10",
|
|
102
|
+
"typebox": "^1.1.38",
|
|
103
|
+
"typescript": "^6.0.3"
|
|
102
104
|
}
|
|
103
105
|
}
|