@wu529778790/open-im 1.11.8-beta.24 → 1.11.8-beta.25

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.
@@ -217,22 +217,27 @@ export function runCodex(cliPath, prompt, sessionId, workDir, callbacks, options
217
217
  const event = parseCodexEvent(line);
218
218
  if (!event)
219
219
  return;
220
- const type = event.type;
221
- log.debug(`[Codex event] type=${type}`);
222
- if (type === 'thread.started') {
223
- const threadId = event.thread_id ?? '';
220
+ // Codex CLI JSONL 格式是嵌套的:顶层 type "event_msg" / "response_item",
221
+ // 真正的子类型在 payload.type 里。旧版扁平格式也兼容。
222
+ const topType = event.type;
223
+ const payload = event.payload ?? event;
224
+ const type = payload.type ?? topType;
225
+ log.debug(`[Codex event] topType=${topType} type=${type}`);
226
+ // thread.started / session_meta → 拿 session ID
227
+ if (type === 'thread.started' || type === 'session_meta') {
228
+ const threadId = payload.thread_id ?? payload.session_id ?? event.thread_id ?? '';
224
229
  if (threadId)
225
230
  callbacks.onSessionId?.(threadId);
226
231
  return;
227
232
  }
228
233
  if (type === 'turn.failed') {
229
234
  completed = true;
230
- const err = event.error;
235
+ const err = payload.error ?? event.error;
231
236
  callbacks.onError(err?.message ?? 'Codex turn failed');
232
237
  return;
233
238
  }
234
239
  if (type === 'error') {
235
- const msg = event.message;
240
+ const msg = payload.message ?? event.message;
236
241
  if (msg?.includes('Reconnecting')) {
237
242
  return;
238
243
  }
@@ -240,12 +245,12 @@ export function runCodex(cliPath, prompt, sessionId, workDir, callbacks, options
240
245
  callbacks.onError(msg ?? 'Codex stream error');
241
246
  return;
242
247
  }
243
- if (type === 'item.started' || type === 'item.updated' || type === 'item.completed') {
244
- const item = event.item;
245
- if (!item)
246
- return;
247
- const itemType = item.type;
248
- if (itemType === 'reasoning' && type === 'item.completed') {
248
+ // item 事件:payload 里可能有 item 字段,或者 payload 本身就是 item
249
+ if (topType === 'response_item' || type === 'item.started' || type === 'item.updated' || type === 'item.completed') {
250
+ const item = payload.item ?? payload;
251
+ const itemType = item.type ?? type;
252
+ if (itemType === 'reasoning') {
253
+ // Codex reasoning 可能是 encrypted_content(不可读),只在有 text 时累加
249
254
  const text = item.text;
250
255
  if (text) {
251
256
  accumulatedThinking += (accumulatedThinking ? '\n\n' : '') + text;
@@ -253,23 +258,41 @@ export function runCodex(cliPath, prompt, sessionId, workDir, callbacks, options
253
258
  }
254
259
  return;
255
260
  }
261
+ // function_call(Codex 新格式:response_item.type=function_call)
262
+ if (itemType === 'function_call') {
263
+ const name = item.name ?? 'unknown';
264
+ const args = item.arguments;
265
+ const toolName = name === 'exec_command' ? 'Bash' : name === 'apply_patch' ? 'Edit' : name;
266
+ toolStats[toolName] = (toolStats[toolName] || 0) + 1;
267
+ callbacks.onToolUse?.(toolName, args ? { arguments: args } : {});
268
+ return;
269
+ }
270
+ // custom_tool_call(apply_patch 等)
271
+ if (itemType === 'custom_tool_call') {
272
+ const name = item.name ?? 'unknown';
273
+ const toolName = name === 'apply_patch' ? 'Edit' : name;
274
+ toolStats[toolName] = (toolStats[toolName] || 0) + 1;
275
+ callbacks.onToolUse?.(toolName, { input: item.input });
276
+ return;
277
+ }
278
+ // command_execution(旧格式)
256
279
  if (itemType === 'command_execution') {
257
280
  const cmd = item.command;
258
- if (cmd && type === 'item.started') {
259
- const toolName = 'Bash';
260
- toolStats[toolName] = (toolStats[toolName] || 0) + 1;
261
- callbacks.onToolUse?.(toolName, { command: cmd });
281
+ if (cmd) {
282
+ toolStats['Bash'] = (toolStats['Bash'] || 0) + 1;
283
+ callbacks.onToolUse?.('Bash', { command: cmd });
262
284
  }
263
285
  return;
264
286
  }
265
- if (itemType === 'file_change' && type === 'item.completed') {
287
+ // file_change(旧格式)
288
+ if (itemType === 'file_change') {
266
289
  const changes = item.changes;
267
- const toolName = 'Edit';
268
- toolStats[toolName] = (toolStats[toolName] || 0) + 1;
269
- callbacks.onToolUse?.(toolName, { changes });
290
+ toolStats['Edit'] = (toolStats['Edit'] || 0) + 1;
291
+ callbacks.onToolUse?.('Edit', { changes });
270
292
  return;
271
293
  }
272
- if (itemType === 'mcp_tool_call' && type === 'item.started') {
294
+ // mcp_tool_call(旧格式)
295
+ if (itemType === 'mcp_tool_call') {
273
296
  const tool = item.tool;
274
297
  const server = item.server;
275
298
  if (tool) {
@@ -279,16 +302,41 @@ export function runCodex(cliPath, prompt, sessionId, workDir, callbacks, options
279
302
  }
280
303
  return;
281
304
  }
282
- if (itemType === 'agent_message' && type === 'item.completed') {
283
- const text = item.text;
305
+ // agent_message / message 最终回复文本
306
+ // Codex 新格式:event_msg.payload.type=agent_message, payload.message=文本
307
+ // response_item.payload.type=message, payload.content=[{type:output_text,text:...}]
308
+ if (itemType === 'agent_message' || itemType === 'message') {
309
+ let text;
310
+ if (itemType === 'agent_message') {
311
+ text = item.message ?? item.text;
312
+ }
313
+ else {
314
+ // message 类型,content 是数组
315
+ const content = item.content;
316
+ if (Array.isArray(content)) {
317
+ text = content
318
+ .filter((c) => c.type === 'output_text' && c.text)
319
+ .map((c) => c.text)
320
+ .join('\n');
321
+ }
322
+ }
284
323
  if (text) {
324
+ // 只累加 final_answer 或 commentary,避免重复
325
+ const phase = item.phase ?? payload.phase;
285
326
  accumulated += (accumulated ? '\n\n' : '') + text;
286
327
  callbacks.onText(accumulated);
287
328
  }
288
329
  return;
289
330
  }
290
331
  }
291
- if (type === 'turn.completed') {
332
+ // task_complete / turn.completed
333
+ if (type === 'task_complete' || type === 'turn.completed') {
334
+ // task_complete 里可能有 last_agent_message
335
+ const lastMsg = payload.last_agent_message;
336
+ if (lastMsg && !accumulated) {
337
+ accumulated = lastMsg;
338
+ callbacks.onText(accumulated);
339
+ }
292
340
  completed = true;
293
341
  callbacks.onComplete({
294
342
  success: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wu529778790/open-im",
3
- "version": "1.11.8-beta.24",
3
+ "version": "1.11.8-beta.25",
4
4
  "description": "Your AI coding assistant, in every chat app. Multi-platform IM bridge for Claude Code, Codex, and CodeBuddy.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",