coder-agent 2.3.4 → 2.3.5
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/index.js +105 -81
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -209,111 +209,135 @@ async function main() {
|
|
|
209
209
|
});
|
|
210
210
|
let inputBuffer = "";
|
|
211
211
|
let pasteTimeout = null;
|
|
212
|
+
let lineCountInBurst = 0;
|
|
212
213
|
let currentAbortController = null;
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if (
|
|
218
|
-
|
|
214
|
+
async function executeAgentChat(trimmed) {
|
|
215
|
+
// Pause standard input processing during agent thinking & updates
|
|
216
|
+
rl.pause();
|
|
217
|
+
// Built-in slash commands
|
|
218
|
+
if (trimmed === "/exit" || trimmed === "/quit") {
|
|
219
|
+
rl.close();
|
|
220
|
+
process.exit(0);
|
|
219
221
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
rl.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
console.log(chalk.hex('#30d158')('✓') + ' ' + chalk.gray('Memory cleared'));
|
|
239
|
-
rl.resume();
|
|
240
|
-
rl.prompt();
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
if (trimmed === "/status") {
|
|
244
|
-
console.log(chalk.dim(`session · ${agent.memoryStatus()}`));
|
|
245
|
-
rl.resume();
|
|
246
|
-
rl.prompt();
|
|
247
|
-
return;
|
|
222
|
+
if (trimmed === "/clear") {
|
|
223
|
+
agent.clearMemory();
|
|
224
|
+
console.log(chalk.hex('#30d158')('✓') + ' ' + chalk.gray('Memory cleared'));
|
|
225
|
+
rl.resume();
|
|
226
|
+
rl.prompt();
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if (trimmed === "/status") {
|
|
230
|
+
console.log(chalk.dim(`session · ${agent.memoryStatus()}`));
|
|
231
|
+
rl.resume();
|
|
232
|
+
rl.prompt();
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (trimmed.startsWith("/model")) {
|
|
236
|
+
const parts = trimmed.split(/\s+/);
|
|
237
|
+
if (parts.length === 1) {
|
|
238
|
+
console.log(chalk.dim(`model `) + chalk.gray(agent.getModel()));
|
|
239
|
+
console.log(chalk.gray(`options `) + chalk.gray(VALID_MODELS.join(" · ")));
|
|
248
240
|
}
|
|
249
|
-
|
|
250
|
-
const
|
|
251
|
-
if (
|
|
252
|
-
|
|
253
|
-
console.log(chalk.
|
|
241
|
+
else {
|
|
242
|
+
const newModel = parts[1];
|
|
243
|
+
if (VALID_MODELS.includes(newModel)) {
|
|
244
|
+
agent.setModel(newModel);
|
|
245
|
+
console.log(chalk.hex('#30d158')('✓') + ' ' + chalk.gray(`Switched model to: ${newModel}`));
|
|
254
246
|
}
|
|
255
247
|
else {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
agent.setModel(newModel);
|
|
259
|
-
console.log(chalk.hex('#30d158')('✓') + ' ' + chalk.gray(`Switched model to: ${newModel}`));
|
|
260
|
-
}
|
|
261
|
-
else {
|
|
262
|
-
console.log(chalk.hex('#ff453a')('✕ error'));
|
|
263
|
-
console.log(chalk.dim(` Model must be one of: ${VALID_MODELS.join(" · ")}`));
|
|
264
|
-
}
|
|
248
|
+
console.log(chalk.hex('#ff453a')('✕ error'));
|
|
249
|
+
console.log(chalk.dim(` Model must be one of: ${VALID_MODELS.join(" · ")}`));
|
|
265
250
|
}
|
|
266
|
-
rl.resume();
|
|
267
|
-
rl.prompt();
|
|
268
|
-
return;
|
|
269
251
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
252
|
+
rl.resume();
|
|
253
|
+
rl.prompt();
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (trimmed === "/help") {
|
|
257
|
+
console.log(chalk.white.bold("\n Interactive Commands:"));
|
|
258
|
+
console.log(chalk.gray(` /model [name] — View active model or switch to [name]
|
|
273
259
|
/clear — Wipe conversation memory
|
|
274
260
|
/status — Show active model and memory usage
|
|
275
261
|
/exit — Exit Coder`));
|
|
276
|
-
|
|
277
|
-
|
|
262
|
+
console.log(chalk.white.bold("\n API Keys & Configuration:"));
|
|
263
|
+
console.log(chalk.gray(` • Stored at: ~/.coder-config.json
|
|
278
264
|
• To change key: Exit and run 'coder-agent --set-key <key>'
|
|
279
265
|
• Env variable option: GEMINI_API_KEY`));
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
266
|
+
rl.resume();
|
|
267
|
+
rl.prompt();
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
currentAbortController = new AbortController();
|
|
271
|
+
try {
|
|
272
|
+
await agent.chat(trimmed, currentAbortController.signal);
|
|
273
|
+
}
|
|
274
|
+
catch (err) {
|
|
275
|
+
if (err?.name === "AbortError" || currentAbortController.signal.aborted) {
|
|
276
|
+
console.log(chalk.hex('#ff453a')('\n✕ cancelled'));
|
|
287
277
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
278
|
+
else {
|
|
279
|
+
console.log(chalk.hex('#ff453a')('✕ error'));
|
|
280
|
+
if (err?.status === 401) {
|
|
281
|
+
console.log(chalk.dim(" Invalid API key. Check your configuration."));
|
|
282
|
+
}
|
|
283
|
+
else if (err?.status === 429) {
|
|
284
|
+
console.log(chalk.dim(" Rate limit exceeded on Gemini API."));
|
|
291
285
|
}
|
|
292
286
|
else {
|
|
293
|
-
console.log(chalk.
|
|
294
|
-
if (err?.status === 401) {
|
|
295
|
-
console.log(chalk.dim(" Invalid API key. Check your configuration."));
|
|
296
|
-
}
|
|
297
|
-
else if (err?.status === 429) {
|
|
298
|
-
console.log(chalk.dim(" Rate limit exceeded on Gemini API."));
|
|
299
|
-
}
|
|
300
|
-
else {
|
|
301
|
-
console.log(chalk.dim(` ${err.message}`));
|
|
302
|
-
}
|
|
287
|
+
console.log(chalk.dim(` ${err.message}`));
|
|
303
288
|
}
|
|
304
289
|
}
|
|
305
|
-
|
|
306
|
-
|
|
290
|
+
}
|
|
291
|
+
finally {
|
|
292
|
+
currentAbortController = null;
|
|
293
|
+
}
|
|
294
|
+
rl.resume();
|
|
295
|
+
rl.prompt();
|
|
296
|
+
}
|
|
297
|
+
rl.setPrompt(chalk.hex('#0a84ff')('›') + ' ');
|
|
298
|
+
rl.prompt();
|
|
299
|
+
rl.on("line", (line) => {
|
|
300
|
+
inputBuffer += (inputBuffer ? "\n" : "") + line;
|
|
301
|
+
lineCountInBurst++;
|
|
302
|
+
if (pasteTimeout) {
|
|
303
|
+
clearTimeout(pasteTimeout);
|
|
304
|
+
}
|
|
305
|
+
pasteTimeout = setTimeout(async () => {
|
|
306
|
+
pasteTimeout = null;
|
|
307
|
+
const burstCount = lineCountInBurst;
|
|
308
|
+
lineCountInBurst = 0;
|
|
309
|
+
// Check if there is an unfinished line in the readline buffer (e.g. pasted text without trailing newline)
|
|
310
|
+
const unfinishedLine = rl.line;
|
|
311
|
+
// If we got multiple lines in this burst, or there is an unfinished line,
|
|
312
|
+
// we consider it a multi-line paste. We don't submit yet; we let the user
|
|
313
|
+
// edit the unfinished line or type more.
|
|
314
|
+
if (burstCount > 1 || unfinishedLine.trim() !== "") {
|
|
315
|
+
return;
|
|
307
316
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
317
|
+
const accumulatedInput = inputBuffer;
|
|
318
|
+
inputBuffer = "";
|
|
319
|
+
const trimmed = accumulatedInput.trim();
|
|
320
|
+
if (!trimmed) {
|
|
321
|
+
rl.prompt();
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
await executeAgentChat(trimmed);
|
|
325
|
+
}, 50);
|
|
311
326
|
});
|
|
312
327
|
// Handle Ctrl+C gracefully
|
|
313
328
|
const sigintHandler = () => {
|
|
314
329
|
if (currentAbortController) {
|
|
315
330
|
currentAbortController.abort();
|
|
316
331
|
}
|
|
332
|
+
else if (inputBuffer !== "" || rl.line !== "") {
|
|
333
|
+
inputBuffer = "";
|
|
334
|
+
lineCountInBurst = 0;
|
|
335
|
+
// Clear the current input buffer in readline
|
|
336
|
+
rl.write(null, { ctrl: true, name: 'u' });
|
|
337
|
+
console.log();
|
|
338
|
+
rl.setPrompt(chalk.hex('#0a84ff')('›') + ' ');
|
|
339
|
+
rl.prompt();
|
|
340
|
+
}
|
|
317
341
|
else {
|
|
318
342
|
rl.close();
|
|
319
343
|
process.exit(0);
|