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.
Files changed (2) hide show
  1. package/extensions/index.ts +51 -26
  2. package/package.json +1 -1
@@ -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
- const mt = parsedBody.max_tokens ?? parsedBody.maxTokens;
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 && typeof parsedBody.reasoning_effort === "string") {
1085
- const re = parsedBody.reasoning_effort.toLowerCase();
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-freeflow",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Personal multi-cloud rolling fallback relay for OpenCode Zen and KiloCode models in OMP/Pi",
5
5
  "keywords": [
6
6
  "pi-package",