chatccc 0.2.276 → 0.2.277

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepccc",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "description": "A lightweight coding agent with OpenAI-compatible and Anthropic Messages API support.",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -392,38 +392,35 @@ function replayStructuredAssistantMessage(message, messageIndex) {
392
392
  ];
393
393
  const messages = [];
394
394
  let assistantParts = [];
395
- let toolParts = [];
396
- const pendingCalls = new Map();
397
- const knownNames = new Map();
395
+ const batchCalls = new Map();
396
+ const batchResults = new Map();
398
397
  const emittedCallIds = new Set();
399
- const flushAssistant = () => {
400
- if (!assistantParts.length)
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
- messages.push({ role: "assistant", content: assistantParts });
403
- assistantParts = [];
404
- };
405
- const completeToolStep = () => {
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
- toolParts = [];
417
+ batchCalls.clear();
418
+ batchResults.clear();
422
419
  };
423
420
  for (const entry of timeline) {
424
421
  if (entry.type === "text") {
425
- if (pendingCalls.size > 0 || toolParts.length > 0)
426
- completeToolStep();
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
- // Consecutive tool calls belong to one assistant step. Only close the
435
- // previous step after at least one result has arrived.
436
- if (toolParts.length > 0)
437
- completeToolStep();
438
- knownNames.set(entry.id, entry.name);
439
- pendingCalls.set(entry.id, entry.name);
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 (!emittedCallIds.has(entry.tool_use_id))
447
+ if (!batchCalls.has(entry.tool_use_id))
450
448
  continue;
451
- const toolName = entry.name ?? knownNames.get(entry.tool_use_id);
449
+ const toolName = entry.name ?? batchCalls.get(entry.tool_use_id);
452
450
  if (!toolName)
453
451
  continue;
454
- flushAssistant();
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
- if (pendingCalls.size > 0 || toolParts.length > 0)
465
- completeToolStep();
466
- else
467
- flushAssistant();
460
+ completeToolBatch();
468
461
  return messages;
469
462
  }
470
463
  function serializeMessagesForCompaction(messages) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chatccc",
3
- "version": "0.2.276",
3
+ "version": "0.2.277",
4
4
  "description": "Feishu bot bridge for Claude Code",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",