coder-agent 2.9.1 → 2.9.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/agent.js CHANGED
@@ -337,53 +337,6 @@ async function callGeminiAPIWithRotation(apiKey, params, maxRetries = 3, initial
337
337
  let buffer = "";
338
338
  let accumulatedContent = "";
339
339
  let accumulatedToolCalls = [];
340
- let typewriterQueue = [];
341
- let typewriterActive = false;
342
- let resolveTypewriterFinished = null;
343
- const pushToTypewriter = (text) => {
344
- typewriterQueue.push(...text.split(""));
345
- if (!typewriterActive) {
346
- typewriterActive = true;
347
- runTypewriterLoop();
348
- }
349
- };
350
- const runTypewriterLoop = async () => {
351
- while (typewriterQueue.length > 0) {
352
- const len = typewriterQueue.length;
353
- let batchSize = 1;
354
- let delay = 15; // default smooth delay
355
- if (len > 80) {
356
- batchSize = 8;
357
- delay = 1;
358
- }
359
- else if (len > 40) {
360
- batchSize = 4;
361
- delay = 2;
362
- }
363
- else if (len > 20) {
364
- batchSize = 2;
365
- delay = 5;
366
- }
367
- else if (len > 10) {
368
- batchSize = 1;
369
- delay = 8;
370
- }
371
- const chars = typewriterQueue.splice(0, batchSize).join("");
372
- accumulatedContent += chars;
373
- const maxLen = (process.stdout.columns || 80) - 20;
374
- let display = accumulatedContent.replace(/\r?\n/g, " ");
375
- if (display.length > maxLen) {
376
- display = "..." + display.slice(-maxLen + 3);
377
- }
378
- updateSpinner(chalk.dim("thinking: ") + chalk.gray(display));
379
- await new Promise((resolve) => setTimeout(resolve, delay));
380
- }
381
- typewriterActive = false;
382
- if (resolveTypewriterFinished) {
383
- resolveTypewriterFinished();
384
- resolveTypewriterFinished = null;
385
- }
386
- };
387
340
  const processChunk = (chunk) => {
388
341
  buffer += decoder.decode(chunk, { stream: true });
389
342
  const lines = buffer.split("\n");
@@ -402,11 +355,14 @@ async function callGeminiAPIWithRotation(apiKey, params, maxRetries = 3, initial
402
355
  continue;
403
356
  const content = choice.delta?.content;
404
357
  if (content) {
358
+ accumulatedContent += content;
405
359
  if (!silent) {
406
- pushToTypewriter(content);
407
- }
408
- else {
409
- accumulatedContent += content;
360
+ const maxLen = (process.stdout.columns || 80) - 20;
361
+ let display = accumulatedContent.replace(/\r?\n/g, " ");
362
+ if (display.length > maxLen) {
363
+ display = "..." + display.slice(-maxLen + 3);
364
+ }
365
+ updateSpinner(chalk.dim("thinking: ") + chalk.gray(display));
410
366
  }
411
367
  }
412
368
  const toolCalls = choice.delta?.tool_calls;
@@ -473,11 +429,14 @@ async function callGeminiAPIWithRotation(apiKey, params, maxRetries = 3, initial
473
429
  if (choice) {
474
430
  const content = choice.delta?.content;
475
431
  if (content) {
432
+ accumulatedContent += content;
476
433
  if (!silent) {
477
- pushToTypewriter(content);
478
- }
479
- else {
480
- accumulatedContent += content;
434
+ const maxLen = (process.stdout.columns || 80) - 20;
435
+ let display = accumulatedContent.replace(/\r?\n/g, " ");
436
+ if (display.length > maxLen) {
437
+ display = "..." + display.slice(-maxLen + 3);
438
+ }
439
+ updateSpinner(chalk.dim("thinking: ") + chalk.gray(display));
481
440
  }
482
441
  }
483
442
  const toolCalls = choice.delta?.tool_calls;
@@ -507,12 +466,6 @@ async function callGeminiAPIWithRotation(apiKey, params, maxRetries = 3, initial
507
466
  }
508
467
  buffer = "";
509
468
  }
510
- // Wait for the typewriter to finish writing before returning
511
- if (typewriterActive && !silent) {
512
- await new Promise((resolve) => {
513
- resolveTypewriterFinished = resolve;
514
- });
515
- }
516
469
  if (!silent) {
517
470
  stopSpinner();
518
471
  if (accumulatedToolCalls.length === 0 && accumulatedContent.trim() !== "") {
@@ -672,6 +625,7 @@ export class Agent {
672
625
  const MAX_ITERATIONS = 12;
673
626
  let waitCount = 0;
674
627
  let emptyResponseRetries = 0;
628
+ let loopInterventions = 0;
675
629
  const MAX_WAITS = 3;
676
630
  const modifiedFiles = new Set();
677
631
  let cleanContent = "";
@@ -841,6 +795,11 @@ export class Agent {
841
795
  const currentKey = `${normalizeContentForLoopCheck(msg.content || "")}|${normalizeToolCallsForLoopCheck(toolCalls)}`;
842
796
  const tempHistory = [...stateHistory, currentKey];
843
797
  if (hasRepeatingCycle(tempHistory)) {
798
+ loopInterventions++;
799
+ if (loopInterventions >= 2) {
800
+ console.log(chalk.hex('#ff453a')('\n✕ Loop intervention failed: Coder is stuck in an execution loop. Exiting to prompt.'));
801
+ break;
802
+ }
844
803
  const warningMessage = `⚠️ [LOOP DETECTED] You are repeating the exact same thoughts or tool calls. Please break out of this loop. Do not repeat the same actions. Re-evaluate your strategy, look at a different file, run a different command, or ask the user for clarification if you cannot proceed.`;
845
804
  console.log(chalk.hex('#ff9f0a')('\n⚠ Loop detected! Intervening to break the loop...'));
846
805
  this.memory.add({
@@ -851,6 +810,8 @@ export class Agent {
851
810
  }
852
811
  else {
853
812
  stateHistory.push(currentKey);
813
+ if (loopInterventions > 0)
814
+ loopInterventions = 0;
854
815
  }
855
816
  if (iterations < MAX_ITERATIONS) {
856
817
  console.log(chalk.dim('\n' + '─'.repeat(48) + '\n'));
package/dist/memory.js CHANGED
@@ -238,7 +238,8 @@ When writing code in your response, always use this block format:
238
238
  \`\`\`
239
239
 
240
240
  Guidelines & Controls:
241
- - Be concise in your explanations; let code and command output speak for itself.
241
+ - Be extremely concise in your explanations; let code and command output speak for itself.
242
+ - When you have successfully completed the user's request or achieved the goal, output an extremely brief and minimal final response (e.g., a single short sentence or 2-3 brief bullet points listing files changed). Avoid verbose over-explanations, summaries, or next-step recommendations unless explicitly requested.
242
243
  - When writing code, always use write_file then run_shell to verify it works.
243
244
  - Prefer using search_grep to locate code, read_file_lines to read relevant parts, and patch_file to make targeted edits, especially in large codebases. This prevents token/context overflow.
244
245
  - Before answering questions or checking for errors in the codebase, always inspect the workspace to identify the files and languages present. Do not guess.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coder-agent",
3
- "version": "2.9.1",
3
+ "version": "2.9.3",
4
4
  "description": "CLI coding agent powered by Google Gemini",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",