@mmmbuto/zai-codex-bridge 0.4.2 → 0.4.4
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/CHANGELOG.md +19 -0
- package/README.md +13 -3
- package/package.json +3 -3
- package/src/server.js +140 -43
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.4.4] - 2026-01-16
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Normalize `bin` path and repository URL for npm publish compatibility
|
|
12
|
+
|
|
13
|
+
## [0.4.3] - 2026-01-16
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- Auto-enable tool bridging when tool-related fields are present in the request
|
|
17
|
+
- Extra logging to surface `allowTools` and `toolsPresent` per request
|
|
18
|
+
- Debug tool summary logging (types and sample names)
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- Correct output_index mapping for streaming tool call events
|
|
22
|
+
- Filter non-function tools to avoid upstream schema errors
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
- README guidance for MCP/tools troubleshooting and proxy startup
|
|
26
|
+
|
|
8
27
|
## [0.4.2] - 2026-01-16
|
|
9
28
|
|
|
10
29
|
### Changed
|
package/README.md
CHANGED
|
@@ -99,7 +99,8 @@ Codex tool-calling / MCP memory requires an additional compatibility layer:
|
|
|
99
99
|
- Codex uses **Responses API tool events** (function call items + arguments delta/done, plus function_call_output inputs)
|
|
100
100
|
- Some upstream models/providers may not emit tool calls (or may emit them in a different shape)
|
|
101
101
|
|
|
102
|
-
This proxy can **attempt** to bridge tools when
|
|
102
|
+
This proxy can **attempt** to bridge tools automatically when the request carries tool definitions
|
|
103
|
+
(`tools`, `tool_choice`, or tool outputs). You can also force it on:
|
|
103
104
|
|
|
104
105
|
```bash
|
|
105
106
|
export ALLOW_TOOLS=1
|
|
@@ -111,6 +112,7 @@ Important:
|
|
|
111
112
|
- Responses `tools` + `tool_choice` → Chat `tools` + `tool_choice`
|
|
112
113
|
- Chat `tool_calls` (stream/non-stream) → Responses function-call events
|
|
113
114
|
- Responses `function_call_output` → Chat `role=tool` messages
|
|
115
|
+
- Non-function tool types are dropped for Z.AI compatibility.
|
|
114
116
|
|
|
115
117
|
(See repo changelog and docs for the exact implemented behavior.)
|
|
116
118
|
|
|
@@ -144,7 +146,8 @@ export ZAI_BASE_URL=https://api.z.ai/api/coding/paas/v4
|
|
|
144
146
|
export LOG_LEVEL=info
|
|
145
147
|
|
|
146
148
|
# Optional
|
|
147
|
-
export ALLOW_TOOLS=1
|
|
149
|
+
export ALLOW_TOOLS=1 # force tool bridging (otherwise auto-enabled when tools are present)
|
|
150
|
+
export ALLOW_SYSTEM=1 # only if your provider supports system role
|
|
148
151
|
```
|
|
149
152
|
|
|
150
153
|
---
|
|
@@ -161,7 +164,7 @@ codex-with-zai() {
|
|
|
161
164
|
local PROXY_PID=""
|
|
162
165
|
|
|
163
166
|
if ! curl -fsS "$HEALTH" >/dev/null 2>&1; then
|
|
164
|
-
zai-codex-bridge --host "$HOST" --port "$PORT" >/dev/null 2>&1 &
|
|
167
|
+
ALLOW_TOOLS=1 zai-codex-bridge --host "$HOST" --port "$PORT" >/dev/null 2>&1 &
|
|
165
168
|
PROXY_PID=$!
|
|
166
169
|
trap 'kill $PROXY_PID 2>/dev/null' EXIT INT TERM
|
|
167
170
|
sleep 1
|
|
@@ -241,6 +244,13 @@ codex-with-zai -m "GLM-4.7"
|
|
|
241
244
|
- Ensure `base_url` points to the proxy root (example: `http://127.0.0.1:31415`).
|
|
242
245
|
- Confirm the proxy is running and `/health` returns `ok`.
|
|
243
246
|
|
|
247
|
+
### MCP/tools not being called
|
|
248
|
+
- Check proxy logs for `allowTools: true` and `toolsPresent: true`.
|
|
249
|
+
- If `toolsPresent: false`, Codex did not send tool definitions (verify your provider config).
|
|
250
|
+
- If tools are present but the model prints literal `<function=...>` markup or never emits tool calls,
|
|
251
|
+
your upstream model likely doesn’t support tool calling.
|
|
252
|
+
- If your provider supports `system` role, try `ALLOW_SYSTEM=1` to improve tool adherence.
|
|
253
|
+
|
|
244
254
|
### 502 Bad Gateway
|
|
245
255
|
- Proxy reached upstream but upstream failed. Enable debug:
|
|
246
256
|
```bash
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mmmbuto/zai-codex-bridge",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "Local proxy that translates OpenAI Responses API format to Z.AI Chat Completions format for Codex",
|
|
5
5
|
"main": "src/server.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"zai-codex-bridge": "
|
|
7
|
+
"zai-codex-bridge": "bin/zai-codex-bridge"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "node src/server.js",
|
|
@@ -28,6 +28,6 @@
|
|
|
28
28
|
},
|
|
29
29
|
"repository": {
|
|
30
30
|
"type": "git",
|
|
31
|
-
"url": "https://github.com/DioNanos/zai-codex-bridge.git"
|
|
31
|
+
"url": "git+https://github.com/DioNanos/zai-codex-bridge.git"
|
|
32
32
|
}
|
|
33
33
|
}
|
package/src/server.js
CHANGED
|
@@ -22,7 +22,7 @@ const DEFAULT_MODEL = process.env.DEFAULT_MODEL || 'glm-4.7';
|
|
|
22
22
|
|
|
23
23
|
// Env toggles for compatibility
|
|
24
24
|
const ALLOW_SYSTEM = process.env.ALLOW_SYSTEM === '1';
|
|
25
|
-
const
|
|
25
|
+
const ALLOW_TOOLS_ENV = process.env.ALLOW_TOOLS === '1';
|
|
26
26
|
|
|
27
27
|
function nowSec() {
|
|
28
28
|
return Math.floor(Date.now() / 1000);
|
|
@@ -90,6 +90,67 @@ function detectFormat(body) {
|
|
|
90
90
|
return 'unknown';
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Detect if request carries tool-related data
|
|
95
|
+
*/
|
|
96
|
+
function requestHasTools(request) {
|
|
97
|
+
if (!request || typeof request !== 'object') return false;
|
|
98
|
+
|
|
99
|
+
if (Array.isArray(request.tools) && request.tools.length > 0) return true;
|
|
100
|
+
if (request.tool_choice) return true;
|
|
101
|
+
|
|
102
|
+
if (Array.isArray(request.input)) {
|
|
103
|
+
for (const item of request.input) {
|
|
104
|
+
if (!item) continue;
|
|
105
|
+
if (item.type === 'function_call_output') return true;
|
|
106
|
+
if (Array.isArray(item.tool_calls) && item.tool_calls.length > 0) return true;
|
|
107
|
+
if (item.tool_call_id) return true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (Array.isArray(request.messages)) {
|
|
112
|
+
for (const msg of request.messages) {
|
|
113
|
+
if (!msg) continue;
|
|
114
|
+
if (msg.role === 'tool') return true;
|
|
115
|
+
if (Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0) return true;
|
|
116
|
+
if (msg.tool_call_id) return true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function summarizeTools(tools, limit = 8) {
|
|
124
|
+
if (!Array.isArray(tools)) return null;
|
|
125
|
+
const types = {};
|
|
126
|
+
const names = [];
|
|
127
|
+
|
|
128
|
+
for (const tool of tools) {
|
|
129
|
+
const type = tool?.type || 'unknown';
|
|
130
|
+
types[type] = (types[type] || 0) + 1;
|
|
131
|
+
if (names.length < limit) {
|
|
132
|
+
if (type === 'function') {
|
|
133
|
+
names.push(tool?.function?.name || '(missing_name)');
|
|
134
|
+
} else {
|
|
135
|
+
names.push(type);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return { count: tools.length, types, sample_names: names };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function summarizeToolShape(tool) {
|
|
144
|
+
if (!tool || typeof tool !== 'object') return null;
|
|
145
|
+
return {
|
|
146
|
+
keys: Object.keys(tool),
|
|
147
|
+
type: tool.type,
|
|
148
|
+
name: tool.name,
|
|
149
|
+
functionKeys: tool.function && typeof tool.function === 'object' ? Object.keys(tool.function) : null,
|
|
150
|
+
functionName: tool.function?.name
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
93
154
|
/**
|
|
94
155
|
* Flatten content parts to string - supports text, input_text, output_text
|
|
95
156
|
*/
|
|
@@ -113,7 +174,7 @@ function flattenContent(content) {
|
|
|
113
174
|
/**
|
|
114
175
|
* Translate Responses format to Chat Completions format
|
|
115
176
|
*/
|
|
116
|
-
function translateResponsesToChat(request) {
|
|
177
|
+
function translateResponsesToChat(request, allowTools) {
|
|
117
178
|
const messages = [];
|
|
118
179
|
|
|
119
180
|
// Add system message from instructions (with ALLOW_SYSTEM toggle)
|
|
@@ -145,8 +206,8 @@ function translateResponsesToChat(request) {
|
|
|
145
206
|
} else if (Array.isArray(request.input)) {
|
|
146
207
|
// Array of ResponseItem objects
|
|
147
208
|
for (const item of request.input) {
|
|
148
|
-
// Handle function_call_output items (tool responses) - only if
|
|
149
|
-
if (
|
|
209
|
+
// Handle function_call_output items (tool responses) - only if allowTools
|
|
210
|
+
if (allowTools && item.type === 'function_call_output') {
|
|
150
211
|
const toolMsg = {
|
|
151
212
|
role: 'tool',
|
|
152
213
|
tool_call_id: item.call_id || item.tool_call_id || '',
|
|
@@ -187,13 +248,13 @@ function translateResponsesToChat(request) {
|
|
|
187
248
|
content: flattenContent(item.content)
|
|
188
249
|
};
|
|
189
250
|
|
|
190
|
-
// Handle tool calls if present (only if
|
|
191
|
-
if (
|
|
251
|
+
// Handle tool calls if present (only if allowTools)
|
|
252
|
+
if (allowTools && item.tool_calls && Array.isArray(item.tool_calls)) {
|
|
192
253
|
msg.tool_calls = item.tool_calls;
|
|
193
254
|
}
|
|
194
255
|
|
|
195
|
-
// Handle tool call ID for tool responses (only if
|
|
196
|
-
if (
|
|
256
|
+
// Handle tool call ID for tool responses (only if allowTools)
|
|
257
|
+
if (allowTools && item.tool_call_id) {
|
|
197
258
|
msg.tool_call_id = item.tool_call_id;
|
|
198
259
|
}
|
|
199
260
|
|
|
@@ -226,27 +287,49 @@ function translateResponsesToChat(request) {
|
|
|
226
287
|
chatRequest.top_p = request.top_p;
|
|
227
288
|
}
|
|
228
289
|
|
|
229
|
-
// Tools handling (only if
|
|
230
|
-
if (
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
290
|
+
// Tools handling (only if allowTools)
|
|
291
|
+
if (allowTools && request.tools && Array.isArray(request.tools)) {
|
|
292
|
+
const originalCount = request.tools.length;
|
|
293
|
+
const normalized = [];
|
|
294
|
+
|
|
295
|
+
for (const tool of request.tools) {
|
|
296
|
+
if (!tool || tool.type !== 'function') continue;
|
|
297
|
+
const fn = tool.function && typeof tool.function === 'object' ? tool.function : null;
|
|
298
|
+
const name = (fn?.name || tool.name || '').trim();
|
|
299
|
+
if (!name) continue;
|
|
300
|
+
|
|
301
|
+
// Prefer nested function fields, fall back to top-level ones if present
|
|
302
|
+
const description = fn?.description ?? tool.description;
|
|
303
|
+
const parameters = fn?.parameters ?? tool.parameters ?? { type: 'object', properties: {} };
|
|
304
|
+
|
|
305
|
+
const functionObj = { name, parameters };
|
|
306
|
+
if (description) functionObj.description = description;
|
|
307
|
+
|
|
308
|
+
// Send minimal tool schema for upstream compatibility
|
|
309
|
+
normalized.push({
|
|
310
|
+
type: 'function',
|
|
311
|
+
function: functionObj
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
chatRequest.tools = normalized;
|
|
316
|
+
|
|
317
|
+
const dropped = originalCount - chatRequest.tools.length;
|
|
318
|
+
if (dropped > 0) {
|
|
319
|
+
log('warn', `Dropped ${dropped} non-function or invalid tools for upstream compatibility`);
|
|
320
|
+
}
|
|
321
|
+
|
|
242
322
|
// Only add tools array if there are valid tools
|
|
243
323
|
if (chatRequest.tools.length === 0) {
|
|
244
324
|
delete chatRequest.tools;
|
|
245
325
|
}
|
|
246
326
|
}
|
|
247
327
|
|
|
248
|
-
if (
|
|
328
|
+
if (allowTools && request.tool_choice) {
|
|
249
329
|
chatRequest.tool_choice = request.tool_choice;
|
|
330
|
+
if (!chatRequest.tools || chatRequest.tools.length === 0) {
|
|
331
|
+
delete chatRequest.tool_choice;
|
|
332
|
+
}
|
|
250
333
|
}
|
|
251
334
|
|
|
252
335
|
log('debug', 'Translated Responses->Chat:', {
|
|
@@ -261,9 +344,9 @@ function translateResponsesToChat(request) {
|
|
|
261
344
|
/**
|
|
262
345
|
* Translate Chat Completions response to Responses format
|
|
263
346
|
* Handles both output_text and reasoning_text content
|
|
264
|
-
* Handles tool_calls if present (only if
|
|
347
|
+
* Handles tool_calls if present (only if allowTools)
|
|
265
348
|
*/
|
|
266
|
-
function translateChatToResponses(chatResponse, responsesRequest, ids) {
|
|
349
|
+
function translateChatToResponses(chatResponse, responsesRequest, ids, allowTools) {
|
|
267
350
|
const msg = chatResponse.choices?.[0]?.message ?? {};
|
|
268
351
|
const outputText = msg.content ?? '';
|
|
269
352
|
const reasoningText = msg.reasoning_content ?? '';
|
|
@@ -289,8 +372,8 @@ function translateChatToResponses(chatResponse, responsesRequest, ids) {
|
|
|
289
372
|
// Build output array: message item + any function_call items
|
|
290
373
|
const finalOutput = [msgItem];
|
|
291
374
|
|
|
292
|
-
// Handle tool_calls (only if
|
|
293
|
-
if (
|
|
375
|
+
// Handle tool_calls (only if allowTools)
|
|
376
|
+
if (allowTools && msg.tool_calls && Array.isArray(msg.tool_calls)) {
|
|
294
377
|
for (const tc of msg.tool_calls) {
|
|
295
378
|
const callId = tc.id || `call_${randomUUID().replace(/-/g, '')}`;
|
|
296
379
|
const name = tc.function?.name || '';
|
|
@@ -386,7 +469,7 @@ async function makeUpstreamRequest(path, body, headers) {
|
|
|
386
469
|
* Handle streaming response from Z.AI with proper Responses API event format
|
|
387
470
|
* Separates reasoning_content, content, and tool_calls into distinct events
|
|
388
471
|
*/
|
|
389
|
-
async function streamChatToResponses(upstreamBody, res, responsesRequest, ids) {
|
|
472
|
+
async function streamChatToResponses(upstreamBody, res, responsesRequest, ids, allowTools) {
|
|
390
473
|
const decoder = new TextDecoder();
|
|
391
474
|
const reader = upstreamBody.getReader();
|
|
392
475
|
let buffer = '';
|
|
@@ -445,9 +528,9 @@ async function streamChatToResponses(upstreamBody, res, responsesRequest, ids) {
|
|
|
445
528
|
let out = '';
|
|
446
529
|
let reasoning = '';
|
|
447
530
|
|
|
448
|
-
// Tool call tracking (only if
|
|
449
|
-
const toolCallsMap = new Map(); // index -> { callId, name, arguments, partialArgs }
|
|
450
|
-
|
|
531
|
+
// Tool call tracking (only if allowTools)
|
|
532
|
+
const toolCallsMap = new Map(); // index -> { callId, name, outputIndex, arguments, partialArgs }
|
|
533
|
+
const TOOL_BASE_INDEX = 1; // After message item
|
|
451
534
|
|
|
452
535
|
while (true) {
|
|
453
536
|
const { done, value } = await reader.read();
|
|
@@ -477,8 +560,8 @@ async function streamChatToResponses(upstreamBody, res, responsesRequest, ids) {
|
|
|
477
560
|
|
|
478
561
|
const delta = chunk.choices?.[0]?.delta || {};
|
|
479
562
|
|
|
480
|
-
// Handle tool_calls (only if
|
|
481
|
-
if (
|
|
563
|
+
// Handle tool_calls (only if allowTools)
|
|
564
|
+
if (allowTools && delta.tool_calls && Array.isArray(delta.tool_calls)) {
|
|
482
565
|
for (const tc of delta.tool_calls) {
|
|
483
566
|
const index = tc.index;
|
|
484
567
|
if (index == null) continue;
|
|
@@ -487,10 +570,12 @@ async function streamChatToResponses(upstreamBody, res, responsesRequest, ids) {
|
|
|
487
570
|
// New tool call - send output_item.added
|
|
488
571
|
const callId = tc.id || `call_${randomUUID().replace(/-/g, '')}`;
|
|
489
572
|
const name = tc.function?.name || '';
|
|
573
|
+
const outputIndex = TOOL_BASE_INDEX + index;
|
|
490
574
|
|
|
491
575
|
toolCallsMap.set(index, {
|
|
492
576
|
callId,
|
|
493
577
|
name,
|
|
578
|
+
outputIndex,
|
|
494
579
|
arguments: '',
|
|
495
580
|
partialArgs: ''
|
|
496
581
|
});
|
|
@@ -506,7 +591,7 @@ async function streamChatToResponses(upstreamBody, res, responsesRequest, ids) {
|
|
|
506
591
|
|
|
507
592
|
sse({
|
|
508
593
|
type: 'response.output_item.added',
|
|
509
|
-
output_index:
|
|
594
|
+
output_index: outputIndex,
|
|
510
595
|
item: fnItemInProgress,
|
|
511
596
|
});
|
|
512
597
|
|
|
@@ -514,7 +599,7 @@ async function streamChatToResponses(upstreamBody, res, responsesRequest, ids) {
|
|
|
514
599
|
sse({
|
|
515
600
|
type: 'response.function_call_name.done',
|
|
516
601
|
item_id: callId,
|
|
517
|
-
output_index:
|
|
602
|
+
output_index: outputIndex,
|
|
518
603
|
name: name,
|
|
519
604
|
});
|
|
520
605
|
}
|
|
@@ -528,7 +613,7 @@ async function streamChatToResponses(upstreamBody, res, responsesRequest, ids) {
|
|
|
528
613
|
sse({
|
|
529
614
|
type: 'response.function_call_name.done',
|
|
530
615
|
item_id: tcData.callId,
|
|
531
|
-
output_index:
|
|
616
|
+
output_index: tcData.outputIndex,
|
|
532
617
|
name: tcData.name,
|
|
533
618
|
});
|
|
534
619
|
}
|
|
@@ -540,7 +625,7 @@ async function streamChatToResponses(upstreamBody, res, responsesRequest, ids) {
|
|
|
540
625
|
sse({
|
|
541
626
|
type: 'response.function_call_arguments.delta',
|
|
542
627
|
item_id: tcData.callId,
|
|
543
|
-
output_index:
|
|
628
|
+
output_index: tcData.outputIndex,
|
|
544
629
|
delta: tc.function.arguments,
|
|
545
630
|
});
|
|
546
631
|
}
|
|
@@ -553,7 +638,7 @@ async function streamChatToResponses(upstreamBody, res, responsesRequest, ids) {
|
|
|
553
638
|
sse({
|
|
554
639
|
type: 'response.function_call_arguments.done',
|
|
555
640
|
item_id: tcData.callId,
|
|
556
|
-
output_index:
|
|
641
|
+
output_index: tcData.outputIndex,
|
|
557
642
|
arguments: tcData.arguments,
|
|
558
643
|
});
|
|
559
644
|
|
|
@@ -568,7 +653,7 @@ async function streamChatToResponses(upstreamBody, res, responsesRequest, ids) {
|
|
|
568
653
|
|
|
569
654
|
sse({
|
|
570
655
|
type: 'response.output_item.done',
|
|
571
|
-
output_index:
|
|
656
|
+
output_index: tcData.outputIndex,
|
|
572
657
|
item: fnItemDone,
|
|
573
658
|
});
|
|
574
659
|
}
|
|
@@ -646,8 +731,9 @@ async function streamChatToResponses(upstreamBody, res, responsesRequest, ids) {
|
|
|
646
731
|
|
|
647
732
|
// Build final output array: message item + any function_call items
|
|
648
733
|
const finalOutput = [msgItemDone];
|
|
649
|
-
if (
|
|
650
|
-
|
|
734
|
+
if (allowTools && toolCallsMap.size > 0) {
|
|
735
|
+
const ordered = Array.from(toolCallsMap.entries()).sort((a, b) => a[0] - b[0]);
|
|
736
|
+
for (const [, tcData] of ordered) {
|
|
651
737
|
finalOutput.push({
|
|
652
738
|
id: tcData.callId,
|
|
653
739
|
type: 'function_call',
|
|
@@ -707,19 +793,30 @@ async function handlePostRequest(req, res) {
|
|
|
707
793
|
return;
|
|
708
794
|
}
|
|
709
795
|
|
|
796
|
+
const hasTools = requestHasTools(request);
|
|
797
|
+
const allowTools = ALLOW_TOOLS_ENV || hasTools;
|
|
798
|
+
|
|
710
799
|
log('info', 'Incoming request:', {
|
|
711
800
|
path,
|
|
712
801
|
format: detectFormat(request),
|
|
713
802
|
model: request.model,
|
|
803
|
+
allowTools,
|
|
804
|
+
toolsPresent: hasTools,
|
|
714
805
|
authHeader: req.headers['authorization'] || req.headers['Authorization'] || 'none'
|
|
715
806
|
});
|
|
807
|
+
if (hasTools) {
|
|
808
|
+
log('debug', 'Tools summary:', summarizeTools(request.tools));
|
|
809
|
+
if (request.tools && request.tools[0]) {
|
|
810
|
+
log('debug', 'Tool[0] shape:', summarizeToolShape(request.tools[0]));
|
|
811
|
+
}
|
|
812
|
+
}
|
|
716
813
|
|
|
717
814
|
let upstreamBody;
|
|
718
815
|
const format = detectFormat(request);
|
|
719
816
|
|
|
720
817
|
if (format === 'responses') {
|
|
721
818
|
// Translate Responses to Chat
|
|
722
|
-
upstreamBody = translateResponsesToChat(request);
|
|
819
|
+
upstreamBody = translateResponsesToChat(request, allowTools);
|
|
723
820
|
} else if (format === 'chat') {
|
|
724
821
|
// Pass through Chat format
|
|
725
822
|
upstreamBody = request;
|
|
@@ -769,7 +866,7 @@ async function handlePostRequest(req, res) {
|
|
|
769
866
|
});
|
|
770
867
|
|
|
771
868
|
try {
|
|
772
|
-
await streamChatToResponses(upstreamResponse.body, res, request, ids);
|
|
869
|
+
await streamChatToResponses(upstreamResponse.body, res, request, ids, allowTools);
|
|
773
870
|
log('info', 'Streaming completed');
|
|
774
871
|
} catch (e) {
|
|
775
872
|
log('error', 'Streaming error:', e);
|
|
@@ -784,7 +881,7 @@ async function handlePostRequest(req, res) {
|
|
|
784
881
|
msgId: `msg_${randomUUID().replace(/-/g, '')}`,
|
|
785
882
|
};
|
|
786
883
|
|
|
787
|
-
const response = translateChatToResponses(chatResponse, request, ids);
|
|
884
|
+
const response = translateChatToResponses(chatResponse, request, ids, allowTools);
|
|
788
885
|
|
|
789
886
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
790
887
|
res.end(JSON.stringify(response));
|