coder-agent 2.9.5 → 2.9.7
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 +82 -22
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -35,7 +35,12 @@ function normalizeFilePath(p) {
|
|
|
35
35
|
if (process.platform === "win32" && /^\/[a-zA-Z]:/.test(normalized)) {
|
|
36
36
|
normalized = normalized.slice(1);
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
try {
|
|
39
|
+
return path.resolve(process.cwd(), normalized);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return path.normalize(normalized);
|
|
43
|
+
}
|
|
39
44
|
}
|
|
40
45
|
function extractDiagnostics(text) {
|
|
41
46
|
const diagnostics = [];
|
|
@@ -180,38 +185,69 @@ function formatResponseText(text) {
|
|
|
180
185
|
return chalk.white(part);
|
|
181
186
|
}).join('');
|
|
182
187
|
}
|
|
183
|
-
function
|
|
184
|
-
if (!
|
|
188
|
+
function normalizeCode(code) {
|
|
189
|
+
if (!code)
|
|
185
190
|
return "";
|
|
186
|
-
return
|
|
191
|
+
return code
|
|
187
192
|
.toLowerCase()
|
|
188
|
-
.replace(/\s+/g, "
|
|
193
|
+
.replace(/\s+/g, "")
|
|
189
194
|
.trim();
|
|
190
195
|
}
|
|
191
|
-
function
|
|
196
|
+
function getLoopCheckKey(toolCalls) {
|
|
192
197
|
if (!toolCalls || toolCalls.length === 0)
|
|
193
198
|
return "";
|
|
194
|
-
|
|
199
|
+
const parts = toolCalls.map(tc => {
|
|
195
200
|
const name = tc.function?.name || "";
|
|
196
|
-
let
|
|
201
|
+
let args = {};
|
|
197
202
|
try {
|
|
198
203
|
const rawArgs = tc.function?.arguments;
|
|
199
|
-
|
|
204
|
+
args = typeof rawArgs === 'string'
|
|
200
205
|
? JSON.parse(rawArgs)
|
|
201
206
|
: rawArgs;
|
|
202
|
-
if (args && typeof args ===
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
207
|
+
if (args && typeof args === "object") {
|
|
208
|
+
if (args.filepath && !args.file_path)
|
|
209
|
+
args.file_path = args.filepath;
|
|
210
|
+
if (args.path && !args.file_path)
|
|
211
|
+
args.file_path = args.path;
|
|
212
|
+
if (args.dirpath && !args.dir_path)
|
|
213
|
+
args.dir_path = args.dirpath;
|
|
208
214
|
}
|
|
209
215
|
}
|
|
210
|
-
catch {
|
|
211
|
-
|
|
216
|
+
catch { }
|
|
217
|
+
const filePath = args.file_path || args.dir_path || "";
|
|
218
|
+
const normalizedPath = filePath ? normalizeFilePath(filePath).toLowerCase() : "";
|
|
219
|
+
switch (name) {
|
|
220
|
+
case "read_file":
|
|
221
|
+
return `read_file:${normalizedPath}`;
|
|
222
|
+
case "read_file_lines":
|
|
223
|
+
const start = args.start_line ?? "";
|
|
224
|
+
const end = args.end_line ?? "";
|
|
225
|
+
return `read_file_lines:${normalizedPath}:${start}-${end}`;
|
|
226
|
+
case "write_file":
|
|
227
|
+
return `write_file:${normalizedPath}:${normalizeCode(args.content || "")}`;
|
|
228
|
+
case "patch_file":
|
|
229
|
+
const targetCode = normalizeCode(args.target_code || "");
|
|
230
|
+
const replacementCode = normalizeCode(args.replacement_code || "");
|
|
231
|
+
return `patch_file:${normalizedPath}:${targetCode}:${replacementCode}`;
|
|
232
|
+
case "list_directory":
|
|
233
|
+
return `list_directory:${normalizedPath}`;
|
|
234
|
+
case "run_shell":
|
|
235
|
+
const cmd = (args.command || "").toLowerCase().trim().replace(/\s+/g, " ");
|
|
236
|
+
return `run_shell:${cmd}`;
|
|
237
|
+
case "web_search":
|
|
238
|
+
const qSearch = (args.query || "").toLowerCase().trim().replace(/\s+/g, " ");
|
|
239
|
+
return `web_search:${qSearch}`;
|
|
240
|
+
case "find_files":
|
|
241
|
+
const qFind = (args.query || "").toLowerCase().trim().replace(/\s+/g, " ");
|
|
242
|
+
return `find_files:${normalizedPath}:${qFind}`;
|
|
243
|
+
case "search_grep":
|
|
244
|
+
const qGrep = (args.query || "").toLowerCase().trim().replace(/\s+/g, " ");
|
|
245
|
+
return `search_grep:${qGrep}`;
|
|
246
|
+
default:
|
|
247
|
+
return `${name}:${JSON.stringify(args)}`;
|
|
212
248
|
}
|
|
213
|
-
|
|
214
|
-
|
|
249
|
+
});
|
|
250
|
+
return parts.sort().join(";");
|
|
215
251
|
}
|
|
216
252
|
function hasRepeatingCycle(history) {
|
|
217
253
|
const n = history.length;
|
|
@@ -503,10 +539,34 @@ async function callGeminiAPIWithRotation(apiKey, params, maxRetries = 3, initial
|
|
|
503
539
|
const nextModel = rotationList[modelIndex];
|
|
504
540
|
if (!silent) {
|
|
505
541
|
stopSpinner();
|
|
506
|
-
|
|
507
|
-
|
|
542
|
+
let reason = "Rate limited";
|
|
543
|
+
if (isModelError)
|
|
544
|
+
reason = "Model unavailable";
|
|
545
|
+
else if (status >= 500)
|
|
546
|
+
reason = "Server error (5xx)";
|
|
547
|
+
console.log(chalk.hex('#ff9f0a')('⚠') + ' ' + chalk.gray(`${reason} on ${currentModel}. Rotating to ${nextModel}...`));
|
|
508
548
|
startSpinner("thinking...");
|
|
509
549
|
}
|
|
550
|
+
// Delay slightly on rate limits or server errors before sending next request
|
|
551
|
+
if (status === 429 || (status >= 500 && status < 600)) {
|
|
552
|
+
try {
|
|
553
|
+
await new Promise((resolve, reject) => {
|
|
554
|
+
const timer = setTimeout(resolve, 2000);
|
|
555
|
+
if (signal) {
|
|
556
|
+
signal.addEventListener("abort", () => {
|
|
557
|
+
clearTimeout(timer);
|
|
558
|
+
const abortErr = new Error("The user aborted a request.");
|
|
559
|
+
abortErr.name = "AbortError";
|
|
560
|
+
reject(abortErr);
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
catch (err) {
|
|
566
|
+
if (err.name === "AbortError" || signal?.aborted)
|
|
567
|
+
throw err;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
510
570
|
currentModel = nextModel;
|
|
511
571
|
attempts = 0; // reset retry counter for the fresh model
|
|
512
572
|
continue;
|
|
@@ -792,7 +852,7 @@ export class Agent {
|
|
|
792
852
|
console.log(line);
|
|
793
853
|
}
|
|
794
854
|
// Loop detection & intervention
|
|
795
|
-
const currentKey =
|
|
855
|
+
const currentKey = getLoopCheckKey(toolCalls);
|
|
796
856
|
const tempHistory = [...stateHistory, currentKey];
|
|
797
857
|
if (hasRepeatingCycle(tempHistory)) {
|
|
798
858
|
loopInterventions++;
|