@corbat-tech/coco 2.20.0 → 2.20.1
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/cli/index.js +109 -27
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -10530,15 +10530,19 @@ function installProcessSafetyNet() {
|
|
|
10530
10530
|
_safetyNetInstalled = true;
|
|
10531
10531
|
const debug = Boolean(process.env["COCO_DEBUG"]);
|
|
10532
10532
|
process.on("uncaughtException", (error) => {
|
|
10533
|
+
if (isAbortError(error)) return;
|
|
10533
10534
|
const msg = error instanceof Error ? error.message : String(error);
|
|
10534
10535
|
console.error(chalk2.red(`
|
|
10535
|
-
\xD7 Unexpected error
|
|
10536
|
+
\xD7 Unexpected error: ${msg}`));
|
|
10537
|
+
console.error(chalk2.dim(" The REPL continues \u2014 type your next message or /help"));
|
|
10536
10538
|
if (debug) console.error(error.stack);
|
|
10537
10539
|
});
|
|
10538
10540
|
process.on("unhandledRejection", (reason) => {
|
|
10541
|
+
if (isAbortError(reason)) return;
|
|
10539
10542
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
10540
10543
|
console.error(chalk2.red(`
|
|
10541
|
-
\xD7 Unhandled
|
|
10544
|
+
\xD7 Unhandled error: ${msg}`));
|
|
10545
|
+
console.error(chalk2.dim(" The REPL continues \u2014 type your next message or /help"));
|
|
10542
10546
|
if (debug && reason instanceof Error) console.error(reason.stack);
|
|
10543
10547
|
});
|
|
10544
10548
|
}
|
|
@@ -36816,7 +36820,22 @@ async function savePermissionPreference(key, value) {
|
|
|
36816
36820
|
}
|
|
36817
36821
|
async function shouldShowPermissionSuggestion() {
|
|
36818
36822
|
const prefs = await loadPermissionPreferences();
|
|
36819
|
-
|
|
36823
|
+
if (prefs.recommendedAllowlistDismissed) {
|
|
36824
|
+
return false;
|
|
36825
|
+
}
|
|
36826
|
+
if (!prefs.recommendedAllowlistApplied) {
|
|
36827
|
+
return true;
|
|
36828
|
+
}
|
|
36829
|
+
try {
|
|
36830
|
+
const content = await fs34__default.readFile(CONFIG_PATHS.trustedTools, "utf-8");
|
|
36831
|
+
const settings = JSON.parse(content);
|
|
36832
|
+
if (!settings.globalTrusted || settings.globalTrusted.length === 0) {
|
|
36833
|
+
return true;
|
|
36834
|
+
}
|
|
36835
|
+
} catch {
|
|
36836
|
+
return true;
|
|
36837
|
+
}
|
|
36838
|
+
return false;
|
|
36820
36839
|
}
|
|
36821
36840
|
async function applyRecommendedPermissions() {
|
|
36822
36841
|
for (const tool of [...RECOMMENDED_GLOBAL, ...RECOMMENDED_PROJECT]) {
|
|
@@ -47606,11 +47625,7 @@ ${icon} ${label}`);
|
|
|
47606
47625
|
if (toolName === "edit_file") {
|
|
47607
47626
|
console.log(`
|
|
47608
47627
|
${icon} ${chalk2.yellow.bold("EDIT")} ${chalk2.cyan(String(input.path || ""))}`);
|
|
47609
|
-
|
|
47610
|
-
String(input.old_string || ""),
|
|
47611
|
-
String(input.new_string || "")
|
|
47612
|
-
);
|
|
47613
|
-
if (editPreview) console.log(editPreview);
|
|
47628
|
+
printEditDiff(String(input.oldText || ""), String(input.newText || ""));
|
|
47614
47629
|
return;
|
|
47615
47630
|
}
|
|
47616
47631
|
console.log(`
|
|
@@ -47682,20 +47697,21 @@ function wordLevelHighlight(deletedContent, addedContent) {
|
|
|
47682
47697
|
}
|
|
47683
47698
|
return { styledDelete, styledAdd };
|
|
47684
47699
|
}
|
|
47685
|
-
function
|
|
47700
|
+
function printEditDiff(oldStr, newStr) {
|
|
47686
47701
|
const termWidth = Math.max(getTerminalWidth2() - 14, 30);
|
|
47687
47702
|
const MAX_SHOWN = 30;
|
|
47688
47703
|
if (!oldStr.trim()) {
|
|
47689
47704
|
const lines = newStr.split("\n").filter((l) => l.trim().length > 0).slice(0, 6);
|
|
47690
|
-
if (lines.length === 0) return
|
|
47705
|
+
if (lines.length === 0) return;
|
|
47691
47706
|
const truncate4 = (s) => s.length > termWidth - 2 ? s.slice(0, termWidth - 3) + "\u2026" : s;
|
|
47692
|
-
|
|
47707
|
+
for (const l of lines) {
|
|
47693
47708
|
const text13 = `+ ${truncate4(l)}`;
|
|
47694
47709
|
const pad = Math.max(0, termWidth - stripAnsi(text13).length + 2);
|
|
47695
|
-
|
|
47696
|
-
}
|
|
47710
|
+
console.log(" " + diffBgAdd(text13 + " ".repeat(pad)));
|
|
47711
|
+
}
|
|
47712
|
+
return;
|
|
47697
47713
|
}
|
|
47698
|
-
if (!newStr.trim() && !oldStr.trim()) return
|
|
47714
|
+
if (!newStr.trim() && !oldStr.trim()) return;
|
|
47699
47715
|
const changes = diffLines(oldStr, newStr);
|
|
47700
47716
|
const diffLineList = [];
|
|
47701
47717
|
let oldNo = 1;
|
|
@@ -47717,7 +47733,7 @@ function renderEditPreview(oldStr, newStr) {
|
|
|
47717
47733
|
}
|
|
47718
47734
|
}
|
|
47719
47735
|
}
|
|
47720
|
-
if (diffLineList.length === 0) return
|
|
47736
|
+
if (diffLineList.length === 0) return;
|
|
47721
47737
|
const pairs = pairAdjacentDiffLines(diffLineList);
|
|
47722
47738
|
const pairedDeletes = new Set(pairs.map((p45) => p45.deleteIdx));
|
|
47723
47739
|
const pairedAdds = new Set(pairs.map((p45) => p45.addIdx));
|
|
@@ -47739,7 +47755,6 @@ function renderEditPreview(oldStr, newStr) {
|
|
|
47739
47755
|
if (n >= 0 && n < diffLineList.length) visibleIndices.add(n);
|
|
47740
47756
|
}
|
|
47741
47757
|
}
|
|
47742
|
-
const result = [];
|
|
47743
47758
|
let shown = 0;
|
|
47744
47759
|
let prevIdx = -1;
|
|
47745
47760
|
const truncate3 = (s) => s.length > termWidth ? s.slice(0, termWidth - 1) + "\u2026" : s;
|
|
@@ -47751,11 +47766,11 @@ function renderEditPreview(oldStr, newStr) {
|
|
|
47751
47766
|
for (let i = 0; i < diffLineList.length; i++) {
|
|
47752
47767
|
if (!visibleIndices.has(i)) continue;
|
|
47753
47768
|
if (shown >= MAX_SHOWN) {
|
|
47754
|
-
|
|
47769
|
+
console.log(chalk2.dim(` \u2026 +${diffLineList.length - i} more lines`));
|
|
47755
47770
|
break;
|
|
47756
47771
|
}
|
|
47757
47772
|
if (prevIdx >= 0 && i > prevIdx + 1) {
|
|
47758
|
-
|
|
47773
|
+
console.log(chalk2.dim(" \u22EE"));
|
|
47759
47774
|
}
|
|
47760
47775
|
prevIdx = i;
|
|
47761
47776
|
shown++;
|
|
@@ -47765,20 +47780,19 @@ function renderEditPreview(oldStr, newStr) {
|
|
|
47765
47780
|
const visLen = stripAnsi(rawContent).length;
|
|
47766
47781
|
const pad = Math.max(0, termWidth - visLen);
|
|
47767
47782
|
const line = diffBgAdd(` + ${rawContent}${" ".repeat(pad)}`);
|
|
47768
|
-
|
|
47783
|
+
console.log(" " + gutter(void 0, dl.newLineNo) + line);
|
|
47769
47784
|
} else if (dl.type === "delete") {
|
|
47770
47785
|
const rawContent = pairedDeletes.has(i) ? wordHighlights.get(i)?.styledDelete ?? truncate3(dl.content) : truncate3(dl.content);
|
|
47771
47786
|
const visLen = stripAnsi(rawContent).length;
|
|
47772
47787
|
const pad = Math.max(0, termWidth - visLen);
|
|
47773
47788
|
const line = diffBgDel(` - ${rawContent}${" ".repeat(pad)}`);
|
|
47774
|
-
|
|
47789
|
+
console.log(" " + gutter(dl.oldLineNo, void 0) + line);
|
|
47775
47790
|
} else {
|
|
47776
|
-
|
|
47791
|
+
console.log(
|
|
47777
47792
|
" " + gutter(dl.oldLineNo, dl.newLineNo) + chalk2.dim(` ${truncate3(dl.content)}`)
|
|
47778
47793
|
);
|
|
47779
47794
|
}
|
|
47780
47795
|
}
|
|
47781
|
-
return result.join("\n");
|
|
47782
47796
|
}
|
|
47783
47797
|
function renderToolEnd(result) {
|
|
47784
47798
|
const status = result.result.success ? chalk2.green("\u2713") : chalk2.red("\u2717");
|
|
@@ -49800,7 +49814,21 @@ var ParallelToolExecutor = class {
|
|
|
49800
49814
|
if (isAbortError(error, signal)) {
|
|
49801
49815
|
return null;
|
|
49802
49816
|
}
|
|
49803
|
-
|
|
49817
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
49818
|
+
const duration2 = performance.now() - startTime;
|
|
49819
|
+
const executedCall2 = {
|
|
49820
|
+
id: toolCall.id,
|
|
49821
|
+
name: toolCall.name,
|
|
49822
|
+
input: toolCall.input,
|
|
49823
|
+
result: {
|
|
49824
|
+
success: false,
|
|
49825
|
+
output: `Unexpected error in ${toolCall.name}: ${errMsg}`,
|
|
49826
|
+
error: errMsg
|
|
49827
|
+
},
|
|
49828
|
+
duration: duration2
|
|
49829
|
+
};
|
|
49830
|
+
onToolEnd?.(executedCall2);
|
|
49831
|
+
return executedCall2;
|
|
49804
49832
|
}
|
|
49805
49833
|
if (!result.success && result.error && onPathAccessDenied) {
|
|
49806
49834
|
const dirPath = extractDeniedPath(result.error);
|
|
@@ -49811,7 +49839,13 @@ var ParallelToolExecutor = class {
|
|
|
49811
49839
|
} catch {
|
|
49812
49840
|
}
|
|
49813
49841
|
if (authorized) {
|
|
49814
|
-
|
|
49842
|
+
try {
|
|
49843
|
+
result = await registry.execute(toolCall.name, toolCall.input, { signal });
|
|
49844
|
+
} catch (retryError) {
|
|
49845
|
+
if (isAbortError(retryError, signal)) return null;
|
|
49846
|
+
const msg = retryError instanceof Error ? retryError.message : String(retryError);
|
|
49847
|
+
result = { success: false, error: `Retry failed: ${msg}`, duration: 0 };
|
|
49848
|
+
}
|
|
49815
49849
|
}
|
|
49816
49850
|
}
|
|
49817
49851
|
}
|
|
@@ -50110,7 +50144,18 @@ ${tail}`;
|
|
|
50110
50144
|
const needsConfirmation = !options.skipConfirmation && !session.trustedTools.has(trustPattern) && requiresConfirmation(toolCall.name, toolCall.input);
|
|
50111
50145
|
if (needsConfirmation) {
|
|
50112
50146
|
options.onBeforeConfirmation?.();
|
|
50113
|
-
|
|
50147
|
+
let confirmResult;
|
|
50148
|
+
try {
|
|
50149
|
+
confirmResult = await confirmToolExecution(toolCall);
|
|
50150
|
+
} catch (confirmError) {
|
|
50151
|
+
options.onAfterConfirmation?.();
|
|
50152
|
+
declinedTools.set(
|
|
50153
|
+
toolCall.id,
|
|
50154
|
+
`Confirmation failed: ${confirmError instanceof Error ? confirmError.message : String(confirmError)}`
|
|
50155
|
+
);
|
|
50156
|
+
options.onToolSkipped?.(toolCall, "Confirmation error");
|
|
50157
|
+
continue;
|
|
50158
|
+
}
|
|
50114
50159
|
options.onAfterConfirmation?.();
|
|
50115
50160
|
if (typeof confirmResult === "object" && confirmResult.type === "edit") {
|
|
50116
50161
|
const editedToolCall = {
|
|
@@ -51164,6 +51209,11 @@ async function startRepl(options = {}) {
|
|
|
51164
51209
|
agentMessage = commandResult.forkPrompt;
|
|
51165
51210
|
} else if (hasPendingImage()) {
|
|
51166
51211
|
const images = consumePendingImages();
|
|
51212
|
+
const imagePrompts = images.map((img) => img.prompt).join("\n");
|
|
51213
|
+
const userText = input?.trim() || "";
|
|
51214
|
+
const combinedText = userText ? `${userText}
|
|
51215
|
+
|
|
51216
|
+
${imagePrompts}`.trim() : imagePrompts;
|
|
51167
51217
|
agentMessage = [
|
|
51168
51218
|
...images.map(
|
|
51169
51219
|
(img) => ({
|
|
@@ -51173,7 +51223,7 @@ async function startRepl(options = {}) {
|
|
|
51173
51223
|
),
|
|
51174
51224
|
{
|
|
51175
51225
|
type: "text",
|
|
51176
|
-
text:
|
|
51226
|
+
text: combinedText
|
|
51177
51227
|
}
|
|
51178
51228
|
];
|
|
51179
51229
|
} else {
|
|
@@ -51182,6 +51232,11 @@ async function startRepl(options = {}) {
|
|
|
51182
51232
|
}
|
|
51183
51233
|
if (agentMessage === null && hasPendingImage()) {
|
|
51184
51234
|
const images = consumePendingImages();
|
|
51235
|
+
const imagePrompts = images.map((img) => img.prompt).join("\n");
|
|
51236
|
+
const userText = input?.trim() || "";
|
|
51237
|
+
const combinedText = userText ? `${userText}
|
|
51238
|
+
|
|
51239
|
+
${imagePrompts}`.trim() : imagePrompts;
|
|
51185
51240
|
agentMessage = [
|
|
51186
51241
|
...images.map(
|
|
51187
51242
|
(img) => ({
|
|
@@ -51191,7 +51246,7 @@ async function startRepl(options = {}) {
|
|
|
51191
51246
|
),
|
|
51192
51247
|
{
|
|
51193
51248
|
type: "text",
|
|
51194
|
-
text:
|
|
51249
|
+
text: combinedText
|
|
51195
51250
|
}
|
|
51196
51251
|
];
|
|
51197
51252
|
}
|
|
@@ -51524,6 +51579,31 @@ async function startRepl(options = {}) {
|
|
|
51524
51579
|
console.log();
|
|
51525
51580
|
continue;
|
|
51526
51581
|
}
|
|
51582
|
+
if (result.error) {
|
|
51583
|
+
session.messages.length = preCallMessageLength;
|
|
51584
|
+
if (originalUserMessage !== null && consecutiveErrors < MAX_CONSECUTIVE_ERRORS && !isNonRetryableProviderError(new Error(result.error))) {
|
|
51585
|
+
consecutiveErrors++;
|
|
51586
|
+
const humanized = humanizeProviderError(new Error(result.error));
|
|
51587
|
+
renderError(humanized);
|
|
51588
|
+
console.log(
|
|
51589
|
+
chalk2.dim(
|
|
51590
|
+
` \u21BB Retrying automatically (attempt ${consecutiveErrors}/${MAX_CONSECUTIVE_ERRORS})\u2026`
|
|
51591
|
+
)
|
|
51592
|
+
);
|
|
51593
|
+
const recoveryPrefix = `[System: The previous attempt failed with: "${humanized}". Please try a different approach, tool, or method to complete the task. Do NOT repeat the exact same action that caused the error.]
|
|
51594
|
+
|
|
51595
|
+
`;
|
|
51596
|
+
pendingQueuedMessages = [recoveryPrefix + originalUserMessage];
|
|
51597
|
+
} else {
|
|
51598
|
+
renderError(result.error);
|
|
51599
|
+
console.log(
|
|
51600
|
+
chalk2.dim(" Recovery failed or error is non-retryable. Returning to prompt.")
|
|
51601
|
+
);
|
|
51602
|
+
consecutiveErrors = 0;
|
|
51603
|
+
}
|
|
51604
|
+
console.log();
|
|
51605
|
+
continue;
|
|
51606
|
+
}
|
|
51527
51607
|
console.log();
|
|
51528
51608
|
if (pendingExplanations.length > 0) {
|
|
51529
51609
|
const settled = await Promise.race([
|
|
@@ -52122,6 +52202,7 @@ registerSwarmCommand(program);
|
|
|
52122
52202
|
program.command("setup").description("Configure AI provider and API key").action(async () => {
|
|
52123
52203
|
const result = await runOnboardingV2();
|
|
52124
52204
|
if (result) {
|
|
52205
|
+
await saveConfiguration(result);
|
|
52125
52206
|
console.log("\n\u2705 Configuration saved! Run `coco` to start coding.");
|
|
52126
52207
|
} else {
|
|
52127
52208
|
console.log("\n\u274C Setup cancelled.");
|
|
@@ -52135,6 +52216,7 @@ program.command("chat", { isDefault: true }).description("Start interactive chat
|
|
|
52135
52216
|
console.log("\n\u274C Setup cancelled.");
|
|
52136
52217
|
return;
|
|
52137
52218
|
}
|
|
52219
|
+
await saveConfiguration(result);
|
|
52138
52220
|
}
|
|
52139
52221
|
const providerType = options.provider ?? await getLastUsedProvider();
|
|
52140
52222
|
if (options.print !== void 0) {
|