@victor-software-house/pi-openai-proxy 4.9.0 → 4.9.2
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 +21 -6
- package/dist/index.mjs +7 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -113,17 +113,32 @@ curl http://localhost:4141/v1/chat/completions \
|
|
|
113
113
|
| `stop` | Via passthrough |
|
|
114
114
|
| `user` | Via passthrough |
|
|
115
115
|
| `stream_options.include_usage` | Final usage chunk in SSE stream |
|
|
116
|
-
| `tools` / `tool_choice` | JSON Schema -> TypeBox conversion (supported subset) |
|
|
116
|
+
| `tools` / `tool_choice` | JSON Schema -> TypeBox conversion (supported subset); `tool_choice` translated per-provider |
|
|
117
117
|
| `tool_calls` in messages | Assistant tool call + tool result roundtrip |
|
|
118
|
+
| `parallel_tool_calls` | Forwarded to OpenAI/Codex; translated to `disable_parallel_tool_use` for Anthropic |
|
|
118
119
|
| `reasoning_effort` | Maps to pi's `ThinkingLevel` (`none`, `minimal`, `low`, `medium`, `high`, `xhigh`) |
|
|
119
|
-
| `response_format` | `text`, `json_object`, and `json_schema`
|
|
120
|
-
| `top_p` |
|
|
121
|
-
| `frequency_penalty` |
|
|
122
|
-
| `presence_penalty` |
|
|
123
|
-
| `seed` |
|
|
120
|
+
| `response_format` | `text`, `json_object`, and `json_schema` (OpenAI-compatible APIs only) |
|
|
121
|
+
| `top_p` | Supported by OpenAI, Anthropic (native), and Google (translated to `topP`) |
|
|
122
|
+
| `frequency_penalty` | OpenAI and Google only (translated to `frequencyPenalty`) |
|
|
123
|
+
| `presence_penalty` | OpenAI and Google only (translated to `presencePenalty`) |
|
|
124
|
+
| `seed` | OpenAI and Google only (translated to nested `generationConfig.seed`) |
|
|
125
|
+
| `stop` | Translated per-provider (`stop_sequences` for Anthropic, `stopSequences` for Google) |
|
|
126
|
+
| `metadata` | OpenAI passthrough; arbitrary keys silently skipped for other providers |
|
|
127
|
+
| `prediction` | OpenAI passthrough only (speculative decoding) |
|
|
124
128
|
|
|
125
129
|
**Not supported:** `n > 1`, `logprobs`, `logit_bias`, remote image URLs (disabled by default).
|
|
126
130
|
|
|
131
|
+
### Provider-aware field translation
|
|
132
|
+
|
|
133
|
+
Fields are translated to each provider's native format, not blindly forwarded:
|
|
134
|
+
|
|
135
|
+
- **OpenAI / Mistral**: All fields passed directly (same wire format)
|
|
136
|
+
- **Codex (Responses API)**: Only `tool_choice` and `parallel_tool_calls` (other fields rejected by API)
|
|
137
|
+
- **Anthropic**: `tool_choice` → `{ type }` format, `stop` → `stop_sequences`, `user` → `metadata.user_id`, `parallel_tool_calls: false` → `disable_parallel_tool_use`
|
|
138
|
+
- **Google**: Nested into `generationConfig` with camelCase names (`topP`, `stopSequences`, `seed`, etc.)
|
|
139
|
+
|
|
140
|
+
Fields that have no equivalent in a target provider are silently skipped — the request succeeds and the provider's default applies.
|
|
141
|
+
|
|
127
142
|
## Model Naming and Exposure
|
|
128
143
|
|
|
129
144
|
### Public model IDs
|
package/dist/index.mjs
CHANGED
|
@@ -324,6 +324,8 @@ const toolArgsSchema = z.record(z.string().trim(), z.unknown());
|
|
|
324
324
|
function convertMessages(messages) {
|
|
325
325
|
const systemParts = [];
|
|
326
326
|
const piMessages = [];
|
|
327
|
+
const toolCallNames = /* @__PURE__ */ new Map();
|
|
328
|
+
for (const msg of messages) if (msg !== void 0 && msg.role === "assistant" && "tool_calls" in msg) for (const tc of msg.tool_calls ?? []) toolCallNames.set(tc.id, tc.function.name);
|
|
327
329
|
for (let i = 0; i < messages.length; i++) {
|
|
328
330
|
const msg = messages[i];
|
|
329
331
|
if (msg === void 0) continue;
|
|
@@ -337,7 +339,8 @@ function convertMessages(messages) {
|
|
|
337
339
|
const assistantMsg = convertAssistantMessage(msg.content ?? null, msg.tool_calls);
|
|
338
340
|
piMessages.push(assistantMsg);
|
|
339
341
|
} else if (msg.role === "tool") {
|
|
340
|
-
const
|
|
342
|
+
const toolName = toolCallNames.get(msg.tool_call_id) ?? "";
|
|
343
|
+
const toolMsg = convertToolMessage(msg.content, msg.tool_call_id, toolName);
|
|
341
344
|
piMessages.push(toolMsg);
|
|
342
345
|
}
|
|
343
346
|
}
|
|
@@ -442,11 +445,11 @@ function convertAssistantMessage(textContent, toolCalls) {
|
|
|
442
445
|
timestamp: Date.now()
|
|
443
446
|
};
|
|
444
447
|
}
|
|
445
|
-
function convertToolMessage(content, toolCallId) {
|
|
448
|
+
function convertToolMessage(content, toolCallId, toolName) {
|
|
446
449
|
return {
|
|
447
450
|
role: "toolResult",
|
|
448
451
|
toolCallId,
|
|
449
|
-
toolName
|
|
452
|
+
toolName,
|
|
450
453
|
content: [{
|
|
451
454
|
type: "text",
|
|
452
455
|
text: content
|
|
@@ -1679,6 +1682,7 @@ function createRoutes(config, configReader = fileConfigReader) {
|
|
|
1679
1682
|
const conversion = convertMessages(request.messages);
|
|
1680
1683
|
if (!conversion.ok) return c.json(invalidRequest(conversion.message, conversion.param), 400);
|
|
1681
1684
|
const context = conversion.context;
|
|
1685
|
+
if (model.api === "openai-codex-responses" && context.systemPrompt === void 0) context.systemPrompt = "";
|
|
1682
1686
|
if (request.tools !== void 0 && request.tools.length > 0) {
|
|
1683
1687
|
const toolConversion = convertTools(request.tools);
|
|
1684
1688
|
if (!toolConversion.ok) return c.json(unsupportedParameter(toolConversion.param, toolConversion.message), 422);
|
package/package.json
CHANGED