coder-agent 2.8.2 → 2.8.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.
Files changed (2) hide show
  1. package/dist/agent.js +59 -0
  2. package/package.json +1 -1
package/dist/agent.js CHANGED
@@ -463,6 +463,50 @@ async function callGeminiAPIWithRotation(apiKey, params, maxRetries = 3, initial
463
463
  processChunk(value);
464
464
  }
465
465
  }
466
+ // Flush remaining buffer in case the final chunk didn't end with a newline
467
+ if (buffer.trim()) {
468
+ const trimmed = buffer.trim();
469
+ if (trimmed.startsWith("data: ") && trimmed !== "data: [DONE]") {
470
+ try {
471
+ const parsed = JSON.parse(trimmed.slice(6));
472
+ const choice = parsed.choices?.[0];
473
+ if (choice) {
474
+ const content = choice.delta?.content;
475
+ if (content) {
476
+ if (!silent) {
477
+ pushToTypewriter(content);
478
+ }
479
+ else {
480
+ accumulatedContent += content;
481
+ }
482
+ }
483
+ const toolCalls = choice.delta?.tool_calls;
484
+ if (toolCalls) {
485
+ for (const tc of toolCalls) {
486
+ const idx = tc.index ?? 0;
487
+ if (!accumulatedToolCalls[idx]) {
488
+ accumulatedToolCalls[idx] = {
489
+ id: tc.id || "",
490
+ type: "function",
491
+ function: { name: "", arguments: "" }
492
+ };
493
+ }
494
+ if (tc.id)
495
+ accumulatedToolCalls[idx].id = tc.id;
496
+ if (tc.function?.name) {
497
+ accumulatedToolCalls[idx].function.name += tc.function.name;
498
+ }
499
+ if (tc.function?.arguments) {
500
+ accumulatedToolCalls[idx].function.arguments += tc.function.arguments;
501
+ }
502
+ }
503
+ }
504
+ }
505
+ }
506
+ catch { }
507
+ }
508
+ buffer = "";
509
+ }
466
510
  // Wait for the typewriter to finish writing before returning
467
511
  if (typewriterActive && !silent) {
468
512
  await new Promise((resolve) => {
@@ -627,6 +671,7 @@ export class Agent {
627
671
  let iterations = 0;
628
672
  const MAX_ITERATIONS = 12;
629
673
  let waitCount = 0;
674
+ let emptyResponseRetries = 0;
630
675
  const MAX_WAITS = 3;
631
676
  const modifiedFiles = new Set();
632
677
  let cleanContent = "";
@@ -710,8 +755,22 @@ export class Agent {
710
755
  cleanContent = cleanContent.trim();
711
756
  // ── No tool calls → final answer ─────────────────────────────────────
712
757
  if (toolCalls.length === 0) {
758
+ if (cleanContent === "") {
759
+ if (emptyResponseRetries < 3) {
760
+ emptyResponseRetries++;
761
+ console.log(chalk.hex('#ff9f0a')(`\n⚠ Warning: Received empty response from API. Retrying (attempt ${emptyResponseRetries}/3)...`));
762
+ this.memory.getAll().pop(); // remove empty assistant message
763
+ continue;
764
+ }
765
+ else {
766
+ console.log(chalk.hex('#ff453a')('\n✕ error: Received consecutive empty responses from Gemini API. Exiting.'));
767
+ break;
768
+ }
769
+ }
713
770
  break;
714
771
  }
772
+ // Reset empty response retries on a successful non-empty turn
773
+ emptyResponseRetries = 0;
715
774
  // ── Phase 2: Tool Execution ───────────────────────────────────────────
716
775
  const statusLines = [];
717
776
  for (const toolCall of toolCalls) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coder-agent",
3
- "version": "2.8.2",
3
+ "version": "2.8.3",
4
4
  "description": "CLI coding agent powered by Google Gemini",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",