@victor-software-house/pi-openai-proxy 4.6.0 → 4.6.1
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 +65 -3
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1141,7 +1141,17 @@ const chatCompletionRequestSchema = z.object({
|
|
|
1141
1141
|
}).strict();
|
|
1142
1142
|
/**
|
|
1143
1143
|
* Fields that are explicitly rejected with a helpful error.
|
|
1144
|
-
*
|
|
1144
|
+
*
|
|
1145
|
+
* `n`, `logprobs`, `top_logprobs`, `logit_bias`: not supported by the pi SDK's
|
|
1146
|
+
* simple completion interface and unlikely to be promoted.
|
|
1147
|
+
*
|
|
1148
|
+
* `functions`, `function_call`: deprecated OpenAI fields, superseded by `tools`
|
|
1149
|
+
* and `tool_choice`.
|
|
1150
|
+
*
|
|
1151
|
+
* `parallel_tool_calls`: the pi SDK does not expose parallel tool call control.
|
|
1152
|
+
* The SSE streaming code handles multiple tool calls per response, so the response
|
|
1153
|
+
* side is capable, but the proxy cannot guarantee the flag reaches the provider.
|
|
1154
|
+
* Needs deeper analysis — see Phase 3D in TODO.md.
|
|
1145
1155
|
*/
|
|
1146
1156
|
const rejectedFields = [
|
|
1147
1157
|
"n",
|
|
@@ -1227,6 +1237,8 @@ const SKIP_PAYLOAD_PASSTHROUGH_APIS = new Set(["openai-codex-responses"]);
|
|
|
1227
1237
|
/**
|
|
1228
1238
|
* Collect fields that need to be injected via onPayload.
|
|
1229
1239
|
* Skips passthrough for APIs that use non-standard request formats.
|
|
1240
|
+
*
|
|
1241
|
+
* @internal Exported for unit testing only.
|
|
1230
1242
|
*/
|
|
1231
1243
|
function collectPayloadFields(request, api) {
|
|
1232
1244
|
if (SKIP_PAYLOAD_PASSTHROUGH_APIS.has(api)) return;
|
|
@@ -1260,9 +1272,55 @@ function collectPayloadFields(request, api) {
|
|
|
1260
1272
|
fields["response_format"] = request.response_format;
|
|
1261
1273
|
hasFields = true;
|
|
1262
1274
|
}
|
|
1275
|
+
if (request.tool_choice !== void 0) {
|
|
1276
|
+
fields["tool_choice"] = request.tool_choice;
|
|
1277
|
+
hasFields = true;
|
|
1278
|
+
}
|
|
1263
1279
|
return hasFields ? fields : void 0;
|
|
1264
1280
|
}
|
|
1265
1281
|
/**
|
|
1282
|
+
* Collect tool strict flags from the original OpenAI request.
|
|
1283
|
+
*
|
|
1284
|
+
* The pi SDK's `Tool` interface has no `strict` field, so the SDK always sets
|
|
1285
|
+
* `strict: false` when building the upstream payload. This function extracts
|
|
1286
|
+
* the per-tool strict flags from the original request so they can be restored
|
|
1287
|
+
* via `onPayload` after the SDK builds the payload.
|
|
1288
|
+
*
|
|
1289
|
+
* Returns a map of tool index -> true for tools that requested strict mode,
|
|
1290
|
+
* or undefined if no tools use strict mode.
|
|
1291
|
+
*
|
|
1292
|
+
* @internal Exported for unit testing only.
|
|
1293
|
+
*/
|
|
1294
|
+
function collectToolStrictFlags(tools) {
|
|
1295
|
+
if (tools === void 0 || tools.length === 0) return;
|
|
1296
|
+
let flags;
|
|
1297
|
+
for (let i = 0; i < tools.length; i++) if (tools[i]?.function.strict === true) {
|
|
1298
|
+
flags ??= /* @__PURE__ */ new Map();
|
|
1299
|
+
flags.set(i, true);
|
|
1300
|
+
}
|
|
1301
|
+
return flags;
|
|
1302
|
+
}
|
|
1303
|
+
/**
|
|
1304
|
+
* Apply strict flags to tool definitions in the upstream payload.
|
|
1305
|
+
*
|
|
1306
|
+
* The pi SDK always sets `strict: false` on tool definitions. This function
|
|
1307
|
+
* patches the payload's `tools` array to restore the client's requested
|
|
1308
|
+
* `strict: true` flags on the matching tool definitions.
|
|
1309
|
+
*
|
|
1310
|
+
* @internal Exported for unit testing only.
|
|
1311
|
+
*/
|
|
1312
|
+
function applyToolStrictFlags(payload, strictFlags) {
|
|
1313
|
+
const tools = payload["tools"];
|
|
1314
|
+
if (!Array.isArray(tools)) return;
|
|
1315
|
+
for (const [index, _flag] of strictFlags) {
|
|
1316
|
+
const tool = tools[index];
|
|
1317
|
+
if (isRecord(tool)) {
|
|
1318
|
+
const fn = tool["function"];
|
|
1319
|
+
if (isRecord(fn)) fn["strict"] = true;
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
/**
|
|
1266
1324
|
* Combine a client disconnect signal with an upstream timeout into a single signal.
|
|
1267
1325
|
* Returns the combined signal, or undefined if neither is provided.
|
|
1268
1326
|
*/
|
|
@@ -1293,8 +1351,12 @@ async function buildStreamOptions(model, request, options) {
|
|
|
1293
1351
|
if (apiKey !== void 0) opts.apiKey = apiKey;
|
|
1294
1352
|
}
|
|
1295
1353
|
const payloadFields = collectPayloadFields(request, model.api);
|
|
1296
|
-
|
|
1297
|
-
|
|
1354
|
+
const strictFlags = collectToolStrictFlags(request.tools);
|
|
1355
|
+
if (payloadFields !== void 0 || strictFlags !== void 0) opts.onPayload = (payload) => {
|
|
1356
|
+
if (isRecord(payload)) {
|
|
1357
|
+
if (payloadFields !== void 0) for (const [key, value] of Object.entries(payloadFields)) payload[key] = value;
|
|
1358
|
+
if (strictFlags !== void 0) applyToolStrictFlags(payload, strictFlags);
|
|
1359
|
+
}
|
|
1298
1360
|
return payload;
|
|
1299
1361
|
};
|
|
1300
1362
|
return opts;
|
package/package.json
CHANGED