@corbat-tech/coco 1.1.0 → 1.2.0
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/README.md +159 -173
- package/dist/cli/index.js +147 -42
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +94 -26
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/cli/index.js
CHANGED
|
@@ -724,9 +724,6 @@ var QualityConfigSchema = z.object({
|
|
|
724
724
|
}).refine((data) => data.minIterations <= data.maxIterations, {
|
|
725
725
|
message: "minIterations must be <= maxIterations",
|
|
726
726
|
path: ["minIterations"]
|
|
727
|
-
}).refine((data) => data.convergenceThreshold < data.minScore, {
|
|
728
|
-
message: "convergenceThreshold must be < minScore",
|
|
729
|
-
path: ["convergenceThreshold"]
|
|
730
727
|
});
|
|
731
728
|
var PersistenceConfigSchema = z.object({
|
|
732
729
|
checkpointInterval: z.number().min(6e4).default(3e5),
|
|
@@ -1072,7 +1069,17 @@ function deepMergeConfig(base, override) {
|
|
|
1072
1069
|
project: { ...base.project, ...override.project },
|
|
1073
1070
|
provider: { ...base.provider, ...override.provider },
|
|
1074
1071
|
quality: { ...base.quality, ...override.quality },
|
|
1075
|
-
persistence: { ...base.persistence, ...override.persistence }
|
|
1072
|
+
persistence: { ...base.persistence, ...override.persistence },
|
|
1073
|
+
// Merge optional sections only if present in either base or override
|
|
1074
|
+
...base.stack || override.stack ? { stack: { ...base.stack, ...override.stack } } : {},
|
|
1075
|
+
...base.integrations || override.integrations ? {
|
|
1076
|
+
integrations: {
|
|
1077
|
+
...base.integrations,
|
|
1078
|
+
...override.integrations
|
|
1079
|
+
}
|
|
1080
|
+
} : {},
|
|
1081
|
+
...base.mcp || override.mcp ? { mcp: { ...base.mcp, ...override.mcp } } : {},
|
|
1082
|
+
...base.tools || override.tools ? { tools: { ...base.tools, ...override.tools } } : {}
|
|
1076
1083
|
};
|
|
1077
1084
|
}
|
|
1078
1085
|
function getProjectConfigPath() {
|
|
@@ -4778,6 +4785,9 @@ var AnthropicProvider = class {
|
|
|
4778
4785
|
try {
|
|
4779
4786
|
currentToolCall.input = currentToolInputJson ? JSON.parse(currentToolInputJson) : {};
|
|
4780
4787
|
} catch {
|
|
4788
|
+
console.warn(
|
|
4789
|
+
`[Anthropic] Failed to parse tool call arguments: ${currentToolInputJson?.slice(0, 100)}`
|
|
4790
|
+
);
|
|
4781
4791
|
currentToolCall.input = {};
|
|
4782
4792
|
}
|
|
4783
4793
|
yield {
|
|
@@ -5310,6 +5320,9 @@ var OpenAIProvider = class {
|
|
|
5310
5320
|
try {
|
|
5311
5321
|
input = builder.arguments ? JSON.parse(builder.arguments) : {};
|
|
5312
5322
|
} catch {
|
|
5323
|
+
console.warn(
|
|
5324
|
+
`[OpenAI] Failed to parse tool call arguments: ${builder.arguments?.slice(0, 100)}`
|
|
5325
|
+
);
|
|
5313
5326
|
}
|
|
5314
5327
|
yield {
|
|
5315
5328
|
type: "tool_use_end",
|
|
@@ -5598,7 +5611,16 @@ var OpenAIProvider = class {
|
|
|
5598
5611
|
).map((tc) => ({
|
|
5599
5612
|
id: tc.id,
|
|
5600
5613
|
name: tc.function.name,
|
|
5601
|
-
input:
|
|
5614
|
+
input: (() => {
|
|
5615
|
+
try {
|
|
5616
|
+
return JSON.parse(tc.function.arguments || "{}");
|
|
5617
|
+
} catch {
|
|
5618
|
+
console.warn(
|
|
5619
|
+
`[OpenAI] Failed to parse tool call arguments: ${tc.function.arguments?.slice(0, 100)}`
|
|
5620
|
+
);
|
|
5621
|
+
return {};
|
|
5622
|
+
}
|
|
5623
|
+
})()
|
|
5602
5624
|
}));
|
|
5603
5625
|
}
|
|
5604
5626
|
/**
|
|
@@ -7246,7 +7268,10 @@ var GeminiProvider = class {
|
|
|
7246
7268
|
for (const part of candidate.content.parts) {
|
|
7247
7269
|
if ("functionCall" in part && part.functionCall) {
|
|
7248
7270
|
const funcCall = part.functionCall;
|
|
7249
|
-
const
|
|
7271
|
+
const sortedArgs = funcCall.args ? Object.keys(funcCall.args).sort().map(
|
|
7272
|
+
(k) => `${k}:${JSON.stringify(funcCall.args[k])}`
|
|
7273
|
+
).join(",") : "";
|
|
7274
|
+
const callKey = `${funcCall.name}-${sortedArgs}`;
|
|
7250
7275
|
if (!emittedToolCalls.has(callKey)) {
|
|
7251
7276
|
emittedToolCalls.add(callKey);
|
|
7252
7277
|
const toolCall = {
|
|
@@ -7278,9 +7303,18 @@ var GeminiProvider = class {
|
|
|
7278
7303
|
}
|
|
7279
7304
|
/**
|
|
7280
7305
|
* Count tokens (approximate)
|
|
7306
|
+
*
|
|
7307
|
+
* Gemini uses a SentencePiece tokenizer. The average ratio varies:
|
|
7308
|
+
* - English text: ~4 characters per token
|
|
7309
|
+
* - Code: ~3.2 characters per token
|
|
7310
|
+
* - Mixed content: ~3.5 characters per token
|
|
7311
|
+
*
|
|
7312
|
+
* Using 3.5 as the default provides a better estimate for typical
|
|
7313
|
+
* coding agent workloads which mix code and natural language.
|
|
7281
7314
|
*/
|
|
7282
7315
|
countTokens(text9) {
|
|
7283
|
-
|
|
7316
|
+
if (!text9) return 0;
|
|
7317
|
+
return Math.ceil(text9.length / 3.5);
|
|
7284
7318
|
}
|
|
7285
7319
|
/**
|
|
7286
7320
|
* Get context window size
|
|
@@ -9658,7 +9692,9 @@ async function saveTrustSettings(settings) {
|
|
|
9658
9692
|
await fs22__default.mkdir(TRUST_SETTINGS_DIR, { recursive: true });
|
|
9659
9693
|
settings.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
9660
9694
|
await fs22__default.writeFile(TRUST_SETTINGS_FILE, JSON.stringify(settings, null, 2), "utf-8");
|
|
9661
|
-
} catch {
|
|
9695
|
+
} catch (error) {
|
|
9696
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
9697
|
+
console.warn(`[Trust] Failed to save trust settings: ${msg}`);
|
|
9662
9698
|
}
|
|
9663
9699
|
}
|
|
9664
9700
|
async function loadTrustedTools(projectPath) {
|
|
@@ -14369,7 +14405,11 @@ function flushLineBuffer() {
|
|
|
14369
14405
|
}
|
|
14370
14406
|
if (inCodeBlock && codeBlockLines.length > 0) {
|
|
14371
14407
|
stopStreamingIndicator();
|
|
14372
|
-
|
|
14408
|
+
try {
|
|
14409
|
+
renderCodeBlock(codeBlockLang, codeBlockLines);
|
|
14410
|
+
} finally {
|
|
14411
|
+
stopStreamingIndicator();
|
|
14412
|
+
}
|
|
14373
14413
|
inCodeBlock = false;
|
|
14374
14414
|
codeBlockLang = "";
|
|
14375
14415
|
codeBlockLines = [];
|
|
@@ -14725,6 +14765,7 @@ function formatInlineMarkdown(text9) {
|
|
|
14725
14765
|
return text9;
|
|
14726
14766
|
}
|
|
14727
14767
|
function wrapText(text9, maxWidth) {
|
|
14768
|
+
if (maxWidth <= 0) return [text9];
|
|
14728
14769
|
const plainText = stripAnsi(text9);
|
|
14729
14770
|
if (plainText.length <= maxWidth) {
|
|
14730
14771
|
return [text9];
|
|
@@ -14732,14 +14773,37 @@ function wrapText(text9, maxWidth) {
|
|
|
14732
14773
|
const lines = [];
|
|
14733
14774
|
let remaining = text9;
|
|
14734
14775
|
while (stripAnsi(remaining).length > maxWidth) {
|
|
14735
|
-
let breakPoint = maxWidth;
|
|
14736
14776
|
const plain = stripAnsi(remaining);
|
|
14777
|
+
let breakPoint = maxWidth;
|
|
14737
14778
|
const lastSpace = plain.lastIndexOf(" ", maxWidth);
|
|
14738
14779
|
if (lastSpace > maxWidth * 0.5) {
|
|
14739
14780
|
breakPoint = lastSpace;
|
|
14740
14781
|
}
|
|
14741
|
-
|
|
14742
|
-
|
|
14782
|
+
const ansiRegex = /\x1b\[[0-9;]*m/g;
|
|
14783
|
+
let match;
|
|
14784
|
+
const ansiPositions = [];
|
|
14785
|
+
ansiRegex.lastIndex = 0;
|
|
14786
|
+
while ((match = ansiRegex.exec(remaining)) !== null) {
|
|
14787
|
+
ansiPositions.push({ start: match.index, end: match.index + match[0].length });
|
|
14788
|
+
}
|
|
14789
|
+
let rawPos = 0;
|
|
14790
|
+
let visualPos = 0;
|
|
14791
|
+
let ansiIdx = 0;
|
|
14792
|
+
while (visualPos < breakPoint && rawPos < remaining.length) {
|
|
14793
|
+
while (ansiIdx < ansiPositions.length && ansiPositions[ansiIdx].start === rawPos) {
|
|
14794
|
+
rawPos = ansiPositions[ansiIdx].end;
|
|
14795
|
+
ansiIdx++;
|
|
14796
|
+
}
|
|
14797
|
+
if (rawPos >= remaining.length) break;
|
|
14798
|
+
rawPos++;
|
|
14799
|
+
visualPos++;
|
|
14800
|
+
}
|
|
14801
|
+
while (ansiIdx < ansiPositions.length && ansiPositions[ansiIdx].start === rawPos) {
|
|
14802
|
+
rawPos = ansiPositions[ansiIdx].end;
|
|
14803
|
+
ansiIdx++;
|
|
14804
|
+
}
|
|
14805
|
+
lines.push(remaining.slice(0, rawPos));
|
|
14806
|
+
remaining = remaining.slice(rawPos).trimStart();
|
|
14743
14807
|
}
|
|
14744
14808
|
if (remaining) {
|
|
14745
14809
|
lines.push(remaining);
|
|
@@ -16188,6 +16252,8 @@ function createInputHandler(_session) {
|
|
|
16188
16252
|
let historyIndex = -1;
|
|
16189
16253
|
let tempLine = "";
|
|
16190
16254
|
let lastMenuLines = 0;
|
|
16255
|
+
let lastCursorRow = 0;
|
|
16256
|
+
let isFirstRender = true;
|
|
16191
16257
|
let isPasting = false;
|
|
16192
16258
|
let pasteBuffer = "";
|
|
16193
16259
|
let isReadingClipboard = false;
|
|
@@ -16219,11 +16285,13 @@ function createInputHandler(_session) {
|
|
|
16219
16285
|
function render() {
|
|
16220
16286
|
const termCols = process.stdout.columns || 80;
|
|
16221
16287
|
const prompt = getPrompt();
|
|
16222
|
-
|
|
16223
|
-
|
|
16224
|
-
|
|
16225
|
-
|
|
16288
|
+
if (!isFirstRender) {
|
|
16289
|
+
const linesToGoUp = lastCursorRow + 1;
|
|
16290
|
+
if (linesToGoUp > 0) {
|
|
16291
|
+
process.stdout.write(ansiEscapes3.cursorUp(linesToGoUp));
|
|
16292
|
+
}
|
|
16226
16293
|
}
|
|
16294
|
+
isFirstRender = false;
|
|
16227
16295
|
process.stdout.write("\r" + ansiEscapes3.eraseDown);
|
|
16228
16296
|
const separator = chalk12.dim("\u2500".repeat(termCols));
|
|
16229
16297
|
let output = separator + "\n";
|
|
@@ -16299,6 +16367,7 @@ function createInputHandler(_session) {
|
|
|
16299
16367
|
if (finalCol > 0) {
|
|
16300
16368
|
output += ansiEscapes3.cursorForward(finalCol);
|
|
16301
16369
|
}
|
|
16370
|
+
lastCursorRow = finalLine;
|
|
16302
16371
|
process.stdout.write(output);
|
|
16303
16372
|
}
|
|
16304
16373
|
function clearMenu() {
|
|
@@ -16325,15 +16394,20 @@ function createInputHandler(_session) {
|
|
|
16325
16394
|
historyIndex = -1;
|
|
16326
16395
|
tempLine = "";
|
|
16327
16396
|
lastMenuLines = 0;
|
|
16397
|
+
lastCursorRow = 0;
|
|
16398
|
+
isFirstRender = true;
|
|
16328
16399
|
render();
|
|
16329
16400
|
if (process.stdin.isTTY) {
|
|
16330
16401
|
process.stdin.setRawMode(true);
|
|
16331
16402
|
}
|
|
16332
16403
|
process.stdin.resume();
|
|
16333
16404
|
process.stdout.write("\x1B[?2004h");
|
|
16405
|
+
const onResize = () => render();
|
|
16406
|
+
process.stdout.on("resize", onResize);
|
|
16334
16407
|
const cleanup = () => {
|
|
16335
16408
|
process.stdout.write("\x1B[?2004l");
|
|
16336
16409
|
process.stdin.removeListener("data", onData);
|
|
16410
|
+
process.stdout.removeListener("resize", onResize);
|
|
16337
16411
|
if (process.stdin.isTTY) {
|
|
16338
16412
|
process.stdin.setRawMode(false);
|
|
16339
16413
|
}
|
|
@@ -17504,7 +17578,8 @@ async function promptEditCommand(originalCommand) {
|
|
|
17504
17578
|
console.log();
|
|
17505
17579
|
console.log(chalk12.dim(" Edit command (or press Enter to cancel):"));
|
|
17506
17580
|
console.log(chalk12.cyan(` Current: ${originalCommand}`));
|
|
17507
|
-
|
|
17581
|
+
const wasRaw = process.stdin.isTTY ? process.stdin.isRaw : false;
|
|
17582
|
+
if (process.stdin.isTTY && wasRaw) {
|
|
17508
17583
|
process.stdin.setRawMode(false);
|
|
17509
17584
|
}
|
|
17510
17585
|
const rl = readline2.createInterface({
|
|
@@ -17517,6 +17592,9 @@ async function promptEditCommand(originalCommand) {
|
|
|
17517
17592
|
return trimmed || null;
|
|
17518
17593
|
} finally {
|
|
17519
17594
|
rl.close();
|
|
17595
|
+
if (process.stdin.isTTY && wasRaw) {
|
|
17596
|
+
process.stdin.setRawMode(true);
|
|
17597
|
+
}
|
|
17520
17598
|
}
|
|
17521
17599
|
}
|
|
17522
17600
|
async function confirmToolExecution(toolCall) {
|
|
@@ -22452,17 +22530,17 @@ var QualityEvaluator = class {
|
|
|
22452
22530
|
maintainabilityResult
|
|
22453
22531
|
] = await Promise.all([
|
|
22454
22532
|
this.coverageAnalyzer.analyze().catch(() => null),
|
|
22455
|
-
this.securityScanner.scan(fileContents),
|
|
22456
|
-
this.complexityAnalyzer.analyze(targetFiles),
|
|
22457
|
-
this.duplicationAnalyzer.analyze(targetFiles),
|
|
22533
|
+
this.securityScanner.scan(fileContents).catch(() => ({ score: 0, vulnerabilities: [] })),
|
|
22534
|
+
this.complexityAnalyzer.analyze(targetFiles).catch(() => ({ score: 0, files: [] })),
|
|
22535
|
+
this.duplicationAnalyzer.analyze(targetFiles).catch(() => ({ score: 0, percentage: 0 })),
|
|
22458
22536
|
this.correctnessAnalyzer.analyze().catch(() => ({ score: 0 })),
|
|
22459
22537
|
this.completenessAnalyzer.analyze(targetFiles).catch(() => ({ score: 0 })),
|
|
22460
22538
|
this.robustnessAnalyzer.analyze(targetFiles).catch(() => ({ score: 0 })),
|
|
22461
22539
|
this.testQualityAnalyzer.analyze().catch(() => ({ score: 0 })),
|
|
22462
22540
|
this.documentationAnalyzer.analyze(targetFiles).catch(() => ({ score: 0 })),
|
|
22463
|
-
this.styleAnalyzer.analyze().catch(() => ({ score:
|
|
22464
|
-
this.readabilityAnalyzer.analyze(targetFiles).catch(() => ({ score:
|
|
22465
|
-
this.maintainabilityAnalyzer.analyze(targetFiles).catch(() => ({ score:
|
|
22541
|
+
this.styleAnalyzer.analyze().catch(() => ({ score: 0 })),
|
|
22542
|
+
this.readabilityAnalyzer.analyze(targetFiles).catch(() => ({ score: 0 })),
|
|
22543
|
+
this.maintainabilityAnalyzer.analyze(targetFiles).catch(() => ({ score: 0 }))
|
|
22466
22544
|
]);
|
|
22467
22545
|
const dimensions = {
|
|
22468
22546
|
testCoverage: coverageResult?.lines.percentage ?? 0,
|
|
@@ -22976,7 +23054,17 @@ Examples:
|
|
|
22976
23054
|
regexPattern = `\\b${pattern}\\b`;
|
|
22977
23055
|
}
|
|
22978
23056
|
const flags = caseSensitive ? "g" : "gi";
|
|
22979
|
-
|
|
23057
|
+
let regex;
|
|
23058
|
+
try {
|
|
23059
|
+
regex = new RegExp(regexPattern, flags);
|
|
23060
|
+
} catch {
|
|
23061
|
+
throw new ToolError(`Invalid regex pattern: ${pattern}`, { tool: "grep" });
|
|
23062
|
+
}
|
|
23063
|
+
if (/(\.\*|\.\+|\[.*\][*+])\s*(\.\*|\.\+|\[.*\][*+])/.test(regexPattern)) {
|
|
23064
|
+
throw new ToolError(`Regex pattern rejected: nested quantifiers may cause slow matching`, {
|
|
23065
|
+
tool: "grep"
|
|
23066
|
+
});
|
|
23067
|
+
}
|
|
22980
23068
|
const stats = await fs22__default.stat(targetPath);
|
|
22981
23069
|
let filesToSearch;
|
|
22982
23070
|
if (stats.isFile()) {
|
|
@@ -24114,9 +24202,11 @@ function parseDiff(raw) {
|
|
|
24114
24202
|
function parseFileBlock(lines, start) {
|
|
24115
24203
|
const diffLine = lines[start];
|
|
24116
24204
|
let i = start + 1;
|
|
24117
|
-
const
|
|
24118
|
-
const
|
|
24119
|
-
const
|
|
24205
|
+
const gitPrefix = "diff --git a/";
|
|
24206
|
+
const pathPart = diffLine.slice(gitPrefix.length);
|
|
24207
|
+
const lastBSlash = pathPart.lastIndexOf(" b/");
|
|
24208
|
+
const oldPath = lastBSlash >= 0 ? pathPart.slice(0, lastBSlash) : pathPart;
|
|
24209
|
+
const newPath = lastBSlash >= 0 ? pathPart.slice(lastBSlash + 3) : oldPath;
|
|
24120
24210
|
let fileType = "modified";
|
|
24121
24211
|
while (i < lines.length && !lines[i].startsWith("diff --git ")) {
|
|
24122
24212
|
const current = lines[i];
|
|
@@ -24262,7 +24352,7 @@ function renderDiff(diff, options) {
|
|
|
24262
24352
|
function renderFileBlock(file, opts) {
|
|
24263
24353
|
const { maxWidth, showLineNumbers, compact } = opts;
|
|
24264
24354
|
const lang = detectLanguage(file.path);
|
|
24265
|
-
const contentWidth = maxWidth - 4;
|
|
24355
|
+
const contentWidth = Math.max(1, maxWidth - 4);
|
|
24266
24356
|
const typeLabel = file.type === "modified" ? "modified" : file.type === "added" ? "new file" : file.type === "deleted" ? "deleted" : `renamed from ${file.oldPath}`;
|
|
24267
24357
|
const statsLabel = ` +${file.additions} -${file.deletions}`;
|
|
24268
24358
|
const title = ` ${file.path} (${typeLabel}${statsLabel}) `;
|
|
@@ -24309,12 +24399,8 @@ function renderFileBlock(file, opts) {
|
|
|
24309
24399
|
}
|
|
24310
24400
|
function formatLineNo(line, show) {
|
|
24311
24401
|
if (!show) return "";
|
|
24312
|
-
|
|
24313
|
-
|
|
24314
|
-
} else if (line.type === "delete") {
|
|
24315
|
-
return chalk12.dim(`${String(line.oldLineNo ?? "").padStart(4)} `);
|
|
24316
|
-
}
|
|
24317
|
-
return chalk12.dim(`${String(line.newLineNo ?? "").padStart(4)} `);
|
|
24402
|
+
const lineNo = line.type === "delete" ? line.oldLineNo : line.newLineNo;
|
|
24403
|
+
return chalk12.dim(`${String(lineNo ?? "").padStart(5)} `);
|
|
24318
24404
|
}
|
|
24319
24405
|
function getChangedLines(diff) {
|
|
24320
24406
|
const result = /* @__PURE__ */ new Map();
|
|
@@ -26471,6 +26557,13 @@ Examples:
|
|
|
26471
26557
|
const startTime = performance.now();
|
|
26472
26558
|
const effectivePrompt = prompt ?? "Describe this image in detail. If it's code or a UI, identify the key elements.";
|
|
26473
26559
|
const absPath = path31.resolve(filePath);
|
|
26560
|
+
const cwd = process.cwd();
|
|
26561
|
+
if (!absPath.startsWith(cwd + path31.sep) && absPath !== cwd) {
|
|
26562
|
+
throw new ToolError(
|
|
26563
|
+
`Path traversal denied: '${filePath}' resolves outside the project directory`,
|
|
26564
|
+
{ tool: "read_image" }
|
|
26565
|
+
);
|
|
26566
|
+
}
|
|
26474
26567
|
const ext = path31.extname(absPath).toLowerCase();
|
|
26475
26568
|
if (!SUPPORTED_FORMATS.has(ext)) {
|
|
26476
26569
|
throw new ToolError(
|
|
@@ -28598,6 +28691,17 @@ async function startRepl(options = {}) {
|
|
|
28598
28691
|
const inputHandler = createInputHandler();
|
|
28599
28692
|
const intentRecognizer = createIntentRecognizer();
|
|
28600
28693
|
await printWelcome(session);
|
|
28694
|
+
const cleanupTerminal = () => {
|
|
28695
|
+
process.stdout.write("\x1B[?2004l");
|
|
28696
|
+
if (process.stdin.isTTY && process.stdin.isRaw) {
|
|
28697
|
+
process.stdin.setRawMode(false);
|
|
28698
|
+
}
|
|
28699
|
+
};
|
|
28700
|
+
process.on("exit", cleanupTerminal);
|
|
28701
|
+
process.on("SIGTERM", () => {
|
|
28702
|
+
cleanupTerminal();
|
|
28703
|
+
process.exit(0);
|
|
28704
|
+
});
|
|
28601
28705
|
while (true) {
|
|
28602
28706
|
const input = await inputHandler.prompt();
|
|
28603
28707
|
if (input === null && !hasPendingImage()) {
|
|
@@ -28677,6 +28781,14 @@ async function startRepl(options = {}) {
|
|
|
28677
28781
|
activeSpinner.start();
|
|
28678
28782
|
}
|
|
28679
28783
|
};
|
|
28784
|
+
const abortController = new AbortController();
|
|
28785
|
+
let wasAborted = false;
|
|
28786
|
+
const sigintHandler = () => {
|
|
28787
|
+
wasAborted = true;
|
|
28788
|
+
abortController.abort();
|
|
28789
|
+
clearSpinner();
|
|
28790
|
+
renderInfo("\nOperation cancelled");
|
|
28791
|
+
};
|
|
28680
28792
|
try {
|
|
28681
28793
|
if (typeof agentMessage === "string" && !isCocoMode() && !wasHintShown() && looksLikeFeatureRequest(agentMessage)) {
|
|
28682
28794
|
markHintShown();
|
|
@@ -28689,14 +28801,6 @@ async function startRepl(options = {}) {
|
|
|
28689
28801
|
session.config.agent.systemPrompt = originalSystemPrompt + "\n" + getCocoModeSystemPrompt();
|
|
28690
28802
|
}
|
|
28691
28803
|
inputHandler.pause();
|
|
28692
|
-
const abortController = new AbortController();
|
|
28693
|
-
let wasAborted = false;
|
|
28694
|
-
const sigintHandler = () => {
|
|
28695
|
-
wasAborted = true;
|
|
28696
|
-
abortController.abort();
|
|
28697
|
-
clearSpinner();
|
|
28698
|
-
renderInfo("\nOperation cancelled");
|
|
28699
|
-
};
|
|
28700
28804
|
process.once("SIGINT", sigintHandler);
|
|
28701
28805
|
const result = await executeAgentTurn(session, agentMessage, provider, toolRegistry, {
|
|
28702
28806
|
onStream: renderStreamChunk,
|
|
@@ -28785,6 +28889,7 @@ async function startRepl(options = {}) {
|
|
|
28785
28889
|
console.log();
|
|
28786
28890
|
} catch (error) {
|
|
28787
28891
|
clearSpinner();
|
|
28892
|
+
process.off("SIGINT", sigintHandler);
|
|
28788
28893
|
if (error instanceof Error && error.name === "AbortError") {
|
|
28789
28894
|
continue;
|
|
28790
28895
|
}
|