@corbat-tech/coco 2.22.2 → 2.23.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 +95 -11
- 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
|
@@ -9617,7 +9617,15 @@ Responses are short and direct by default. Lead with the answer or action, not r
|
|
|
9617
9617
|
|
|
9618
9618
|
## File Changes
|
|
9619
9619
|
|
|
9620
|
-
**Never output raw diff or unified diff format in your responses.** Use edit_file and write_file to make changes \u2014 Coco renders a visual diff automatically.
|
|
9620
|
+
**Never output raw diff or unified diff format in your responses.** Use edit_file and write_file to make changes \u2014 Coco renders a visual diff automatically.
|
|
9621
|
+
|
|
9622
|
+
## Output Discipline
|
|
9623
|
+
|
|
9624
|
+
**NEVER echo file contents in your responses.** When you read a file, extract only the specific information needed \u2014 do NOT reprint whole files, functions, or large excerpts. The terminal shows which files you read and their line counts \u2014 the user does not need to see the content again.
|
|
9625
|
+
|
|
9626
|
+
**During tool-calling iterations, keep text minimal.** A single short orienting line before tool calls is acceptable. Do NOT explain every step, narrate what you are about to do, or produce paragraphs between tool calls. Reserve explanatory text for your final response after all tools have completed.
|
|
9627
|
+
|
|
9628
|
+
**Code blocks in responses are expensive.** Only include a code block when the user explicitly asks to see code, or when the code IS the deliverable (e.g., a script to paste in a terminal). Never include a code block to "show your work" when you can write the file directly instead.`;
|
|
9621
9629
|
SHELL_METACHARACTERS = /[;|&`$(){}<>!\n\\'"]/;
|
|
9622
9630
|
SAFE_COMMAND_VALIDATORS = {
|
|
9623
9631
|
git: (args) => {
|
|
@@ -47052,6 +47060,8 @@ var streamingIndicatorInterval = null;
|
|
|
47052
47060
|
var streamingIndicatorFrame = 0;
|
|
47053
47061
|
var STREAMING_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
47054
47062
|
var getTerminalWidth2 = () => process.stdout.columns || 80;
|
|
47063
|
+
var MAX_STREAMING_CODE_LINES = 50;
|
|
47064
|
+
var STREAMING_CODE_HEAD_LINES = 40;
|
|
47055
47065
|
function startStreamingIndicator() {
|
|
47056
47066
|
if (streamingIndicatorActive) return;
|
|
47057
47067
|
streamingIndicatorActive = true;
|
|
@@ -47375,11 +47385,17 @@ function renderSimpleCodeBlock(lang, lines, blockId) {
|
|
|
47375
47385
|
const isDiff = lang === "diff" || !lang && looksLikeDiff(lines);
|
|
47376
47386
|
const title = lang || "Code";
|
|
47377
47387
|
console.log(chalk2.dim(`${title} \xB7 #${blockId}`));
|
|
47388
|
+
let displayLines = lines;
|
|
47389
|
+
let truncatedCount = 0;
|
|
47390
|
+
if (!isDiff && lines.length > MAX_STREAMING_CODE_LINES) {
|
|
47391
|
+
displayLines = lines.slice(0, STREAMING_CODE_HEAD_LINES);
|
|
47392
|
+
truncatedCount = lines.length - STREAMING_CODE_HEAD_LINES;
|
|
47393
|
+
}
|
|
47378
47394
|
const bgDel = chalk2.bgRgb(80, 20, 20);
|
|
47379
47395
|
const bgAdd = chalk2.bgRgb(20, 60, 20);
|
|
47380
47396
|
let oldLineNo = 0;
|
|
47381
47397
|
let newLineNo = 0;
|
|
47382
|
-
for (const line of
|
|
47398
|
+
for (const line of displayLines) {
|
|
47383
47399
|
if (isDiff) {
|
|
47384
47400
|
const hunkMatch = line.match(/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
|
|
47385
47401
|
if (hunkMatch) {
|
|
@@ -47407,6 +47423,9 @@ function renderSimpleCodeBlock(lang, lines, blockId) {
|
|
|
47407
47423
|
}
|
|
47408
47424
|
}
|
|
47409
47425
|
}
|
|
47426
|
+
if (truncatedCount > 0) {
|
|
47427
|
+
console.log(chalk2.dim(` \u2026 ${truncatedCount} more lines \xB7 /copy ${blockId} for full content`));
|
|
47428
|
+
}
|
|
47410
47429
|
console.log(chalk2.dim(` #${blockId} \xB7 /copy ${blockId}`));
|
|
47411
47430
|
}
|
|
47412
47431
|
function formatDiffLineNo(line, oldLineNo, newLineNo) {
|
|
@@ -50058,6 +50077,8 @@ async function executeAgentTurn(session, userMessage, provider, toolRegistry, op
|
|
|
50058
50077
|
const maxIterations = session.config.agent.maxToolIterations;
|
|
50059
50078
|
const toolErrorCounts = /* @__PURE__ */ new Map();
|
|
50060
50079
|
const MAX_CONSECUTIVE_TOOL_ERRORS = 3;
|
|
50080
|
+
const ITERATION_LIMIT_WARNING_RATIO = 0.75;
|
|
50081
|
+
const ITERATION_LIMIT_SUMMARY_PROMPT = `[System: You have now used all allowed iterations and tool calls are no longer available. Write your final response immediately: (1) briefly state what was completed, (2) describe what still needs to be done, (3) give specific next steps so the user can continue. Be concise and direct.]`;
|
|
50061
50082
|
const INLINE_RESULT_MAX_CHARS = 8e3;
|
|
50062
50083
|
const INLINE_RESULT_HEAD_CHARS = 6500;
|
|
50063
50084
|
const INLINE_RESULT_TAIL_CHARS = 1e3;
|
|
@@ -50072,6 +50093,8 @@ ${tail}`;
|
|
|
50072
50093
|
}
|
|
50073
50094
|
while (iteration < maxIterations) {
|
|
50074
50095
|
iteration++;
|
|
50096
|
+
const isLastIteration = iteration === maxIterations;
|
|
50097
|
+
const iterationTextChunks = [];
|
|
50075
50098
|
if (options.signal?.aborted) {
|
|
50076
50099
|
return abortReturn();
|
|
50077
50100
|
}
|
|
@@ -50099,7 +50122,7 @@ ${tail}`;
|
|
|
50099
50122
|
}
|
|
50100
50123
|
responseContent += chunk.text;
|
|
50101
50124
|
finalContent += chunk.text;
|
|
50102
|
-
|
|
50125
|
+
iterationTextChunks.push(chunk);
|
|
50103
50126
|
}
|
|
50104
50127
|
if (chunk.type === "tool_use_start" && chunk.toolCall) {
|
|
50105
50128
|
flushLineBuffer();
|
|
@@ -50176,6 +50199,11 @@ ${tail}`;
|
|
|
50176
50199
|
error: errorMsg
|
|
50177
50200
|
};
|
|
50178
50201
|
}
|
|
50202
|
+
if (collectedToolCalls.length === 0) {
|
|
50203
|
+
for (const bufferedChunk of iterationTextChunks) {
|
|
50204
|
+
options.onStream?.(bufferedChunk);
|
|
50205
|
+
}
|
|
50206
|
+
}
|
|
50179
50207
|
const inputText = messages.map((m) => {
|
|
50180
50208
|
if (typeof m.content === "string") return m.content;
|
|
50181
50209
|
try {
|
|
@@ -50351,10 +50379,20 @@ ${tail}`;
|
|
|
50351
50379
|
});
|
|
50352
50380
|
const declineReason = declinedTools.get(toolCall.id);
|
|
50353
50381
|
if (declineReason) {
|
|
50382
|
+
let skipContent;
|
|
50383
|
+
if (declineReason === "User declined") {
|
|
50384
|
+
skipContent = "The user explicitly declined this tool call. You MUST find a different approach \u2014 do not retry the same action or parameters.";
|
|
50385
|
+
} else if (declineReason.toLowerCase().includes("timeout") || declineReason.toLowerCase().includes("timed out")) {
|
|
50386
|
+
skipContent = `Tool execution timed out: ${declineReason}. Try a simpler or faster alternative, or break the task into smaller steps.`;
|
|
50387
|
+
} else if (declineReason.toLowerCase().includes("abort")) {
|
|
50388
|
+
skipContent = "Tool execution was cancelled.";
|
|
50389
|
+
} else {
|
|
50390
|
+
skipContent = `Tool execution was skipped: ${declineReason}`;
|
|
50391
|
+
}
|
|
50354
50392
|
toolResults.push({
|
|
50355
50393
|
type: "tool_result",
|
|
50356
50394
|
tool_use_id: toolCall.id,
|
|
50357
|
-
content:
|
|
50395
|
+
content: skipContent,
|
|
50358
50396
|
is_error: true
|
|
50359
50397
|
});
|
|
50360
50398
|
continue;
|
|
@@ -50408,6 +50446,28 @@ ${tail}`;
|
|
|
50408
50446
|
}
|
|
50409
50447
|
}
|
|
50410
50448
|
}
|
|
50449
|
+
if (toolResults.length > 0) {
|
|
50450
|
+
const warningThreshold = Math.ceil(maxIterations * ITERATION_LIMIT_WARNING_RATIO);
|
|
50451
|
+
const lastIdx = toolResults.length - 1;
|
|
50452
|
+
const last = toolResults[lastIdx];
|
|
50453
|
+
if (isLastIteration && !stuckInErrorLoop) {
|
|
50454
|
+
toolResults[lastIdx] = {
|
|
50455
|
+
...last,
|
|
50456
|
+
content: typeof last.content === "string" ? last.content + `
|
|
50457
|
+
|
|
50458
|
+
${ITERATION_LIMIT_SUMMARY_PROMPT}` : ITERATION_LIMIT_SUMMARY_PROMPT
|
|
50459
|
+
};
|
|
50460
|
+
} else if (iteration === warningThreshold) {
|
|
50461
|
+
const remaining = maxIterations - iteration;
|
|
50462
|
+
const warning = `
|
|
50463
|
+
|
|
50464
|
+
[System: Iteration budget warning \u2014 ${iteration} of ${maxIterations} iterations used, ${remaining} remaining. Begin wrapping up your task. Prioritize the most critical remaining steps.]`;
|
|
50465
|
+
toolResults[lastIdx] = {
|
|
50466
|
+
...last,
|
|
50467
|
+
content: typeof last.content === "string" ? last.content + warning : warning
|
|
50468
|
+
};
|
|
50469
|
+
}
|
|
50470
|
+
}
|
|
50411
50471
|
const assistantContent = response.content ? [{ type: "text", text: response.content }, ...toolUses] : toolUses;
|
|
50412
50472
|
addMessage(session, {
|
|
50413
50473
|
role: "assistant",
|
|
@@ -50452,14 +50512,38 @@ ${tail}`;
|
|
|
50452
50512
|
}
|
|
50453
50513
|
break;
|
|
50454
50514
|
}
|
|
50455
|
-
|
|
50456
|
-
|
|
50457
|
-
|
|
50515
|
+
if (isLastIteration && toolResults.length > 0) {
|
|
50516
|
+
let summaryThinkingEnded = false;
|
|
50517
|
+
options.onThinkingStart?.();
|
|
50518
|
+
try {
|
|
50519
|
+
const finalMessages = getConversationContext(session, toolRegistry);
|
|
50520
|
+
for await (const chunk of provider.streamWithTools(finalMessages, {
|
|
50521
|
+
tools: [],
|
|
50522
|
+
maxTokens: session.config.provider.maxTokens,
|
|
50523
|
+
signal: options.signal
|
|
50524
|
+
})) {
|
|
50525
|
+
if (options.signal?.aborted) break;
|
|
50526
|
+
if (chunk.type === "text" && chunk.text) {
|
|
50527
|
+
if (!summaryThinkingEnded) {
|
|
50528
|
+
options.onThinkingEnd?.();
|
|
50529
|
+
summaryThinkingEnded = true;
|
|
50530
|
+
}
|
|
50531
|
+
finalContent += chunk.text;
|
|
50532
|
+
options.onStream?.(chunk);
|
|
50533
|
+
}
|
|
50534
|
+
if (chunk.type === "done") break;
|
|
50535
|
+
}
|
|
50536
|
+
} catch {
|
|
50537
|
+
const notice = `
|
|
50458
50538
|
|
|
50459
|
-
|
|
50460
|
-
|
|
50461
|
-
|
|
50462
|
-
|
|
50539
|
+
I have reached the maximum iteration limit (${maxIterations}). The task may be incomplete. Type "continue" to give me more iterations, or describe what you'd like me to focus on next.`;
|
|
50540
|
+
finalContent += notice;
|
|
50541
|
+
options.onStream?.({ type: "text", text: notice });
|
|
50542
|
+
} finally {
|
|
50543
|
+
if (!summaryThinkingEnded) options.onThinkingEnd?.();
|
|
50544
|
+
}
|
|
50545
|
+
break;
|
|
50546
|
+
}
|
|
50463
50547
|
}
|
|
50464
50548
|
options.onStream?.({ type: "done" });
|
|
50465
50549
|
return {
|