coder-agent 2.6.1 → 2.6.2

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 +100 -5
  2. package/package.json +1 -1
package/dist/agent.js CHANGED
@@ -276,6 +276,104 @@ async function callGeminiAPIWithRotation(apiKey, params, maxRetries = 3, initial
276
276
  err.status = res.status;
277
277
  throw err;
278
278
  }
279
+ if (params.stream) {
280
+ const decoder = new TextDecoder();
281
+ let buffer = "";
282
+ let accumulatedContent = "";
283
+ let accumulatedToolCalls = [];
284
+ if (!silent) {
285
+ stopSpinner();
286
+ }
287
+ const processChunk = (chunk) => {
288
+ buffer += decoder.decode(chunk, { stream: true });
289
+ const lines = buffer.split("\n");
290
+ buffer = lines.pop() || "";
291
+ for (const line of lines) {
292
+ const trimmed = line.trim();
293
+ if (!trimmed)
294
+ continue;
295
+ if (trimmed === "data: [DONE]")
296
+ break;
297
+ if (trimmed.startsWith("data: ")) {
298
+ try {
299
+ const parsed = JSON.parse(trimmed.slice(6));
300
+ const choice = parsed.choices?.[0];
301
+ if (!choice)
302
+ continue;
303
+ const content = choice.delta?.content;
304
+ if (content) {
305
+ accumulatedContent += content;
306
+ if (!silent) {
307
+ process.stdout.write(content);
308
+ }
309
+ }
310
+ const toolCalls = choice.delta?.tool_calls;
311
+ if (toolCalls) {
312
+ for (const tc of toolCalls) {
313
+ const idx = tc.index ?? 0;
314
+ if (!accumulatedToolCalls[idx]) {
315
+ accumulatedToolCalls[idx] = {
316
+ id: tc.id || "",
317
+ type: "function",
318
+ function: { name: "", arguments: "" }
319
+ };
320
+ }
321
+ if (tc.id)
322
+ accumulatedToolCalls[idx].id = tc.id;
323
+ if (tc.function?.name) {
324
+ accumulatedToolCalls[idx].function.name += tc.function.name;
325
+ }
326
+ if (tc.function?.arguments) {
327
+ accumulatedToolCalls[idx].function.arguments += tc.function.arguments;
328
+ }
329
+ }
330
+ }
331
+ }
332
+ catch (e) {
333
+ // Ignore partial JSON parse errors
334
+ }
335
+ }
336
+ }
337
+ };
338
+ const bodyStream = res.body;
339
+ if (bodyStream && typeof bodyStream[Symbol.asyncIterator] === "function") {
340
+ for await (const chunk of bodyStream) {
341
+ if (signal?.aborted) {
342
+ const abortErr = new Error("The user aborted a request.");
343
+ abortErr.name = "AbortError";
344
+ throw abortErr;
345
+ }
346
+ processChunk(chunk);
347
+ }
348
+ }
349
+ else if (bodyStream && typeof bodyStream.getReader === "function") {
350
+ const reader = bodyStream.getReader();
351
+ while (true) {
352
+ if (signal?.aborted) {
353
+ const abortErr = new Error("The user aborted a request.");
354
+ abortErr.name = "AbortError";
355
+ throw abortErr;
356
+ }
357
+ const { done, value } = await reader.read();
358
+ if (done)
359
+ break;
360
+ if (value)
361
+ processChunk(value);
362
+ }
363
+ }
364
+ const finalResponse = {
365
+ choices: [
366
+ {
367
+ message: {
368
+ role: "assistant",
369
+ content: accumulatedContent,
370
+ tool_calls: accumulatedToolCalls.length > 0 ? accumulatedToolCalls.filter(Boolean) : undefined
371
+ }
372
+ }
373
+ ]
374
+ };
375
+ return { data: finalResponse, modelUsed: currentModel };
376
+ }
279
377
  const data = await res.json();
280
378
  return { data, modelUsed: currentModel };
281
379
  }
@@ -451,6 +549,7 @@ export class Agent {
451
549
  tools: TOOL_DEFINITIONS,
452
550
  tool_choice: "auto",
453
551
  temperature: 0.2,
552
+ stream: true,
454
553
  }, 3, 1500, signal);
455
554
  stopSpinner();
456
555
  if (signal?.aborted) {
@@ -560,11 +659,7 @@ export class Agent {
560
659
  console.log(chalk.dim('─') + ' ' + chalk.dim(`${modifiedFiles.size} file(s) modified`));
561
660
  }
562
661
  // ── Phase 3: Final Agent Response ───────────────────────────────────────
563
- console.log(chalk.dim('\n' + '─'.repeat(48) + '\n'));
564
- if (cleanContent) {
565
- console.log(formatResponseText(cleanContent));
566
- console.log(""); // one trailing blank line
567
- }
662
+ // Content has already been streamed in real-time.
568
663
  if (iterations >= MAX_ITERATIONS) {
569
664
  console.log(chalk.hex('#ff453a')('✕ error'));
570
665
  console.log(chalk.dim(' Max tool iterations reached.'));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coder-agent",
3
- "version": "2.6.1",
3
+ "version": "2.6.2",
4
4
  "description": "CLI coding agent powered by Google Gemini",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",