@corbat-tech/coco 2.20.0 → 2.21.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/dist/cli/index.js +121 -33
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -4487,7 +4487,7 @@ var init_codex = __esm({
|
|
|
4487
4487
|
model,
|
|
4488
4488
|
input,
|
|
4489
4489
|
instructions: instructions ?? "You are a helpful coding assistant.",
|
|
4490
|
-
|
|
4490
|
+
max_output_tokens: options?.maxTokens ?? this.config.maxTokens ?? 8192,
|
|
4491
4491
|
temperature: options?.temperature ?? this.config.temperature ?? 0,
|
|
4492
4492
|
store: false,
|
|
4493
4493
|
stream: true
|
|
@@ -10461,8 +10461,9 @@ function isNonRetryableProviderError(error) {
|
|
|
10461
10461
|
if (error instanceof ProviderError) {
|
|
10462
10462
|
const code = error.statusCode;
|
|
10463
10463
|
if (code === 401 || code === 403) return true;
|
|
10464
|
+
if (code === 400) return true;
|
|
10464
10465
|
const msg = error.message.toLowerCase();
|
|
10465
|
-
if (msg.includes("exceeded your current quota") || msg.includes("usage limit") || msg.includes("insufficient_quota") || msg.includes("billing") || msg.includes("payment") || msg.includes("invalid_api_key") || msg.includes("incorrect api key") || msg.includes("bad credentials") || msg.includes("not authorized")) {
|
|
10466
|
+
if (msg.includes("exceeded your current quota") || msg.includes("usage limit") || msg.includes("insufficient_quota") || msg.includes("billing") || msg.includes("payment") || msg.includes("invalid_api_key") || msg.includes("incorrect api key") || msg.includes("bad credentials") || msg.includes("not authorized") || msg.includes("unsupported parameter")) {
|
|
10466
10467
|
return true;
|
|
10467
10468
|
}
|
|
10468
10469
|
}
|
|
@@ -10530,15 +10531,19 @@ function installProcessSafetyNet() {
|
|
|
10530
10531
|
_safetyNetInstalled = true;
|
|
10531
10532
|
const debug = Boolean(process.env["COCO_DEBUG"]);
|
|
10532
10533
|
process.on("uncaughtException", (error) => {
|
|
10534
|
+
if (isAbortError(error)) return;
|
|
10533
10535
|
const msg = error instanceof Error ? error.message : String(error);
|
|
10534
10536
|
console.error(chalk2.red(`
|
|
10535
|
-
\xD7 Unexpected error
|
|
10537
|
+
\xD7 Unexpected error: ${msg}`));
|
|
10538
|
+
console.error(chalk2.dim(" The REPL continues \u2014 type your next message or /help"));
|
|
10536
10539
|
if (debug) console.error(error.stack);
|
|
10537
10540
|
});
|
|
10538
10541
|
process.on("unhandledRejection", (reason) => {
|
|
10542
|
+
if (isAbortError(reason)) return;
|
|
10539
10543
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
10540
10544
|
console.error(chalk2.red(`
|
|
10541
|
-
\xD7 Unhandled
|
|
10545
|
+
\xD7 Unhandled error: ${msg}`));
|
|
10546
|
+
console.error(chalk2.dim(" The REPL continues \u2014 type your next message or /help"));
|
|
10542
10547
|
if (debug && reason instanceof Error) console.error(reason.stack);
|
|
10543
10548
|
});
|
|
10544
10549
|
}
|
|
@@ -11173,12 +11178,12 @@ function renderFileBlock(file, opts) {
|
|
|
11173
11178
|
}
|
|
11174
11179
|
}
|
|
11175
11180
|
}
|
|
11176
|
-
console.log();
|
|
11177
11181
|
}
|
|
11178
11182
|
function formatLineNo(line, show) {
|
|
11179
11183
|
if (!show) return "";
|
|
11180
|
-
const
|
|
11181
|
-
|
|
11184
|
+
const oldStr = line.oldLineNo !== void 0 ? String(line.oldLineNo) : "";
|
|
11185
|
+
const newStr = line.newLineNo !== void 0 ? String(line.newLineNo) : "";
|
|
11186
|
+
return chalk2.dim(`${oldStr.padStart(4)} | ${newStr.padStart(4)} `);
|
|
11182
11187
|
}
|
|
11183
11188
|
function getChangedLines(diff) {
|
|
11184
11189
|
const result = /* @__PURE__ */ new Map();
|
|
@@ -36816,7 +36821,22 @@ async function savePermissionPreference(key, value) {
|
|
|
36816
36821
|
}
|
|
36817
36822
|
async function shouldShowPermissionSuggestion() {
|
|
36818
36823
|
const prefs = await loadPermissionPreferences();
|
|
36819
|
-
|
|
36824
|
+
if (prefs.recommendedAllowlistDismissed) {
|
|
36825
|
+
return false;
|
|
36826
|
+
}
|
|
36827
|
+
if (!prefs.recommendedAllowlistApplied) {
|
|
36828
|
+
return true;
|
|
36829
|
+
}
|
|
36830
|
+
try {
|
|
36831
|
+
const content = await fs34__default.readFile(CONFIG_PATHS.trustedTools, "utf-8");
|
|
36832
|
+
const settings = JSON.parse(content);
|
|
36833
|
+
if (!settings.globalTrusted || settings.globalTrusted.length === 0) {
|
|
36834
|
+
return true;
|
|
36835
|
+
}
|
|
36836
|
+
} catch {
|
|
36837
|
+
return true;
|
|
36838
|
+
}
|
|
36839
|
+
return false;
|
|
36820
36840
|
}
|
|
36821
36841
|
async function applyRecommendedPermissions() {
|
|
36822
36842
|
for (const tool of [...RECOMMENDED_GLOBAL, ...RECOMMENDED_PROJECT]) {
|
|
@@ -47606,11 +47626,7 @@ ${icon} ${label}`);
|
|
|
47606
47626
|
if (toolName === "edit_file") {
|
|
47607
47627
|
console.log(`
|
|
47608
47628
|
${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);
|
|
47629
|
+
printEditDiff(String(input.oldText || ""), String(input.newText || ""));
|
|
47614
47630
|
return;
|
|
47615
47631
|
}
|
|
47616
47632
|
console.log(`
|
|
@@ -47682,20 +47698,21 @@ function wordLevelHighlight(deletedContent, addedContent) {
|
|
|
47682
47698
|
}
|
|
47683
47699
|
return { styledDelete, styledAdd };
|
|
47684
47700
|
}
|
|
47685
|
-
function
|
|
47686
|
-
const termWidth = Math.max(getTerminalWidth2() -
|
|
47701
|
+
function printEditDiff(oldStr, newStr) {
|
|
47702
|
+
const termWidth = Math.max(getTerminalWidth2() - 15, 30);
|
|
47687
47703
|
const MAX_SHOWN = 30;
|
|
47688
47704
|
if (!oldStr.trim()) {
|
|
47689
47705
|
const lines = newStr.split("\n").filter((l) => l.trim().length > 0).slice(0, 6);
|
|
47690
|
-
if (lines.length === 0) return
|
|
47706
|
+
if (lines.length === 0) return;
|
|
47691
47707
|
const truncate4 = (s) => s.length > termWidth - 2 ? s.slice(0, termWidth - 3) + "\u2026" : s;
|
|
47692
|
-
|
|
47708
|
+
for (const l of lines) {
|
|
47693
47709
|
const text13 = `+ ${truncate4(l)}`;
|
|
47694
47710
|
const pad = Math.max(0, termWidth - stripAnsi(text13).length + 2);
|
|
47695
|
-
|
|
47696
|
-
}
|
|
47711
|
+
console.log(" " + diffBgAdd(text13 + " ".repeat(pad)));
|
|
47712
|
+
}
|
|
47713
|
+
return;
|
|
47697
47714
|
}
|
|
47698
|
-
if (!newStr.trim() && !oldStr.trim()) return
|
|
47715
|
+
if (!newStr.trim() && !oldStr.trim()) return;
|
|
47699
47716
|
const changes = diffLines(oldStr, newStr);
|
|
47700
47717
|
const diffLineList = [];
|
|
47701
47718
|
let oldNo = 1;
|
|
@@ -47717,7 +47734,7 @@ function renderEditPreview(oldStr, newStr) {
|
|
|
47717
47734
|
}
|
|
47718
47735
|
}
|
|
47719
47736
|
}
|
|
47720
|
-
if (diffLineList.length === 0) return
|
|
47737
|
+
if (diffLineList.length === 0) return;
|
|
47721
47738
|
const pairs = pairAdjacentDiffLines(diffLineList);
|
|
47722
47739
|
const pairedDeletes = new Set(pairs.map((p45) => p45.deleteIdx));
|
|
47723
47740
|
const pairedAdds = new Set(pairs.map((p45) => p45.addIdx));
|
|
@@ -47739,7 +47756,6 @@ function renderEditPreview(oldStr, newStr) {
|
|
|
47739
47756
|
if (n >= 0 && n < diffLineList.length) visibleIndices.add(n);
|
|
47740
47757
|
}
|
|
47741
47758
|
}
|
|
47742
|
-
const result = [];
|
|
47743
47759
|
let shown = 0;
|
|
47744
47760
|
let prevIdx = -1;
|
|
47745
47761
|
const truncate3 = (s) => s.length > termWidth ? s.slice(0, termWidth - 1) + "\u2026" : s;
|
|
@@ -47751,11 +47767,11 @@ function renderEditPreview(oldStr, newStr) {
|
|
|
47751
47767
|
for (let i = 0; i < diffLineList.length; i++) {
|
|
47752
47768
|
if (!visibleIndices.has(i)) continue;
|
|
47753
47769
|
if (shown >= MAX_SHOWN) {
|
|
47754
|
-
|
|
47770
|
+
console.log(chalk2.dim(` \u2026 +${diffLineList.length - i} more lines`));
|
|
47755
47771
|
break;
|
|
47756
47772
|
}
|
|
47757
47773
|
if (prevIdx >= 0 && i > prevIdx + 1) {
|
|
47758
|
-
|
|
47774
|
+
console.log(chalk2.dim(" \u22EE"));
|
|
47759
47775
|
}
|
|
47760
47776
|
prevIdx = i;
|
|
47761
47777
|
shown++;
|
|
@@ -47765,20 +47781,19 @@ function renderEditPreview(oldStr, newStr) {
|
|
|
47765
47781
|
const visLen = stripAnsi(rawContent).length;
|
|
47766
47782
|
const pad = Math.max(0, termWidth - visLen);
|
|
47767
47783
|
const line = diffBgAdd(` + ${rawContent}${" ".repeat(pad)}`);
|
|
47768
|
-
|
|
47784
|
+
console.log(" " + gutter(void 0, dl.newLineNo) + line);
|
|
47769
47785
|
} else if (dl.type === "delete") {
|
|
47770
47786
|
const rawContent = pairedDeletes.has(i) ? wordHighlights.get(i)?.styledDelete ?? truncate3(dl.content) : truncate3(dl.content);
|
|
47771
47787
|
const visLen = stripAnsi(rawContent).length;
|
|
47772
47788
|
const pad = Math.max(0, termWidth - visLen);
|
|
47773
47789
|
const line = diffBgDel(` - ${rawContent}${" ".repeat(pad)}`);
|
|
47774
|
-
|
|
47790
|
+
console.log(" " + gutter(dl.oldLineNo, void 0) + line);
|
|
47775
47791
|
} else {
|
|
47776
|
-
|
|
47792
|
+
console.log(
|
|
47777
47793
|
" " + gutter(dl.oldLineNo, dl.newLineNo) + chalk2.dim(` ${truncate3(dl.content)}`)
|
|
47778
47794
|
);
|
|
47779
47795
|
}
|
|
47780
47796
|
}
|
|
47781
|
-
return result.join("\n");
|
|
47782
47797
|
}
|
|
47783
47798
|
function renderToolEnd(result) {
|
|
47784
47799
|
const status = result.result.success ? chalk2.green("\u2713") : chalk2.red("\u2717");
|
|
@@ -49800,7 +49815,21 @@ var ParallelToolExecutor = class {
|
|
|
49800
49815
|
if (isAbortError(error, signal)) {
|
|
49801
49816
|
return null;
|
|
49802
49817
|
}
|
|
49803
|
-
|
|
49818
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
49819
|
+
const duration2 = performance.now() - startTime;
|
|
49820
|
+
const executedCall2 = {
|
|
49821
|
+
id: toolCall.id,
|
|
49822
|
+
name: toolCall.name,
|
|
49823
|
+
input: toolCall.input,
|
|
49824
|
+
result: {
|
|
49825
|
+
success: false,
|
|
49826
|
+
output: `Unexpected error in ${toolCall.name}: ${errMsg}`,
|
|
49827
|
+
error: errMsg
|
|
49828
|
+
},
|
|
49829
|
+
duration: duration2
|
|
49830
|
+
};
|
|
49831
|
+
onToolEnd?.(executedCall2);
|
|
49832
|
+
return executedCall2;
|
|
49804
49833
|
}
|
|
49805
49834
|
if (!result.success && result.error && onPathAccessDenied) {
|
|
49806
49835
|
const dirPath = extractDeniedPath(result.error);
|
|
@@ -49811,7 +49840,13 @@ var ParallelToolExecutor = class {
|
|
|
49811
49840
|
} catch {
|
|
49812
49841
|
}
|
|
49813
49842
|
if (authorized) {
|
|
49814
|
-
|
|
49843
|
+
try {
|
|
49844
|
+
result = await registry.execute(toolCall.name, toolCall.input, { signal });
|
|
49845
|
+
} catch (retryError) {
|
|
49846
|
+
if (isAbortError(retryError, signal)) return null;
|
|
49847
|
+
const msg = retryError instanceof Error ? retryError.message : String(retryError);
|
|
49848
|
+
result = { success: false, error: `Retry failed: ${msg}`, duration: 0 };
|
|
49849
|
+
}
|
|
49815
49850
|
}
|
|
49816
49851
|
}
|
|
49817
49852
|
}
|
|
@@ -50046,6 +50081,9 @@ ${tail}`;
|
|
|
50046
50081
|
if (isAbortError(streamError, options.signal)) {
|
|
50047
50082
|
return abortReturn();
|
|
50048
50083
|
}
|
|
50084
|
+
if (isNonRetryableProviderError(streamError)) {
|
|
50085
|
+
throw streamError;
|
|
50086
|
+
}
|
|
50049
50087
|
const errorMsg = streamError instanceof Error ? streamError.message : String(streamError);
|
|
50050
50088
|
addMessage(session, {
|
|
50051
50089
|
role: "assistant",
|
|
@@ -50110,7 +50148,18 @@ ${tail}`;
|
|
|
50110
50148
|
const needsConfirmation = !options.skipConfirmation && !session.trustedTools.has(trustPattern) && requiresConfirmation(toolCall.name, toolCall.input);
|
|
50111
50149
|
if (needsConfirmation) {
|
|
50112
50150
|
options.onBeforeConfirmation?.();
|
|
50113
|
-
|
|
50151
|
+
let confirmResult;
|
|
50152
|
+
try {
|
|
50153
|
+
confirmResult = await confirmToolExecution(toolCall);
|
|
50154
|
+
} catch (confirmError) {
|
|
50155
|
+
options.onAfterConfirmation?.();
|
|
50156
|
+
declinedTools.set(
|
|
50157
|
+
toolCall.id,
|
|
50158
|
+
`Confirmation failed: ${confirmError instanceof Error ? confirmError.message : String(confirmError)}`
|
|
50159
|
+
);
|
|
50160
|
+
options.onToolSkipped?.(toolCall, "Confirmation error");
|
|
50161
|
+
continue;
|
|
50162
|
+
}
|
|
50114
50163
|
options.onAfterConfirmation?.();
|
|
50115
50164
|
if (typeof confirmResult === "object" && confirmResult.type === "edit") {
|
|
50116
50165
|
const editedToolCall = {
|
|
@@ -51164,6 +51213,11 @@ async function startRepl(options = {}) {
|
|
|
51164
51213
|
agentMessage = commandResult.forkPrompt;
|
|
51165
51214
|
} else if (hasPendingImage()) {
|
|
51166
51215
|
const images = consumePendingImages();
|
|
51216
|
+
const imagePrompts = images.map((img) => img.prompt).join("\n");
|
|
51217
|
+
const userText = input?.trim() || "";
|
|
51218
|
+
const combinedText = userText ? `${userText}
|
|
51219
|
+
|
|
51220
|
+
${imagePrompts}`.trim() : imagePrompts;
|
|
51167
51221
|
agentMessage = [
|
|
51168
51222
|
...images.map(
|
|
51169
51223
|
(img) => ({
|
|
@@ -51173,7 +51227,7 @@ async function startRepl(options = {}) {
|
|
|
51173
51227
|
),
|
|
51174
51228
|
{
|
|
51175
51229
|
type: "text",
|
|
51176
|
-
text:
|
|
51230
|
+
text: combinedText
|
|
51177
51231
|
}
|
|
51178
51232
|
];
|
|
51179
51233
|
} else {
|
|
@@ -51182,6 +51236,11 @@ async function startRepl(options = {}) {
|
|
|
51182
51236
|
}
|
|
51183
51237
|
if (agentMessage === null && hasPendingImage()) {
|
|
51184
51238
|
const images = consumePendingImages();
|
|
51239
|
+
const imagePrompts = images.map((img) => img.prompt).join("\n");
|
|
51240
|
+
const userText = input?.trim() || "";
|
|
51241
|
+
const combinedText = userText ? `${userText}
|
|
51242
|
+
|
|
51243
|
+
${imagePrompts}`.trim() : imagePrompts;
|
|
51185
51244
|
agentMessage = [
|
|
51186
51245
|
...images.map(
|
|
51187
51246
|
(img) => ({
|
|
@@ -51191,7 +51250,7 @@ async function startRepl(options = {}) {
|
|
|
51191
51250
|
),
|
|
51192
51251
|
{
|
|
51193
51252
|
type: "text",
|
|
51194
|
-
text:
|
|
51253
|
+
text: combinedText
|
|
51195
51254
|
}
|
|
51196
51255
|
];
|
|
51197
51256
|
}
|
|
@@ -51524,6 +51583,31 @@ async function startRepl(options = {}) {
|
|
|
51524
51583
|
console.log();
|
|
51525
51584
|
continue;
|
|
51526
51585
|
}
|
|
51586
|
+
if (result.error) {
|
|
51587
|
+
session.messages.length = preCallMessageLength;
|
|
51588
|
+
if (originalUserMessage !== null && consecutiveErrors < MAX_CONSECUTIVE_ERRORS && !isNonRetryableProviderError(new Error(result.error))) {
|
|
51589
|
+
consecutiveErrors++;
|
|
51590
|
+
const humanized = humanizeProviderError(new Error(result.error));
|
|
51591
|
+
renderError(humanized);
|
|
51592
|
+
console.log(
|
|
51593
|
+
chalk2.dim(
|
|
51594
|
+
` \u21BB Retrying automatically (attempt ${consecutiveErrors}/${MAX_CONSECUTIVE_ERRORS})\u2026`
|
|
51595
|
+
)
|
|
51596
|
+
);
|
|
51597
|
+
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.]
|
|
51598
|
+
|
|
51599
|
+
`;
|
|
51600
|
+
pendingQueuedMessages = [recoveryPrefix + originalUserMessage];
|
|
51601
|
+
} else {
|
|
51602
|
+
renderError(result.error);
|
|
51603
|
+
console.log(
|
|
51604
|
+
chalk2.dim(" Recovery failed or error is non-retryable. Returning to prompt.")
|
|
51605
|
+
);
|
|
51606
|
+
consecutiveErrors = 0;
|
|
51607
|
+
}
|
|
51608
|
+
console.log();
|
|
51609
|
+
continue;
|
|
51610
|
+
}
|
|
51527
51611
|
console.log();
|
|
51528
51612
|
if (pendingExplanations.length > 0) {
|
|
51529
51613
|
const settled = await Promise.race([
|
|
@@ -51700,6 +51784,8 @@ async function startRepl(options = {}) {
|
|
|
51700
51784
|
console.log(chalk2.dim(" Recovery failed after multiple attempts. Returning to prompt."));
|
|
51701
51785
|
continue;
|
|
51702
51786
|
}
|
|
51787
|
+
session.messages.length = preCallMessageLength;
|
|
51788
|
+
consecutiveErrors = 0;
|
|
51703
51789
|
renderError(errorMsg);
|
|
51704
51790
|
} finally {
|
|
51705
51791
|
clearSpinner();
|
|
@@ -52122,6 +52208,7 @@ registerSwarmCommand(program);
|
|
|
52122
52208
|
program.command("setup").description("Configure AI provider and API key").action(async () => {
|
|
52123
52209
|
const result = await runOnboardingV2();
|
|
52124
52210
|
if (result) {
|
|
52211
|
+
await saveConfiguration(result);
|
|
52125
52212
|
console.log("\n\u2705 Configuration saved! Run `coco` to start coding.");
|
|
52126
52213
|
} else {
|
|
52127
52214
|
console.log("\n\u274C Setup cancelled.");
|
|
@@ -52135,6 +52222,7 @@ program.command("chat", { isDefault: true }).description("Start interactive chat
|
|
|
52135
52222
|
console.log("\n\u274C Setup cancelled.");
|
|
52136
52223
|
return;
|
|
52137
52224
|
}
|
|
52225
|
+
await saveConfiguration(result);
|
|
52138
52226
|
}
|
|
52139
52227
|
const providerType = options.provider ?? await getLastUsedProvider();
|
|
52140
52228
|
if (options.print !== void 0) {
|