@mmmbuto/zai-codex-bridge 0.1.7 → 0.1.8

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/package.json +1 -1
  2. package/src/server.js +39 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmmbuto/zai-codex-bridge",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
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": {
package/src/server.js CHANGED
@@ -80,10 +80,24 @@ function translateResponsesToChat(request) {
80
80
  content: request.input
81
81
  });
82
82
  } else if (Array.isArray(request.input)) {
83
- // Array of message objects
83
+ // Array of ResponseItem objects - filter only Message items with role
84
84
  for (const item of request.input) {
85
+ // Only process items with a 'role' field (Message items)
86
+ // Skip Reasoning, FunctionCall, LocalShellCall, etc.
87
+ if (!item.role) continue;
88
+
89
+ // Map non-standard roles to Z.AI-compatible roles
90
+ // Z.AI accepts: system, user, assistant
91
+ let role = item.role;
92
+ if (role === 'developer') {
93
+ role = 'user'; // Map developer to user
94
+ } else if (role !== 'system' && role !== 'user' && role !== 'assistant') {
95
+ // Skip any other non-standard roles
96
+ continue;
97
+ }
98
+
85
99
  const msg = {
86
- role: item.role,
100
+ role: role,
87
101
  content: flattenContent(item.content)
88
102
  };
89
103
 
@@ -127,7 +141,21 @@ function translateResponsesToChat(request) {
127
141
  }
128
142
 
129
143
  if (request.tools && Array.isArray(request.tools)) {
130
- chatRequest.tools = request.tools;
144
+ // Filter out tools with null or empty function
145
+ chatRequest.tools = request.tools.filter(tool => {
146
+ if (tool.type === 'function') {
147
+ // Check if function has required fields
148
+ return tool.function && typeof tool.function === 'object' &&
149
+ tool.function.name && tool.function.name.length > 0 &&
150
+ tool.function.parameters !== undefined && tool.function.parameters !== null;
151
+ }
152
+ // Keep non-function tools (if any)
153
+ return true;
154
+ });
155
+ // Only add tools array if there are valid tools
156
+ if (chatRequest.tools.length === 0) {
157
+ delete chatRequest.tools;
158
+ }
131
159
  }
132
160
 
133
161
  if (request.tool_choice) {
@@ -210,7 +238,9 @@ async function makeUpstreamRequest(path, body, headers) {
210
238
  base: ZAI_BASE_URL,
211
239
  hasAuth: !!upstreamHeaders.Authorization,
212
240
  bodyKeys: Object.keys(body),
213
- bodyPreview: JSON.stringify(body).substring(0, 200)
241
+ bodyPreview: JSON.stringify(body).substring(0, 800),
242
+ messagesCount: body.messages?.length || 0,
243
+ allRoles: body.messages?.map(m => m.role) || []
214
244
  });
215
245
 
216
246
  const response = await fetch(url, {
@@ -229,6 +259,7 @@ async function streamChatToResponses(stream, res) {
229
259
  const decoder = new TextDecoder();
230
260
  let buffer = '';
231
261
  let chunkCount = 0;
262
+ let deltaCount = 0;
232
263
 
233
264
  log('debug', 'Starting to process stream');
234
265
 
@@ -252,9 +283,10 @@ async function streamChatToResponses(stream, res) {
252
283
 
253
284
  // Check for stream end
254
285
  if (data === '[DONE]') {
255
- log('debug', 'Stream end received');
286
+ log('info', `Stream end received - wrote ${deltaCount} deltas total`);
256
287
  res.write(`event: completed\n`);
257
288
  res.write(`data: ${JSON.stringify({ status: 'completed' })}\n\n`);
289
+ log('info', 'Sent completed event');
258
290
  return;
259
291
  }
260
292
 
@@ -268,6 +300,7 @@ async function streamChatToResponses(stream, res) {
268
300
  const content = delta?.content || delta?.reasoning_content || '';
269
301
 
270
302
  if (content) {
303
+ deltaCount++;
271
304
  log('debug', 'Writing delta:', content.substring(0, 30));
272
305
  res.write(`event: output.text.delta\n`);
273
306
  res.write(`data: ${JSON.stringify({ value: content })}\n\n`);
@@ -283,7 +316,7 @@ async function streamChatToResponses(stream, res) {
283
316
  }
284
317
  }
285
318
 
286
- log('debug', 'Stream ended naturally');
319
+ log('info', `Stream ended naturally - wrote ${deltaCount} deltas`);
287
320
  }
288
321
 
289
322
  /**