@corbat-tech/coco 1.5.0 → 1.6.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 +329 -39
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +266 -22
- package/dist/index.js.map +1 -1
- package/package.json +23 -20
- package/README.old.md +0 -310
package/dist/cli/index.js
CHANGED
|
@@ -19,6 +19,7 @@ import { fileURLToPath, URL as URL$1 } from 'url';
|
|
|
19
19
|
import JSON5 from 'json5';
|
|
20
20
|
import Anthropic from '@anthropic-ai/sdk';
|
|
21
21
|
import OpenAI from 'openai';
|
|
22
|
+
import { jsonrepair } from 'jsonrepair';
|
|
22
23
|
import * as http from 'http';
|
|
23
24
|
import { execFile, exec, execSync, execFileSync, spawn } from 'child_process';
|
|
24
25
|
import { promisify } from 'util';
|
|
@@ -981,6 +982,71 @@ var init_allow_path_prompt = __esm({
|
|
|
981
982
|
init_allowed_paths();
|
|
982
983
|
}
|
|
983
984
|
});
|
|
985
|
+
|
|
986
|
+
// src/tools/utils/heartbeat.ts
|
|
987
|
+
var heartbeat_exports = {};
|
|
988
|
+
__export(heartbeat_exports, {
|
|
989
|
+
CommandHeartbeat: () => CommandHeartbeat
|
|
990
|
+
});
|
|
991
|
+
var CommandHeartbeat;
|
|
992
|
+
var init_heartbeat = __esm({
|
|
993
|
+
"src/tools/utils/heartbeat.ts"() {
|
|
994
|
+
CommandHeartbeat = class {
|
|
995
|
+
startTime = 0;
|
|
996
|
+
lastActivityTime = 0;
|
|
997
|
+
updateInterval = null;
|
|
998
|
+
warnThreshold = 30;
|
|
999
|
+
// seconds
|
|
1000
|
+
updateIntervalSeconds = 10;
|
|
1001
|
+
// seconds
|
|
1002
|
+
callbacks;
|
|
1003
|
+
constructor(callbacks = {}) {
|
|
1004
|
+
this.callbacks = callbacks;
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* Start monitoring - begins periodic updates and silence warnings
|
|
1008
|
+
*/
|
|
1009
|
+
start() {
|
|
1010
|
+
this.startTime = Date.now();
|
|
1011
|
+
this.lastActivityTime = Date.now();
|
|
1012
|
+
this.updateInterval = setInterval(() => {
|
|
1013
|
+
const stats = this.getStats();
|
|
1014
|
+
this.callbacks.onUpdate?.(stats);
|
|
1015
|
+
if (stats.silentSeconds >= this.warnThreshold) {
|
|
1016
|
+
this.callbacks.onWarn?.(`\u26A0\uFE0F Command silent for ${stats.silentSeconds}s`);
|
|
1017
|
+
}
|
|
1018
|
+
}, this.updateIntervalSeconds * 1e3);
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Register activity - call this when command produces output
|
|
1022
|
+
* Resets the silence timer
|
|
1023
|
+
*/
|
|
1024
|
+
activity() {
|
|
1025
|
+
this.lastActivityTime = Date.now();
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1028
|
+
* Stop monitoring - clears periodic interval
|
|
1029
|
+
* Should be called in finally{} block to ensure cleanup
|
|
1030
|
+
*/
|
|
1031
|
+
stop() {
|
|
1032
|
+
if (this.updateInterval) {
|
|
1033
|
+
clearInterval(this.updateInterval);
|
|
1034
|
+
this.updateInterval = null;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Get current heartbeat statistics
|
|
1039
|
+
*/
|
|
1040
|
+
getStats() {
|
|
1041
|
+
const now = Date.now();
|
|
1042
|
+
return {
|
|
1043
|
+
elapsedSeconds: Math.floor((now - this.startTime) / 1e3),
|
|
1044
|
+
silentSeconds: Math.floor((now - this.lastActivityTime) / 1e3)
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
});
|
|
984
1050
|
function isEnvVarSafe(name) {
|
|
985
1051
|
if (SAFE_ENV_VARS.has(name)) {
|
|
986
1052
|
return true;
|
|
@@ -1117,23 +1183,50 @@ Examples:
|
|
|
1117
1183
|
}
|
|
1118
1184
|
const startTime = performance.now();
|
|
1119
1185
|
const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS;
|
|
1186
|
+
const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
|
|
1187
|
+
const heartbeat = new CommandHeartbeat2({
|
|
1188
|
+
onUpdate: (stats) => {
|
|
1189
|
+
if (stats.elapsedSeconds > 10) {
|
|
1190
|
+
process.stderr.write(`\r\u23F1\uFE0F ${stats.elapsedSeconds}s elapsed`);
|
|
1191
|
+
}
|
|
1192
|
+
},
|
|
1193
|
+
onWarn: (message) => {
|
|
1194
|
+
process.stderr.write(`
|
|
1195
|
+
${message}
|
|
1196
|
+
`);
|
|
1197
|
+
}
|
|
1198
|
+
});
|
|
1120
1199
|
try {
|
|
1200
|
+
heartbeat.start();
|
|
1121
1201
|
const options = {
|
|
1122
1202
|
cwd: cwd ?? process.cwd(),
|
|
1123
1203
|
timeout: timeoutMs,
|
|
1124
1204
|
env: { ...process.env, ...env2 },
|
|
1125
1205
|
shell: true,
|
|
1126
1206
|
reject: false,
|
|
1207
|
+
buffer: false,
|
|
1208
|
+
// Enable streaming
|
|
1127
1209
|
maxBuffer: MAX_OUTPUT_SIZE
|
|
1128
1210
|
};
|
|
1129
|
-
const
|
|
1211
|
+
const subprocess = execa(command, options);
|
|
1212
|
+
let stdoutBuffer = "";
|
|
1213
|
+
let stderrBuffer = "";
|
|
1214
|
+
subprocess.stdout?.on("data", (chunk) => {
|
|
1215
|
+
const text11 = chunk.toString();
|
|
1216
|
+
stdoutBuffer += text11;
|
|
1217
|
+
process.stdout.write(text11);
|
|
1218
|
+
heartbeat.activity();
|
|
1219
|
+
});
|
|
1220
|
+
subprocess.stderr?.on("data", (chunk) => {
|
|
1221
|
+
const text11 = chunk.toString();
|
|
1222
|
+
stderrBuffer += text11;
|
|
1223
|
+
process.stderr.write(text11);
|
|
1224
|
+
heartbeat.activity();
|
|
1225
|
+
});
|
|
1226
|
+
const result = await subprocess;
|
|
1130
1227
|
return {
|
|
1131
|
-
stdout: truncateOutput(
|
|
1132
|
-
|
|
1133
|
-
),
|
|
1134
|
-
stderr: truncateOutput(
|
|
1135
|
-
typeof result.stderr === "string" ? result.stderr : String(result.stderr ?? "")
|
|
1136
|
-
),
|
|
1228
|
+
stdout: truncateOutput(stdoutBuffer),
|
|
1229
|
+
stderr: truncateOutput(stderrBuffer),
|
|
1137
1230
|
exitCode: result.exitCode ?? 0,
|
|
1138
1231
|
duration: performance.now() - startTime
|
|
1139
1232
|
};
|
|
@@ -1148,6 +1241,9 @@ Examples:
|
|
|
1148
1241
|
`Command execution failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1149
1242
|
{ tool: "bash_exec", cause: error instanceof Error ? error : void 0 }
|
|
1150
1243
|
);
|
|
1244
|
+
} finally {
|
|
1245
|
+
heartbeat.stop();
|
|
1246
|
+
process.stderr.write("\r \r");
|
|
1151
1247
|
}
|
|
1152
1248
|
}
|
|
1153
1249
|
});
|
|
@@ -6191,8 +6287,10 @@ var OpenAIProvider = class {
|
|
|
6191
6287
|
const timeoutInterval = setInterval(checkTimeout, 5e3);
|
|
6192
6288
|
try {
|
|
6193
6289
|
for await (const chunk of stream) {
|
|
6194
|
-
lastActivityTime = Date.now();
|
|
6195
6290
|
const delta = chunk.choices[0]?.delta;
|
|
6291
|
+
if (delta?.content || delta?.tool_calls) {
|
|
6292
|
+
lastActivityTime = Date.now();
|
|
6293
|
+
}
|
|
6196
6294
|
if (delta?.content) {
|
|
6197
6295
|
yield { type: "text", text: delta.content };
|
|
6198
6296
|
}
|
|
@@ -6238,10 +6336,20 @@ var OpenAIProvider = class {
|
|
|
6238
6336
|
let input = {};
|
|
6239
6337
|
try {
|
|
6240
6338
|
input = builder.arguments ? JSON.parse(builder.arguments) : {};
|
|
6241
|
-
} catch {
|
|
6339
|
+
} catch (error) {
|
|
6242
6340
|
console.warn(
|
|
6243
|
-
`[OpenAI] Failed to parse tool call arguments: ${builder.arguments?.slice(0, 100)}`
|
|
6341
|
+
`[OpenAI] Failed to parse tool call arguments for ${builder.name}: ${builder.arguments?.slice(0, 100)}`
|
|
6244
6342
|
);
|
|
6343
|
+
try {
|
|
6344
|
+
if (builder.arguments) {
|
|
6345
|
+
const repaired = jsonrepair(builder.arguments);
|
|
6346
|
+
input = JSON.parse(repaired);
|
|
6347
|
+
console.log(`[OpenAI] \u2713 Successfully repaired JSON for ${builder.name}`);
|
|
6348
|
+
}
|
|
6349
|
+
} catch (repairError) {
|
|
6350
|
+
console.error(`[OpenAI] Cannot repair JSON for ${builder.name}, using empty object`);
|
|
6351
|
+
console.error(`[OpenAI] Original error:`, error);
|
|
6352
|
+
}
|
|
6245
6353
|
}
|
|
6246
6354
|
yield {
|
|
6247
6355
|
type: "tool_use_end",
|
|
@@ -10601,14 +10709,42 @@ function generateToolCatalog(registry) {
|
|
|
10601
10709
|
}
|
|
10602
10710
|
var COCO_SYSTEM_PROMPT = `You are Corbat-Coco, an autonomous coding assistant with an extensive toolkit.
|
|
10603
10711
|
|
|
10604
|
-
##
|
|
10712
|
+
## YOUR PRIMARY DIRECTIVE: EXECUTE, DON'T TALK ABOUT EXECUTING
|
|
10713
|
+
|
|
10714
|
+
\u{1F6A8} **CRITICAL - READ THIS FIRST** \u{1F6A8}
|
|
10715
|
+
YOU ARE AN EXECUTION AGENT, NOT A CONVERSATIONAL ASSISTANT.
|
|
10716
|
+
|
|
10717
|
+
**WRONG BEHAVIOR (Never do this):**
|
|
10718
|
+
\u274C "I'll create a file called hello.js with a function..."
|
|
10719
|
+
\u274C "I created hello.js with the following code..."
|
|
10720
|
+
\u274C "Here's what the file would look like..."
|
|
10721
|
+
\u274C Showing code blocks without calling write_file tool
|
|
10722
|
+
|
|
10723
|
+
**CORRECT BEHAVIOR (Always do this):**
|
|
10724
|
+
\u2705 Immediately call write_file tool with the code
|
|
10725
|
+
\u2705 Then say "Created hello.js with greeting function"
|
|
10726
|
+
\u2705 TOOLS FIRST, then brief confirmation
|
|
10727
|
+
|
|
10728
|
+
**Core Principle: USE TOOLS, DON'T DESCRIBE**
|
|
10729
|
+
\u26A0\uFE0F CRITICAL: You MUST use your tools to perform actions. NEVER just describe what you would do or claim you did something without actually calling a tool.
|
|
10605
10730
|
|
|
10606
|
-
|
|
10607
|
-
|
|
10608
|
-
|
|
10609
|
-
|
|
10610
|
-
|
|
10611
|
-
|
|
10731
|
+
**Tool Calling is MANDATORY:**
|
|
10732
|
+
- User says "create a file" \u2192 CALL write_file tool FIRST (don't show code, don't explain, just CALL THE TOOL)
|
|
10733
|
+
- User says "search the web" \u2192 CALL web_search tool FIRST (don't describe what you would search for)
|
|
10734
|
+
- User says "run tests" \u2192 CALL bash_exec tool FIRST (don't say you ran them, actually run them)
|
|
10735
|
+
- EVERY action requires a TOOL CALL. Text responses are ONLY for brief confirmations AFTER tools execute.
|
|
10736
|
+
|
|
10737
|
+
**Execution Process:**
|
|
10738
|
+
1. **Analyze**: Understand what the user wants (in your head, don't output this)
|
|
10739
|
+
2. **Execute**: IMMEDIATELY CALL THE APPROPRIATE TOOLS (this is mandatory, not optional)
|
|
10740
|
+
3. **Respond**: Brief confirmation of what was done (AFTER tools executed)
|
|
10741
|
+
|
|
10742
|
+
**Critical Rules:**
|
|
10743
|
+
- User says "create X with Y" \u2192 Immediately call write_file/edit_file tool, no discussion
|
|
10744
|
+
- If a task needs data you don't have, fetch it with web_search/web_fetch FIRST, THEN complete the task with other tools
|
|
10745
|
+
- Never ask "should I do this?" or "do you want me to...?" - JUST DO IT (with tools)
|
|
10746
|
+
- If you don't call tools, you didn't do the task - showing code is NOT the same as creating files
|
|
10747
|
+
- NEVER show code blocks as examples - ALWAYS write them to files with tools
|
|
10612
10748
|
|
|
10613
10749
|
**IMPORTANT**: You have many tools beyond basic file/bash/git. Before answering "I can't do that", check if any of your tools can help. For example:
|
|
10614
10750
|
- Need information from the internet? Use **web_search** and **web_fetch**
|
|
@@ -10626,13 +10762,19 @@ When the user asks you to do something, follow this process:
|
|
|
10626
10762
|
{TOOL_CATALOG}
|
|
10627
10763
|
|
|
10628
10764
|
## Guidelines
|
|
10629
|
-
- Be
|
|
10630
|
-
-
|
|
10631
|
-
- Always verify
|
|
10632
|
-
-
|
|
10633
|
-
-
|
|
10765
|
+
- **Be action-oriented**: Execute tasks immediately without asking for confirmation
|
|
10766
|
+
- **Multi-step tasks**: Chain tools together to complete the full request
|
|
10767
|
+
- **Always verify**: Read files after editing, run tests after changes
|
|
10768
|
+
- **Don't present options**: If the user says "create X", create it with reasonable defaults
|
|
10769
|
+
- **Don't ask "should I..."**: The user already told you what to do by making the request
|
|
10770
|
+
- **Combine tools**: Use web_search + write_file, bash + read_file, etc. to complete tasks fully
|
|
10634
10771
|
- **Never** add "Co-Authored-By", "Generated by", or any AI attribution to commits, code comments, documentation, or PR descriptions. All output must read as if written by the developer.
|
|
10635
10772
|
|
|
10773
|
+
**Example Flows:**
|
|
10774
|
+
- "Create an HTML with weather data" \u2192 web_search for weather \u2192 write_file with HTML \u2192 DONE
|
|
10775
|
+
- "Add tests for function X" \u2192 read_file to see X \u2192 write_file with tests \u2192 bash to run tests \u2192 DONE
|
|
10776
|
+
- "Fix the bug in Y" \u2192 read_file to understand \u2192 edit_file to fix \u2192 bash to test \u2192 DONE
|
|
10777
|
+
|
|
10636
10778
|
## File Access
|
|
10637
10779
|
File operations are restricted to the project directory by default.
|
|
10638
10780
|
When you need to access a path outside the project, use the **authorize_path** tool first \u2014 it will ask the user for permission interactively. Once authorized, proceed with the file operation.
|
|
@@ -24325,7 +24467,21 @@ Examples:
|
|
|
24325
24467
|
const projectDir = cwd ?? process.cwd();
|
|
24326
24468
|
const startTime = performance.now();
|
|
24327
24469
|
const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS3;
|
|
24470
|
+
const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
|
|
24471
|
+
const heartbeat = new CommandHeartbeat2({
|
|
24472
|
+
onUpdate: (stats) => {
|
|
24473
|
+
if (stats.elapsedSeconds > 10) {
|
|
24474
|
+
process.stderr.write(`\r\u23F1\uFE0F ${stats.elapsedSeconds}s elapsed`);
|
|
24475
|
+
}
|
|
24476
|
+
},
|
|
24477
|
+
onWarn: (message) => {
|
|
24478
|
+
process.stderr.write(`
|
|
24479
|
+
${message}
|
|
24480
|
+
`);
|
|
24481
|
+
}
|
|
24482
|
+
});
|
|
24328
24483
|
try {
|
|
24484
|
+
heartbeat.start();
|
|
24329
24485
|
const pm = packageManager ?? await detectPackageManager(projectDir);
|
|
24330
24486
|
const cmdArgs = ["run", script];
|
|
24331
24487
|
if (args && args.length > 0) {
|
|
@@ -24336,13 +24492,30 @@ Examples:
|
|
|
24336
24492
|
timeout: timeoutMs,
|
|
24337
24493
|
env: { ...process.env, ...env2 },
|
|
24338
24494
|
reject: false,
|
|
24495
|
+
buffer: false,
|
|
24496
|
+
// Enable streaming
|
|
24339
24497
|
maxBuffer: MAX_OUTPUT_SIZE2
|
|
24340
24498
|
};
|
|
24341
|
-
const
|
|
24499
|
+
const subprocess = execa(pm, cmdArgs, options);
|
|
24500
|
+
let stdoutBuffer = "";
|
|
24501
|
+
let stderrBuffer = "";
|
|
24502
|
+
subprocess.stdout?.on("data", (chunk) => {
|
|
24503
|
+
const text11 = chunk.toString();
|
|
24504
|
+
stdoutBuffer += text11;
|
|
24505
|
+
process.stdout.write(text11);
|
|
24506
|
+
heartbeat.activity();
|
|
24507
|
+
});
|
|
24508
|
+
subprocess.stderr?.on("data", (chunk) => {
|
|
24509
|
+
const text11 = chunk.toString();
|
|
24510
|
+
stderrBuffer += text11;
|
|
24511
|
+
process.stderr.write(text11);
|
|
24512
|
+
heartbeat.activity();
|
|
24513
|
+
});
|
|
24514
|
+
const result = await subprocess;
|
|
24342
24515
|
return {
|
|
24343
24516
|
success: result.exitCode === 0,
|
|
24344
|
-
stdout: truncateOutput2(
|
|
24345
|
-
stderr: truncateOutput2(
|
|
24517
|
+
stdout: truncateOutput2(stdoutBuffer),
|
|
24518
|
+
stderr: truncateOutput2(stderrBuffer),
|
|
24346
24519
|
exitCode: result.exitCode ?? 0,
|
|
24347
24520
|
duration: performance.now() - startTime,
|
|
24348
24521
|
packageManager: pm
|
|
@@ -24358,6 +24531,9 @@ Examples:
|
|
|
24358
24531
|
`Failed to run script '${script}': ${error instanceof Error ? error.message : String(error)}`,
|
|
24359
24532
|
{ tool: "run_script", cause: error instanceof Error ? error : void 0 }
|
|
24360
24533
|
);
|
|
24534
|
+
} finally {
|
|
24535
|
+
heartbeat.stop();
|
|
24536
|
+
process.stderr.write("\r \r");
|
|
24361
24537
|
}
|
|
24362
24538
|
}
|
|
24363
24539
|
});
|
|
@@ -24383,7 +24559,21 @@ Examples:
|
|
|
24383
24559
|
const projectDir = cwd ?? process.cwd();
|
|
24384
24560
|
const startTime = performance.now();
|
|
24385
24561
|
const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS3;
|
|
24562
|
+
const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
|
|
24563
|
+
const heartbeat = new CommandHeartbeat2({
|
|
24564
|
+
onUpdate: (stats) => {
|
|
24565
|
+
if (stats.elapsedSeconds > 10) {
|
|
24566
|
+
process.stderr.write(`\r\u23F1\uFE0F ${stats.elapsedSeconds}s elapsed`);
|
|
24567
|
+
}
|
|
24568
|
+
},
|
|
24569
|
+
onWarn: (message) => {
|
|
24570
|
+
process.stderr.write(`
|
|
24571
|
+
${message}
|
|
24572
|
+
`);
|
|
24573
|
+
}
|
|
24574
|
+
});
|
|
24386
24575
|
try {
|
|
24576
|
+
heartbeat.start();
|
|
24387
24577
|
const pm = packageManager ?? await detectPackageManager(projectDir);
|
|
24388
24578
|
let cmdArgs;
|
|
24389
24579
|
if (packages && packages.length > 0) {
|
|
@@ -24423,13 +24613,30 @@ Examples:
|
|
|
24423
24613
|
cwd: projectDir,
|
|
24424
24614
|
timeout: timeoutMs,
|
|
24425
24615
|
reject: false,
|
|
24616
|
+
buffer: false,
|
|
24617
|
+
// Enable streaming
|
|
24426
24618
|
maxBuffer: MAX_OUTPUT_SIZE2
|
|
24427
24619
|
};
|
|
24428
|
-
const
|
|
24620
|
+
const subprocess = execa(pm, cmdArgs, options);
|
|
24621
|
+
let stdoutBuffer = "";
|
|
24622
|
+
let stderrBuffer = "";
|
|
24623
|
+
subprocess.stdout?.on("data", (chunk) => {
|
|
24624
|
+
const text11 = chunk.toString();
|
|
24625
|
+
stdoutBuffer += text11;
|
|
24626
|
+
process.stdout.write(text11);
|
|
24627
|
+
heartbeat.activity();
|
|
24628
|
+
});
|
|
24629
|
+
subprocess.stderr?.on("data", (chunk) => {
|
|
24630
|
+
const text11 = chunk.toString();
|
|
24631
|
+
stderrBuffer += text11;
|
|
24632
|
+
process.stderr.write(text11);
|
|
24633
|
+
heartbeat.activity();
|
|
24634
|
+
});
|
|
24635
|
+
const result = await subprocess;
|
|
24429
24636
|
return {
|
|
24430
24637
|
success: result.exitCode === 0,
|
|
24431
|
-
stdout: truncateOutput2(
|
|
24432
|
-
stderr: truncateOutput2(
|
|
24638
|
+
stdout: truncateOutput2(stdoutBuffer),
|
|
24639
|
+
stderr: truncateOutput2(stderrBuffer),
|
|
24433
24640
|
exitCode: result.exitCode ?? 0,
|
|
24434
24641
|
duration: performance.now() - startTime,
|
|
24435
24642
|
packageManager: pm
|
|
@@ -24445,6 +24652,9 @@ Examples:
|
|
|
24445
24652
|
`Failed to install dependencies: ${error instanceof Error ? error.message : String(error)}`,
|
|
24446
24653
|
{ tool: "install_deps", cause: error instanceof Error ? error : void 0 }
|
|
24447
24654
|
);
|
|
24655
|
+
} finally {
|
|
24656
|
+
heartbeat.stop();
|
|
24657
|
+
process.stderr.write("\r \r");
|
|
24448
24658
|
}
|
|
24449
24659
|
}
|
|
24450
24660
|
});
|
|
@@ -24469,12 +24679,26 @@ Examples:
|
|
|
24469
24679
|
const projectDir = cwd ?? process.cwd();
|
|
24470
24680
|
const startTime = performance.now();
|
|
24471
24681
|
const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS3;
|
|
24682
|
+
const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
|
|
24683
|
+
const heartbeat = new CommandHeartbeat2({
|
|
24684
|
+
onUpdate: (stats) => {
|
|
24685
|
+
if (stats.elapsedSeconds > 10) {
|
|
24686
|
+
process.stderr.write(`\r\u23F1\uFE0F ${stats.elapsedSeconds}s elapsed`);
|
|
24687
|
+
}
|
|
24688
|
+
},
|
|
24689
|
+
onWarn: (message) => {
|
|
24690
|
+
process.stderr.write(`
|
|
24691
|
+
${message}
|
|
24692
|
+
`);
|
|
24693
|
+
}
|
|
24694
|
+
});
|
|
24472
24695
|
try {
|
|
24473
24696
|
try {
|
|
24474
24697
|
await fs23__default.access(path20__default.join(projectDir, "Makefile"));
|
|
24475
24698
|
} catch {
|
|
24476
24699
|
throw new ToolError("No Makefile found in directory", { tool: "make" });
|
|
24477
24700
|
}
|
|
24701
|
+
heartbeat.start();
|
|
24478
24702
|
const cmdArgs = [];
|
|
24479
24703
|
if (target) {
|
|
24480
24704
|
cmdArgs.push(...target.split(/\s+/));
|
|
@@ -24487,13 +24711,30 @@ Examples:
|
|
|
24487
24711
|
timeout: timeoutMs,
|
|
24488
24712
|
env: { ...process.env, ...env2 },
|
|
24489
24713
|
reject: false,
|
|
24714
|
+
buffer: false,
|
|
24715
|
+
// Enable streaming
|
|
24490
24716
|
maxBuffer: MAX_OUTPUT_SIZE2
|
|
24491
24717
|
};
|
|
24492
|
-
const
|
|
24718
|
+
const subprocess = execa("make", cmdArgs, options);
|
|
24719
|
+
let stdoutBuffer = "";
|
|
24720
|
+
let stderrBuffer = "";
|
|
24721
|
+
subprocess.stdout?.on("data", (chunk) => {
|
|
24722
|
+
const text11 = chunk.toString();
|
|
24723
|
+
stdoutBuffer += text11;
|
|
24724
|
+
process.stdout.write(text11);
|
|
24725
|
+
heartbeat.activity();
|
|
24726
|
+
});
|
|
24727
|
+
subprocess.stderr?.on("data", (chunk) => {
|
|
24728
|
+
const text11 = chunk.toString();
|
|
24729
|
+
stderrBuffer += text11;
|
|
24730
|
+
process.stderr.write(text11);
|
|
24731
|
+
heartbeat.activity();
|
|
24732
|
+
});
|
|
24733
|
+
const result = await subprocess;
|
|
24493
24734
|
return {
|
|
24494
24735
|
success: result.exitCode === 0,
|
|
24495
|
-
stdout: truncateOutput2(
|
|
24496
|
-
stderr: truncateOutput2(
|
|
24736
|
+
stdout: truncateOutput2(stdoutBuffer),
|
|
24737
|
+
stderr: truncateOutput2(stderrBuffer),
|
|
24497
24738
|
exitCode: result.exitCode ?? 0,
|
|
24498
24739
|
duration: performance.now() - startTime
|
|
24499
24740
|
};
|
|
@@ -24509,6 +24750,9 @@ Examples:
|
|
|
24509
24750
|
`Make failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
24510
24751
|
{ tool: "make", cause: error instanceof Error ? error : void 0 }
|
|
24511
24752
|
);
|
|
24753
|
+
} finally {
|
|
24754
|
+
heartbeat.stop();
|
|
24755
|
+
process.stderr.write("\r \r");
|
|
24512
24756
|
}
|
|
24513
24757
|
}
|
|
24514
24758
|
});
|
|
@@ -24534,7 +24778,21 @@ Examples:
|
|
|
24534
24778
|
const projectDir = cwd ?? process.cwd();
|
|
24535
24779
|
const startTime = performance.now();
|
|
24536
24780
|
const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS3;
|
|
24781
|
+
const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
|
|
24782
|
+
const heartbeat = new CommandHeartbeat2({
|
|
24783
|
+
onUpdate: (stats) => {
|
|
24784
|
+
if (stats.elapsedSeconds > 10) {
|
|
24785
|
+
process.stderr.write(`\r\u23F1\uFE0F ${stats.elapsedSeconds}s elapsed`);
|
|
24786
|
+
}
|
|
24787
|
+
},
|
|
24788
|
+
onWarn: (message) => {
|
|
24789
|
+
process.stderr.write(`
|
|
24790
|
+
${message}
|
|
24791
|
+
`);
|
|
24792
|
+
}
|
|
24793
|
+
});
|
|
24537
24794
|
try {
|
|
24795
|
+
heartbeat.start();
|
|
24538
24796
|
const cmdArgs = [];
|
|
24539
24797
|
if (project) {
|
|
24540
24798
|
cmdArgs.push("--project", project);
|
|
@@ -24552,13 +24810,30 @@ Examples:
|
|
|
24552
24810
|
cwd: projectDir,
|
|
24553
24811
|
timeout: timeoutMs,
|
|
24554
24812
|
reject: false,
|
|
24813
|
+
buffer: false,
|
|
24814
|
+
// Enable streaming
|
|
24555
24815
|
maxBuffer: MAX_OUTPUT_SIZE2
|
|
24556
24816
|
};
|
|
24557
|
-
const
|
|
24817
|
+
const subprocess = execa("npx", ["tsc", ...cmdArgs], options);
|
|
24818
|
+
let stdoutBuffer = "";
|
|
24819
|
+
let stderrBuffer = "";
|
|
24820
|
+
subprocess.stdout?.on("data", (chunk) => {
|
|
24821
|
+
const text11 = chunk.toString();
|
|
24822
|
+
stdoutBuffer += text11;
|
|
24823
|
+
process.stdout.write(text11);
|
|
24824
|
+
heartbeat.activity();
|
|
24825
|
+
});
|
|
24826
|
+
subprocess.stderr?.on("data", (chunk) => {
|
|
24827
|
+
const text11 = chunk.toString();
|
|
24828
|
+
stderrBuffer += text11;
|
|
24829
|
+
process.stderr.write(text11);
|
|
24830
|
+
heartbeat.activity();
|
|
24831
|
+
});
|
|
24832
|
+
const result = await subprocess;
|
|
24558
24833
|
return {
|
|
24559
24834
|
success: result.exitCode === 0,
|
|
24560
|
-
stdout: truncateOutput2(
|
|
24561
|
-
stderr: truncateOutput2(
|
|
24835
|
+
stdout: truncateOutput2(stdoutBuffer),
|
|
24836
|
+
stderr: truncateOutput2(stderrBuffer),
|
|
24562
24837
|
exitCode: result.exitCode ?? 0,
|
|
24563
24838
|
duration: performance.now() - startTime
|
|
24564
24839
|
};
|
|
@@ -24573,6 +24848,9 @@ Examples:
|
|
|
24573
24848
|
`TypeScript compile failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
24574
24849
|
{ tool: "tsc", cause: error instanceof Error ? error : void 0 }
|
|
24575
24850
|
);
|
|
24851
|
+
} finally {
|
|
24852
|
+
heartbeat.stop();
|
|
24853
|
+
process.stderr.write("\r \r");
|
|
24576
24854
|
}
|
|
24577
24855
|
}
|
|
24578
24856
|
});
|
|
@@ -30442,7 +30720,11 @@ async function startRepl(options = {}) {
|
|
|
30442
30720
|
clearSpinner();
|
|
30443
30721
|
renderToolStart(result2.name, result2.input);
|
|
30444
30722
|
renderToolEnd(result2);
|
|
30445
|
-
|
|
30723
|
+
if (isCocoMode()) {
|
|
30724
|
+
setSpinner("Processing results & checking quality...");
|
|
30725
|
+
} else {
|
|
30726
|
+
setSpinner("Processing...");
|
|
30727
|
+
}
|
|
30446
30728
|
},
|
|
30447
30729
|
onToolSkipped: (tc, reason) => {
|
|
30448
30730
|
clearSpinner();
|
|
@@ -30455,10 +30737,18 @@ async function startRepl(options = {}) {
|
|
|
30455
30737
|
if (!thinkingStartTime) return;
|
|
30456
30738
|
const elapsed = Math.floor((Date.now() - thinkingStartTime) / 1e3);
|
|
30457
30739
|
if (elapsed < 4) return;
|
|
30458
|
-
if (
|
|
30459
|
-
|
|
30460
|
-
|
|
30461
|
-
|
|
30740
|
+
if (isCocoMode()) {
|
|
30741
|
+
if (elapsed < 8) setSpinner("Analyzing request...");
|
|
30742
|
+
else if (elapsed < 15) setSpinner("Running quality checks...");
|
|
30743
|
+
else if (elapsed < 25) setSpinner("Iterating for quality...");
|
|
30744
|
+
else if (elapsed < 40) setSpinner("Verifying implementation...");
|
|
30745
|
+
else setSpinner(`Quality iteration in progress... (${elapsed}s)`);
|
|
30746
|
+
} else {
|
|
30747
|
+
if (elapsed < 8) setSpinner("Analyzing request...");
|
|
30748
|
+
else if (elapsed < 12) setSpinner("Planning approach...");
|
|
30749
|
+
else if (elapsed < 16) setSpinner("Preparing tools...");
|
|
30750
|
+
else setSpinner(`Still working... (${elapsed}s)`);
|
|
30751
|
+
}
|
|
30462
30752
|
}, 2e3);
|
|
30463
30753
|
},
|
|
30464
30754
|
onThinkingEnd: () => {
|