chatccc 0.2.276 → 0.2.278
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.
|
@@ -392,38 +392,35 @@ function replayStructuredAssistantMessage(message, messageIndex) {
|
|
|
392
392
|
];
|
|
393
393
|
const messages = [];
|
|
394
394
|
let assistantParts = [];
|
|
395
|
-
|
|
396
|
-
const
|
|
397
|
-
const knownNames = new Map();
|
|
395
|
+
const batchCalls = new Map();
|
|
396
|
+
const batchResults = new Map();
|
|
398
397
|
const emittedCallIds = new Set();
|
|
399
|
-
const
|
|
400
|
-
if (
|
|
398
|
+
const completeToolBatch = () => {
|
|
399
|
+
if (assistantParts.length > 0) {
|
|
400
|
+
messages.push({ role: "assistant", content: assistantParts });
|
|
401
|
+
assistantParts = [];
|
|
402
|
+
}
|
|
403
|
+
if (batchCalls.size === 0) {
|
|
404
|
+
batchResults.clear();
|
|
401
405
|
return;
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
// OpenAI/LiteLLM requires every tool message to immediately follow the
|
|
407
|
-
// assistant message that declared all matching tool_calls for that step.
|
|
408
|
-
flushAssistant();
|
|
409
|
-
for (const [toolCallId, toolName] of pendingCalls) {
|
|
410
|
-
toolParts.push({
|
|
406
|
+
}
|
|
407
|
+
const toolParts = [];
|
|
408
|
+
for (const [toolCallId, toolName] of batchCalls) {
|
|
409
|
+
toolParts.push(batchResults.get(toolCallId) ?? {
|
|
411
410
|
type: "tool-result",
|
|
412
411
|
toolCallId,
|
|
413
412
|
toolName,
|
|
414
413
|
output: { type: "text", value: "[tool execution interrupted; result unavailable]" },
|
|
415
414
|
});
|
|
416
415
|
}
|
|
417
|
-
pendingCalls.clear();
|
|
418
|
-
if (!toolParts.length)
|
|
419
|
-
return;
|
|
420
416
|
messages.push({ role: "tool", content: toolParts });
|
|
421
|
-
|
|
417
|
+
batchCalls.clear();
|
|
418
|
+
batchResults.clear();
|
|
422
419
|
};
|
|
423
420
|
for (const entry of timeline) {
|
|
424
421
|
if (entry.type === "text") {
|
|
425
|
-
if (
|
|
426
|
-
|
|
422
|
+
if (batchCalls.size > 0 || batchResults.size > 0)
|
|
423
|
+
completeToolBatch();
|
|
427
424
|
const previous = assistantParts[assistantParts.length - 1];
|
|
428
425
|
if (previous?.type === "text")
|
|
429
426
|
previous.text += entry.text;
|
|
@@ -431,12 +428,13 @@ function replayStructuredAssistantMessage(message, messageIndex) {
|
|
|
431
428
|
assistantParts.push({ type: "text", text: entry.text });
|
|
432
429
|
}
|
|
433
430
|
else if (entry.type === "tool_use") {
|
|
434
|
-
//
|
|
435
|
-
//
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
431
|
+
// Providers may interleave parallel tool results with later tool-call
|
|
432
|
+
// events from the same assistant step. Keep the whole contiguous tool
|
|
433
|
+
// segment together until text resumes; closing on the first result can
|
|
434
|
+
// emit a later real result as an orphaned `role: tool` message.
|
|
435
|
+
if (emittedCallIds.has(entry.id))
|
|
436
|
+
continue;
|
|
437
|
+
batchCalls.set(entry.id, entry.name);
|
|
440
438
|
emittedCallIds.add(entry.id);
|
|
441
439
|
assistantParts.push({
|
|
442
440
|
type: "tool-call",
|
|
@@ -446,14 +444,12 @@ function replayStructuredAssistantMessage(message, messageIndex) {
|
|
|
446
444
|
});
|
|
447
445
|
}
|
|
448
446
|
else {
|
|
449
|
-
if (!
|
|
447
|
+
if (!batchCalls.has(entry.tool_use_id))
|
|
450
448
|
continue;
|
|
451
|
-
const toolName = entry.name ??
|
|
449
|
+
const toolName = entry.name ?? batchCalls.get(entry.tool_use_id);
|
|
452
450
|
if (!toolName)
|
|
453
451
|
continue;
|
|
454
|
-
|
|
455
|
-
pendingCalls.delete(entry.tool_use_id);
|
|
456
|
-
toolParts.push({
|
|
452
|
+
batchResults.set(entry.tool_use_id, {
|
|
457
453
|
type: "tool-result",
|
|
458
454
|
toolCallId: entry.tool_use_id,
|
|
459
455
|
toolName,
|
|
@@ -461,10 +457,7 @@ function replayStructuredAssistantMessage(message, messageIndex) {
|
|
|
461
457
|
});
|
|
462
458
|
}
|
|
463
459
|
}
|
|
464
|
-
|
|
465
|
-
completeToolStep();
|
|
466
|
-
else
|
|
467
|
-
flushAssistant();
|
|
460
|
+
completeToolBatch();
|
|
468
461
|
return messages;
|
|
469
462
|
}
|
|
470
463
|
function serializeMessagesForCompaction(messages) {
|
|
@@ -71,6 +71,13 @@ function resolveCodexEffort() {
|
|
|
71
71
|
// normalizeCodexMessage — Codex 事件 → UnifiedStreamMessage | null
|
|
72
72
|
// ---------------------------------------------------------------------------
|
|
73
73
|
export function normalizeCodexMessage(msg) {
|
|
74
|
+
if (msg.type === "error" && msg.message?.trim()) {
|
|
75
|
+
throw new Error(`Codex turn failed: ${msg.message.trim()}`);
|
|
76
|
+
}
|
|
77
|
+
if (msg.type === "turn.failed") {
|
|
78
|
+
const detail = typeof msg.error === "string" ? msg.error : msg.error?.message;
|
|
79
|
+
throw new Error(`Codex turn failed: ${detail?.trim() || "unknown Codex error"}`);
|
|
80
|
+
}
|
|
74
81
|
// agent_message 只是 Codex 的一条阶段性文本 item。即使内容看起来像完整答复,
|
|
75
82
|
// 后面仍可能继续发出工具调用,因此不能用它关闭 response-stall watchdog。
|
|
76
83
|
if (msg.type === "item.completed" &&
|