pi-freeflow 1.0.2 → 1.0.3
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/extensions/index.ts +51 -26
- package/package.json +1 -1
package/extensions/index.ts
CHANGED
|
@@ -844,6 +844,54 @@ function sanitizeHeaders(
|
|
|
844
844
|
return sanitized;
|
|
845
845
|
}
|
|
846
846
|
|
|
847
|
+
function normalizeRequestBody(
|
|
848
|
+
body: Record<string, unknown>,
|
|
849
|
+
isRelay = false,
|
|
850
|
+
): Record<string, unknown> {
|
|
851
|
+
// 1. Tool choice normalization (OpenCode Zen only supports "auto" or undefined)
|
|
852
|
+
if (body.tool_choice === "none") {
|
|
853
|
+
delete body.tool_choice;
|
|
854
|
+
delete body.tools;
|
|
855
|
+
} else if (body.tool_choice && body.tool_choice !== "auto") {
|
|
856
|
+
body.tool_choice = "auto";
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
// 2. Reasoning normalization
|
|
860
|
+
if (typeof body.reasoning_effort === "string") {
|
|
861
|
+
const re = body.reasoning_effort.toLowerCase();
|
|
862
|
+
if (re === "xhigh" || re === "max") {
|
|
863
|
+
body.reasoning_effort = "max";
|
|
864
|
+
} else if (re === "high" || re === "medium") {
|
|
865
|
+
body.reasoning_effort = "high";
|
|
866
|
+
} else if (re === "none" || re === "off") {
|
|
867
|
+
delete body.reasoning_effort;
|
|
868
|
+
} else {
|
|
869
|
+
body.reasoning_effort = "low";
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
if (body.reasoning && typeof body.reasoning === "object") {
|
|
873
|
+
const r = body.reasoning as Record<string, unknown>;
|
|
874
|
+
if (r.effort === "none" || r.effort === "off") {
|
|
875
|
+
delete r.effort;
|
|
876
|
+
} else if (typeof r.effort === "string") {
|
|
877
|
+
const re = r.effort.toLowerCase();
|
|
878
|
+
if (re === "xhigh" || re === "max") r.effort = "max";
|
|
879
|
+
else if (re === "high" || re === "medium") r.effort = "high";
|
|
880
|
+
else r.effort = "low";
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// 3. Max tokens clamp for Vercel relay
|
|
885
|
+
if (isRelay) {
|
|
886
|
+
const mt = body.max_tokens ?? body.maxTokens;
|
|
887
|
+
if (typeof mt === "number" && mt > RELAY_MAX_TOKENS) {
|
|
888
|
+
body.max_tokens = RELAY_MAX_TOKENS;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
return body;
|
|
893
|
+
}
|
|
894
|
+
|
|
847
895
|
// ponytail: shared stream pipe — upstream abort/timeout must end response,
|
|
848
896
|
// not become an uncaught exception that crashes pi.
|
|
849
897
|
function pipeUpstreamStream(
|
|
@@ -1017,27 +1065,11 @@ function startProxy(
|
|
|
1017
1065
|
activeHost,
|
|
1018
1066
|
);
|
|
1019
1067
|
try {
|
|
1020
|
-
// ponytail: clamp max_tokens for Vercel relay — large values
|
|
1021
|
-
// cause 400 "Upstream request failed" (response size / duration
|
|
1022
|
-
// limits). Direct mode stays unconstrained.
|
|
1023
1068
|
let relayBody = bodyChunks.length
|
|
1024
1069
|
? Buffer.concat(bodyChunks)
|
|
1025
1070
|
: undefined;
|
|
1026
1071
|
if (relayBody && parsedBody) {
|
|
1027
|
-
|
|
1028
|
-
if (typeof mt === "number" && mt > RELAY_MAX_TOKENS) {
|
|
1029
|
-
parsedBody.max_tokens = RELAY_MAX_TOKENS;
|
|
1030
|
-
}
|
|
1031
|
-
if (typeof parsedBody.reasoning_effort === "string") {
|
|
1032
|
-
const re = parsedBody.reasoning_effort.toLowerCase();
|
|
1033
|
-
if (re === "xhigh" || re === "max") {
|
|
1034
|
-
parsedBody.reasoning_effort = "max";
|
|
1035
|
-
} else if (re === "high" || re === "medium") {
|
|
1036
|
-
parsedBody.reasoning_effort = "high";
|
|
1037
|
-
} else {
|
|
1038
|
-
parsedBody.reasoning_effort = "low";
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1072
|
+
normalizeRequestBody(parsedBody, true);
|
|
1041
1073
|
relayBody = Buffer.from(JSON.stringify(parsedBody));
|
|
1042
1074
|
}
|
|
1043
1075
|
const response = await relayFetch(fullUrl, {
|
|
@@ -1081,15 +1113,8 @@ function startProxy(
|
|
|
1081
1113
|
}
|
|
1082
1114
|
// direct path (existing, untouched)
|
|
1083
1115
|
let directBody = Buffer.concat(bodyChunks);
|
|
1084
|
-
if (parsedBody
|
|
1085
|
-
|
|
1086
|
-
if (re === "xhigh" || re === "max") {
|
|
1087
|
-
parsedBody.reasoning_effort = "max";
|
|
1088
|
-
} else if (re === "high" || re === "medium") {
|
|
1089
|
-
parsedBody.reasoning_effort = "high";
|
|
1090
|
-
} else {
|
|
1091
|
-
parsedBody.reasoning_effort = "low";
|
|
1092
|
-
}
|
|
1116
|
+
if (parsedBody) {
|
|
1117
|
+
normalizeRequestBody(parsedBody, false);
|
|
1093
1118
|
directBody = Buffer.from(JSON.stringify(parsedBody));
|
|
1094
1119
|
}
|
|
1095
1120
|
const fwd = sanitizeHeaders(req.headers, target.hostname);
|