@corbat-tech/coco 2.28.2 → 2.28.3

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/dist/cli/index.js CHANGED
@@ -53353,28 +53353,80 @@ ${tail}`;
53353
53353
  }
53354
53354
  function shouldRecoverNoToolTurn(stopReason, content) {
53355
53355
  const trimmed = content.trim();
53356
+ if (trimmed.length === 0) {
53357
+ return {
53358
+ recover: true,
53359
+ reason: "The previous response produced no usable output. Continue the task immediately or explain the blocker in one concise sentence.",
53360
+ category: "empty"
53361
+ };
53362
+ }
53356
53363
  if (stopReason === "tool_use") {
53357
53364
  return {
53358
53365
  recover: true,
53359
- reason: "The previous response indicated tool use, but no tool calls were received. Re-emit the tool call(s) now."
53366
+ reason: "The previous response indicated tool use, but no tool calls were received. Re-emit the tool call(s) now.",
53367
+ category: "tool_use"
53360
53368
  };
53361
53369
  }
53362
53370
  if (stopReason === "max_tokens" && trimmed.length === 0) {
53363
53371
  return {
53364
53372
  recover: true,
53365
- reason: "The previous response was cut off before producing any usable output. Continue immediately."
53373
+ reason: "The previous response was cut off before producing any usable output. Continue immediately.",
53374
+ category: "empty"
53366
53375
  };
53367
53376
  }
53368
- const planningOnly = trimmed.length > 0 && trimmed.length < 320 && /^(voy a|ahora voy|i('| )?ll|i will|let me|starting|preparing|activating|continuo|contin[uú]o|de acuerdo[, ]+voy)\b/i.test(
53377
+ const planningOnly = trimmed.length > 0 && trimmed.length < 320 && /^(voy a|ahora voy|voy a revisar|voy a comprobar|voy a mirar|déjame|dejame|a continuación|i('| )?ll|i will|let me|starting|preparing|activating|checking|reviewing|looking into|working on|continuo|contin[uú]o|de acuerdo[, ]+voy)\b/i.test(
53369
53378
  trimmed
53370
53379
  );
53371
53380
  if (planningOnly) {
53372
53381
  return {
53373
53382
  recover: true,
53374
- reason: "Do not only describe the next step. Execute it now with concrete tool calls."
53383
+ reason: "Do not only describe the next step. Execute it now with concrete tool calls.",
53384
+ category: "planning_only"
53375
53385
  };
53376
53386
  }
53377
- return { recover: false, reason: "" };
53387
+ return { recover: false, reason: "", category: "none" };
53388
+ }
53389
+ async function requestNoToolFallbackExplanation(priorContent, reason) {
53390
+ let explanation = "";
53391
+ let explanationThinkingEnded = false;
53392
+ options.onThinkingStart?.();
53393
+ try {
53394
+ const finalMessages = [
53395
+ ...getConversationContext(session, toolRegistry),
53396
+ {
53397
+ role: "assistant",
53398
+ content: priorContent || "[No output returned in previous step.]"
53399
+ },
53400
+ {
53401
+ role: "user",
53402
+ content: `[System: ${reason} Do not call tools. Either explain the exact blocker and ask the user for the smallest missing input, or, if the task is already complete, summarize it briefly. Do not return an empty response.]`
53403
+ }
53404
+ ];
53405
+ for await (const chunk of provider.streamWithTools(finalMessages, {
53406
+ tools: [],
53407
+ maxTokens: session.config.provider.maxTokens,
53408
+ signal: options.signal
53409
+ })) {
53410
+ if (options.signal?.aborted) break;
53411
+ if (chunk.type === "text" && chunk.text) {
53412
+ if (!explanationThinkingEnded) {
53413
+ options.onThinkingEnd?.();
53414
+ explanationThinkingEnded = true;
53415
+ }
53416
+ explanation += chunk.text;
53417
+ options.onStream?.(chunk);
53418
+ }
53419
+ if (chunk.type === "done") break;
53420
+ }
53421
+ } catch {
53422
+ } finally {
53423
+ if (!explanationThinkingEnded) options.onThinkingEnd?.();
53424
+ }
53425
+ const trimmed = explanation.trim();
53426
+ if (trimmed.length > 0) {
53427
+ return explanation;
53428
+ }
53429
+ return "I could not continue because the model stopped returning actionable output. Please retry, switch provider/model, or tell me the exact next step you want me to take.";
53378
53430
  }
53379
53431
  function shouldAutoExtendIterationBudget(latestExecuted, latestToolResults, isInErrorLoop) {
53380
53432
  if (isInErrorLoop) return false;
@@ -53544,6 +53596,15 @@ ${tail}`;
53544
53596
  });
53545
53597
  continue;
53546
53598
  }
53599
+ if (noToolRecovery.recover) {
53600
+ noToolRecoveryAttempts = 0;
53601
+ finalContent += await requestNoToolFallbackExplanation(
53602
+ responseContent,
53603
+ noToolRecovery.reason
53604
+ );
53605
+ addMessage(session, { role: "assistant", content: finalContent });
53606
+ break;
53607
+ }
53547
53608
  noToolRecoveryAttempts = 0;
53548
53609
  addMessage(session, { role: "assistant", content: responseContent });
53549
53610
  break;