@corbat-tech/coco 1.4.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 +654 -111
- 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
|
@@ -12,13 +12,14 @@ import { z } from 'zod';
|
|
|
12
12
|
import chalk42 from 'chalk';
|
|
13
13
|
import * as p9 from '@clack/prompts';
|
|
14
14
|
import { execa } from 'execa';
|
|
15
|
+
import * as crypto from 'crypto';
|
|
16
|
+
import { randomUUID } from 'crypto';
|
|
15
17
|
import { Command } from 'commander';
|
|
16
18
|
import { fileURLToPath, URL as URL$1 } from 'url';
|
|
17
19
|
import JSON5 from 'json5';
|
|
18
|
-
import * as crypto from 'crypto';
|
|
19
|
-
import { randomUUID } from 'crypto';
|
|
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';
|
|
@@ -448,8 +449,8 @@ __export(trust_store_exports, {
|
|
|
448
449
|
saveTrustStore: () => saveTrustStore,
|
|
449
450
|
updateLastAccessed: () => updateLastAccessed
|
|
450
451
|
});
|
|
451
|
-
async function ensureDir(
|
|
452
|
-
await mkdir(dirname(
|
|
452
|
+
async function ensureDir(path44) {
|
|
453
|
+
await mkdir(dirname(path44), { recursive: true });
|
|
453
454
|
}
|
|
454
455
|
async function loadTrustStore(storePath = TRUST_STORE_PATH) {
|
|
455
456
|
try {
|
|
@@ -527,8 +528,8 @@ function canPerformOperation(store, projectPath, operation) {
|
|
|
527
528
|
};
|
|
528
529
|
return permissions[level]?.includes(operation) ?? false;
|
|
529
530
|
}
|
|
530
|
-
function normalizePath(
|
|
531
|
-
return join(
|
|
531
|
+
function normalizePath(path44) {
|
|
532
|
+
return join(path44);
|
|
532
533
|
}
|
|
533
534
|
function createTrustStore(storePath = TRUST_STORE_PATH) {
|
|
534
535
|
let store = null;
|
|
@@ -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
|
});
|
|
@@ -1260,6 +1356,224 @@ Examples:
|
|
|
1260
1356
|
bashTools = [bashExecTool, bashBackgroundTool, commandExistsTool, getEnvTool];
|
|
1261
1357
|
}
|
|
1262
1358
|
});
|
|
1359
|
+
async function fileExists(filePath) {
|
|
1360
|
+
try {
|
|
1361
|
+
await fs23__default.access(filePath);
|
|
1362
|
+
return true;
|
|
1363
|
+
} catch {
|
|
1364
|
+
return false;
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
var init_files = __esm({
|
|
1368
|
+
"src/utils/files.ts"() {
|
|
1369
|
+
init_errors();
|
|
1370
|
+
}
|
|
1371
|
+
});
|
|
1372
|
+
|
|
1373
|
+
// src/cli/repl/context/stack-detector.ts
|
|
1374
|
+
var stack_detector_exports = {};
|
|
1375
|
+
__export(stack_detector_exports, {
|
|
1376
|
+
detectProjectStack: () => detectProjectStack
|
|
1377
|
+
});
|
|
1378
|
+
async function detectStack(cwd) {
|
|
1379
|
+
if (await fileExists(path20__default.join(cwd, "package.json"))) return "node";
|
|
1380
|
+
if (await fileExists(path20__default.join(cwd, "Cargo.toml"))) return "rust";
|
|
1381
|
+
if (await fileExists(path20__default.join(cwd, "pyproject.toml"))) return "python";
|
|
1382
|
+
if (await fileExists(path20__default.join(cwd, "go.mod"))) return "go";
|
|
1383
|
+
if (await fileExists(path20__default.join(cwd, "pom.xml"))) return "java";
|
|
1384
|
+
if (await fileExists(path20__default.join(cwd, "build.gradle"))) return "java";
|
|
1385
|
+
if (await fileExists(path20__default.join(cwd, "build.gradle.kts"))) return "java";
|
|
1386
|
+
return "unknown";
|
|
1387
|
+
}
|
|
1388
|
+
async function detectPackageManager2(cwd, stack) {
|
|
1389
|
+
if (stack === "rust") return "cargo";
|
|
1390
|
+
if (stack === "python") return "pip";
|
|
1391
|
+
if (stack === "go") return "go";
|
|
1392
|
+
if (stack === "java") {
|
|
1393
|
+
if (await fileExists(path20__default.join(cwd, "build.gradle")) || await fileExists(path20__default.join(cwd, "build.gradle.kts"))) {
|
|
1394
|
+
return "gradle";
|
|
1395
|
+
}
|
|
1396
|
+
if (await fileExists(path20__default.join(cwd, "pom.xml"))) {
|
|
1397
|
+
return "maven";
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
if (stack === "node") {
|
|
1401
|
+
if (await fileExists(path20__default.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
1402
|
+
if (await fileExists(path20__default.join(cwd, "yarn.lock"))) return "yarn";
|
|
1403
|
+
if (await fileExists(path20__default.join(cwd, "bun.lockb"))) return "bun";
|
|
1404
|
+
return "npm";
|
|
1405
|
+
}
|
|
1406
|
+
return null;
|
|
1407
|
+
}
|
|
1408
|
+
async function parsePackageJson(cwd) {
|
|
1409
|
+
const packageJsonPath = path20__default.join(cwd, "package.json");
|
|
1410
|
+
try {
|
|
1411
|
+
const content = await fs23__default.readFile(packageJsonPath, "utf-8");
|
|
1412
|
+
const pkg = JSON.parse(content);
|
|
1413
|
+
const allDeps = {
|
|
1414
|
+
...pkg.dependencies,
|
|
1415
|
+
...pkg.devDependencies
|
|
1416
|
+
};
|
|
1417
|
+
const frameworks = [];
|
|
1418
|
+
if (allDeps.react) frameworks.push("React");
|
|
1419
|
+
if (allDeps.vue) frameworks.push("Vue");
|
|
1420
|
+
if (allDeps["@angular/core"]) frameworks.push("Angular");
|
|
1421
|
+
if (allDeps.next) frameworks.push("Next.js");
|
|
1422
|
+
if (allDeps.nuxt) frameworks.push("Nuxt");
|
|
1423
|
+
if (allDeps.express) frameworks.push("Express");
|
|
1424
|
+
if (allDeps.fastify) frameworks.push("Fastify");
|
|
1425
|
+
if (allDeps.nestjs || allDeps["@nestjs/core"]) frameworks.push("NestJS");
|
|
1426
|
+
const buildTools2 = [];
|
|
1427
|
+
if (allDeps.webpack) buildTools2.push("webpack");
|
|
1428
|
+
if (allDeps.vite) buildTools2.push("vite");
|
|
1429
|
+
if (allDeps.rollup) buildTools2.push("rollup");
|
|
1430
|
+
if (allDeps.tsup) buildTools2.push("tsup");
|
|
1431
|
+
if (allDeps.esbuild) buildTools2.push("esbuild");
|
|
1432
|
+
if (pkg.scripts?.build) buildTools2.push("build");
|
|
1433
|
+
const testingFrameworks = [];
|
|
1434
|
+
if (allDeps.vitest) testingFrameworks.push("vitest");
|
|
1435
|
+
if (allDeps.jest) testingFrameworks.push("jest");
|
|
1436
|
+
if (allDeps.mocha) testingFrameworks.push("mocha");
|
|
1437
|
+
if (allDeps.chai) testingFrameworks.push("chai");
|
|
1438
|
+
if (allDeps["@playwright/test"]) testingFrameworks.push("playwright");
|
|
1439
|
+
if (allDeps.cypress) testingFrameworks.push("cypress");
|
|
1440
|
+
const languages = ["JavaScript"];
|
|
1441
|
+
if (allDeps.typescript || await fileExists(path20__default.join(cwd, "tsconfig.json"))) {
|
|
1442
|
+
languages.push("TypeScript");
|
|
1443
|
+
}
|
|
1444
|
+
return {
|
|
1445
|
+
dependencies: allDeps,
|
|
1446
|
+
frameworks,
|
|
1447
|
+
buildTools: buildTools2,
|
|
1448
|
+
testingFrameworks,
|
|
1449
|
+
languages
|
|
1450
|
+
};
|
|
1451
|
+
} catch {
|
|
1452
|
+
return {
|
|
1453
|
+
dependencies: {},
|
|
1454
|
+
frameworks: [],
|
|
1455
|
+
buildTools: [],
|
|
1456
|
+
testingFrameworks: [],
|
|
1457
|
+
languages: []
|
|
1458
|
+
};
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
async function parsePomXml(cwd) {
|
|
1462
|
+
const pomPath = path20__default.join(cwd, "pom.xml");
|
|
1463
|
+
try {
|
|
1464
|
+
const content = await fs23__default.readFile(pomPath, "utf-8");
|
|
1465
|
+
const dependencies = {};
|
|
1466
|
+
const frameworks = [];
|
|
1467
|
+
const buildTools2 = ["maven"];
|
|
1468
|
+
const testingFrameworks = [];
|
|
1469
|
+
const depRegex = /<groupId>([^<]+)<\/groupId>\s*<artifactId>([^<]+)<\/artifactId>/g;
|
|
1470
|
+
let match;
|
|
1471
|
+
while ((match = depRegex.exec(content)) !== null) {
|
|
1472
|
+
const groupId = match[1];
|
|
1473
|
+
const artifactId = match[2];
|
|
1474
|
+
if (!groupId || !artifactId) continue;
|
|
1475
|
+
const fullName = `${groupId}:${artifactId}`;
|
|
1476
|
+
dependencies[fullName] = "unknown";
|
|
1477
|
+
if (artifactId.includes("spring-boot")) {
|
|
1478
|
+
if (!frameworks.includes("Spring Boot")) frameworks.push("Spring Boot");
|
|
1479
|
+
}
|
|
1480
|
+
if (artifactId.includes("spring-webmvc") || artifactId.includes("spring-web")) {
|
|
1481
|
+
if (!frameworks.includes("Spring MVC")) frameworks.push("Spring MVC");
|
|
1482
|
+
}
|
|
1483
|
+
if (artifactId.includes("hibernate")) {
|
|
1484
|
+
if (!frameworks.includes("Hibernate")) frameworks.push("Hibernate");
|
|
1485
|
+
}
|
|
1486
|
+
if (artifactId === "junit-jupiter" || artifactId === "junit") {
|
|
1487
|
+
if (!testingFrameworks.includes("JUnit")) testingFrameworks.push("JUnit");
|
|
1488
|
+
}
|
|
1489
|
+
if (artifactId === "mockito-core") {
|
|
1490
|
+
if (!testingFrameworks.includes("Mockito")) testingFrameworks.push("Mockito");
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
return { dependencies, frameworks, buildTools: buildTools2, testingFrameworks };
|
|
1494
|
+
} catch {
|
|
1495
|
+
return { dependencies: {}, frameworks: [], buildTools: ["maven"], testingFrameworks: [] };
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
async function parsePyprojectToml(cwd) {
|
|
1499
|
+
const pyprojectPath = path20__default.join(cwd, "pyproject.toml");
|
|
1500
|
+
try {
|
|
1501
|
+
const content = await fs23__default.readFile(pyprojectPath, "utf-8");
|
|
1502
|
+
const dependencies = {};
|
|
1503
|
+
const frameworks = [];
|
|
1504
|
+
const buildTools2 = ["pip"];
|
|
1505
|
+
const testingFrameworks = [];
|
|
1506
|
+
const lines = content.split("\n");
|
|
1507
|
+
for (const line of lines) {
|
|
1508
|
+
const trimmed = line.trim();
|
|
1509
|
+
if (trimmed.match(/^["']?[\w-]+["']?\s*=\s*["'][\^~>=<]+[\d.]+["']/)) {
|
|
1510
|
+
const depMatch = trimmed.match(/^["']?([\w-]+)["']?\s*=\s*["']([\^~>=<]+[\d.]+)["']/);
|
|
1511
|
+
if (depMatch && depMatch[1] && depMatch[2]) {
|
|
1512
|
+
dependencies[depMatch[1]] = depMatch[2];
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
if (trimmed.includes("fastapi")) frameworks.push("FastAPI");
|
|
1516
|
+
if (trimmed.includes("django")) frameworks.push("Django");
|
|
1517
|
+
if (trimmed.includes("flask")) frameworks.push("Flask");
|
|
1518
|
+
if (trimmed.includes("pytest")) testingFrameworks.push("pytest");
|
|
1519
|
+
if (trimmed.includes("unittest")) testingFrameworks.push("unittest");
|
|
1520
|
+
}
|
|
1521
|
+
return { dependencies, frameworks, buildTools: buildTools2, testingFrameworks };
|
|
1522
|
+
} catch {
|
|
1523
|
+
return { dependencies: {}, frameworks: [], buildTools: ["pip"], testingFrameworks: [] };
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
async function detectProjectStack(cwd) {
|
|
1527
|
+
const stack = await detectStack(cwd);
|
|
1528
|
+
const packageManager = await detectPackageManager2(cwd, stack);
|
|
1529
|
+
let dependencies = {};
|
|
1530
|
+
let frameworks = [];
|
|
1531
|
+
let buildTools2 = [];
|
|
1532
|
+
let testingFrameworks = [];
|
|
1533
|
+
let languages = [];
|
|
1534
|
+
if (stack === "node") {
|
|
1535
|
+
const parsed = await parsePackageJson(cwd);
|
|
1536
|
+
dependencies = parsed.dependencies;
|
|
1537
|
+
frameworks = parsed.frameworks;
|
|
1538
|
+
buildTools2 = parsed.buildTools;
|
|
1539
|
+
testingFrameworks = parsed.testingFrameworks;
|
|
1540
|
+
languages = parsed.languages;
|
|
1541
|
+
} else if (stack === "java") {
|
|
1542
|
+
const parsed = await parsePomXml(cwd);
|
|
1543
|
+
dependencies = parsed.dependencies;
|
|
1544
|
+
frameworks = parsed.frameworks;
|
|
1545
|
+
buildTools2 = parsed.buildTools;
|
|
1546
|
+
testingFrameworks = parsed.testingFrameworks;
|
|
1547
|
+
languages = ["Java"];
|
|
1548
|
+
} else if (stack === "python") {
|
|
1549
|
+
const parsed = await parsePyprojectToml(cwd);
|
|
1550
|
+
dependencies = parsed.dependencies;
|
|
1551
|
+
frameworks = parsed.frameworks;
|
|
1552
|
+
buildTools2 = parsed.buildTools;
|
|
1553
|
+
testingFrameworks = parsed.testingFrameworks;
|
|
1554
|
+
languages = ["Python"];
|
|
1555
|
+
} else if (stack === "go") {
|
|
1556
|
+
languages = ["Go"];
|
|
1557
|
+
buildTools2 = ["go"];
|
|
1558
|
+
} else if (stack === "rust") {
|
|
1559
|
+
languages = ["Rust"];
|
|
1560
|
+
buildTools2 = ["cargo"];
|
|
1561
|
+
}
|
|
1562
|
+
return {
|
|
1563
|
+
stack,
|
|
1564
|
+
packageManager,
|
|
1565
|
+
dependencies,
|
|
1566
|
+
frameworks,
|
|
1567
|
+
buildTools: buildTools2,
|
|
1568
|
+
testingFrameworks,
|
|
1569
|
+
languages
|
|
1570
|
+
};
|
|
1571
|
+
}
|
|
1572
|
+
var init_stack_detector = __esm({
|
|
1573
|
+
"src/cli/repl/context/stack-detector.ts"() {
|
|
1574
|
+
init_files();
|
|
1575
|
+
}
|
|
1576
|
+
});
|
|
1263
1577
|
function findPackageJson() {
|
|
1264
1578
|
let dir = dirname(fileURLToPath(import.meta.url));
|
|
1265
1579
|
for (let i = 0; i < 10; i++) {
|
|
@@ -1418,8 +1732,8 @@ Generated by Corbat-Coco v0.1.0
|
|
|
1418
1732
|
|
|
1419
1733
|
// src/cli/commands/init.ts
|
|
1420
1734
|
function registerInitCommand(program2) {
|
|
1421
|
-
program2.command("init").description("Initialize a new Corbat-Coco project").argument("[path]", "Project directory path", ".").option("-t, --template <template>", "Project template to use").option("-y, --yes", "Skip prompts and use defaults").option("--skip-discovery", "Skip the discovery phase (use existing spec)").action(async (
|
|
1422
|
-
await runInit(
|
|
1735
|
+
program2.command("init").description("Initialize a new Corbat-Coco project").argument("[path]", "Project directory path", ".").option("-t, --template <template>", "Project template to use").option("-y, --yes", "Skip prompts and use defaults").option("--skip-discovery", "Skip the discovery phase (use existing spec)").action(async (path44, options) => {
|
|
1736
|
+
await runInit(path44, options);
|
|
1423
1737
|
});
|
|
1424
1738
|
}
|
|
1425
1739
|
async function runInit(projectPath, options) {
|
|
@@ -1498,18 +1812,18 @@ async function gatherProjectInfo() {
|
|
|
1498
1812
|
language
|
|
1499
1813
|
};
|
|
1500
1814
|
}
|
|
1501
|
-
function getDefaultProjectInfo(
|
|
1502
|
-
const name =
|
|
1815
|
+
function getDefaultProjectInfo(path44) {
|
|
1816
|
+
const name = path44 === "." ? "my-project" : path44.split("/").pop() || "my-project";
|
|
1503
1817
|
return {
|
|
1504
1818
|
name,
|
|
1505
1819
|
description: "",
|
|
1506
1820
|
language: "typescript"
|
|
1507
1821
|
};
|
|
1508
1822
|
}
|
|
1509
|
-
async function checkExistingProject(
|
|
1823
|
+
async function checkExistingProject(path44) {
|
|
1510
1824
|
try {
|
|
1511
|
-
const
|
|
1512
|
-
await
|
|
1825
|
+
const fs44 = await import('fs/promises');
|
|
1826
|
+
await fs44.access(`${path44}/.coco`);
|
|
1513
1827
|
return true;
|
|
1514
1828
|
} catch {
|
|
1515
1829
|
return false;
|
|
@@ -5973,8 +6287,10 @@ var OpenAIProvider = class {
|
|
|
5973
6287
|
const timeoutInterval = setInterval(checkTimeout, 5e3);
|
|
5974
6288
|
try {
|
|
5975
6289
|
for await (const chunk of stream) {
|
|
5976
|
-
lastActivityTime = Date.now();
|
|
5977
6290
|
const delta = chunk.choices[0]?.delta;
|
|
6291
|
+
if (delta?.content || delta?.tool_calls) {
|
|
6292
|
+
lastActivityTime = Date.now();
|
|
6293
|
+
}
|
|
5978
6294
|
if (delta?.content) {
|
|
5979
6295
|
yield { type: "text", text: delta.content };
|
|
5980
6296
|
}
|
|
@@ -6020,10 +6336,20 @@ var OpenAIProvider = class {
|
|
|
6020
6336
|
let input = {};
|
|
6021
6337
|
try {
|
|
6022
6338
|
input = builder.arguments ? JSON.parse(builder.arguments) : {};
|
|
6023
|
-
} catch {
|
|
6339
|
+
} catch (error) {
|
|
6024
6340
|
console.warn(
|
|
6025
|
-
`[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)}`
|
|
6026
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
|
+
}
|
|
6027
6353
|
}
|
|
6028
6354
|
yield {
|
|
6029
6355
|
type: "tool_use_end",
|
|
@@ -8368,20 +8694,20 @@ async function createCliPhaseContext(projectPath, _onUserInput) {
|
|
|
8368
8694
|
},
|
|
8369
8695
|
tools: {
|
|
8370
8696
|
file: {
|
|
8371
|
-
async read(
|
|
8372
|
-
const
|
|
8373
|
-
return
|
|
8697
|
+
async read(path44) {
|
|
8698
|
+
const fs44 = await import('fs/promises');
|
|
8699
|
+
return fs44.readFile(path44, "utf-8");
|
|
8374
8700
|
},
|
|
8375
|
-
async write(
|
|
8376
|
-
const
|
|
8701
|
+
async write(path44, content) {
|
|
8702
|
+
const fs44 = await import('fs/promises');
|
|
8377
8703
|
const nodePath = await import('path');
|
|
8378
|
-
await
|
|
8379
|
-
await
|
|
8704
|
+
await fs44.mkdir(nodePath.dirname(path44), { recursive: true });
|
|
8705
|
+
await fs44.writeFile(path44, content, "utf-8");
|
|
8380
8706
|
},
|
|
8381
|
-
async exists(
|
|
8382
|
-
const
|
|
8707
|
+
async exists(path44) {
|
|
8708
|
+
const fs44 = await import('fs/promises');
|
|
8383
8709
|
try {
|
|
8384
|
-
await
|
|
8710
|
+
await fs44.access(path44);
|
|
8385
8711
|
return true;
|
|
8386
8712
|
} catch {
|
|
8387
8713
|
return false;
|
|
@@ -8620,16 +8946,16 @@ async function loadTasks(_options) {
|
|
|
8620
8946
|
];
|
|
8621
8947
|
}
|
|
8622
8948
|
async function checkProjectState() {
|
|
8623
|
-
const
|
|
8949
|
+
const fs44 = await import('fs/promises');
|
|
8624
8950
|
let hasProject = false;
|
|
8625
8951
|
let hasPlan = false;
|
|
8626
8952
|
try {
|
|
8627
|
-
await
|
|
8953
|
+
await fs44.access(".coco");
|
|
8628
8954
|
hasProject = true;
|
|
8629
8955
|
} catch {
|
|
8630
8956
|
}
|
|
8631
8957
|
try {
|
|
8632
|
-
await
|
|
8958
|
+
await fs44.access(".coco/planning/backlog.json");
|
|
8633
8959
|
hasPlan = true;
|
|
8634
8960
|
} catch {
|
|
8635
8961
|
}
|
|
@@ -8733,24 +9059,24 @@ function getPhaseStatusForPhase(phase) {
|
|
|
8733
9059
|
return "in_progress";
|
|
8734
9060
|
}
|
|
8735
9061
|
async function loadProjectState(cwd, config) {
|
|
8736
|
-
const
|
|
8737
|
-
const
|
|
8738
|
-
const statePath =
|
|
8739
|
-
const backlogPath =
|
|
8740
|
-
const checkpointDir =
|
|
9062
|
+
const fs44 = await import('fs/promises');
|
|
9063
|
+
const path44 = await import('path');
|
|
9064
|
+
const statePath = path44.join(cwd, ".coco", "state.json");
|
|
9065
|
+
const backlogPath = path44.join(cwd, ".coco", "planning", "backlog.json");
|
|
9066
|
+
const checkpointDir = path44.join(cwd, ".coco", "checkpoints");
|
|
8741
9067
|
let currentPhase = "idle";
|
|
8742
9068
|
let metrics;
|
|
8743
9069
|
let sprint;
|
|
8744
9070
|
let checkpoints = [];
|
|
8745
9071
|
try {
|
|
8746
|
-
const stateContent = await
|
|
9072
|
+
const stateContent = await fs44.readFile(statePath, "utf-8");
|
|
8747
9073
|
const stateData = JSON.parse(stateContent);
|
|
8748
9074
|
currentPhase = stateData.currentPhase || "idle";
|
|
8749
9075
|
metrics = stateData.metrics;
|
|
8750
9076
|
} catch {
|
|
8751
9077
|
}
|
|
8752
9078
|
try {
|
|
8753
|
-
const backlogContent = await
|
|
9079
|
+
const backlogContent = await fs44.readFile(backlogPath, "utf-8");
|
|
8754
9080
|
const backlogData = JSON.parse(backlogContent);
|
|
8755
9081
|
if (backlogData.currentSprint) {
|
|
8756
9082
|
const tasks = backlogData.tasks || [];
|
|
@@ -8772,7 +9098,7 @@ async function loadProjectState(cwd, config) {
|
|
|
8772
9098
|
} catch {
|
|
8773
9099
|
}
|
|
8774
9100
|
try {
|
|
8775
|
-
const files = await
|
|
9101
|
+
const files = await fs44.readdir(checkpointDir);
|
|
8776
9102
|
checkpoints = files.filter((f) => f.endsWith(".json")).sort().reverse();
|
|
8777
9103
|
} catch {
|
|
8778
9104
|
}
|
|
@@ -8908,8 +9234,8 @@ async function restoreFromCheckpoint(_checkpoint) {
|
|
|
8908
9234
|
}
|
|
8909
9235
|
async function checkProjectExists() {
|
|
8910
9236
|
try {
|
|
8911
|
-
const
|
|
8912
|
-
await
|
|
9237
|
+
const fs44 = await import('fs/promises');
|
|
9238
|
+
await fs44.access(".coco");
|
|
8913
9239
|
return true;
|
|
8914
9240
|
} catch {
|
|
8915
9241
|
return false;
|
|
@@ -9570,12 +9896,12 @@ async function loadConfig2() {
|
|
|
9570
9896
|
};
|
|
9571
9897
|
}
|
|
9572
9898
|
async function saveConfig(config) {
|
|
9573
|
-
const
|
|
9574
|
-
await
|
|
9575
|
-
await
|
|
9899
|
+
const fs44 = await import('fs/promises');
|
|
9900
|
+
await fs44.mkdir(".coco", { recursive: true });
|
|
9901
|
+
await fs44.writeFile(".coco/config.json", JSON.stringify(config, null, 2));
|
|
9576
9902
|
}
|
|
9577
|
-
function getNestedValue(obj,
|
|
9578
|
-
const keys =
|
|
9903
|
+
function getNestedValue(obj, path44) {
|
|
9904
|
+
const keys = path44.split(".");
|
|
9579
9905
|
let current = obj;
|
|
9580
9906
|
for (const key of keys) {
|
|
9581
9907
|
if (current === null || current === void 0 || typeof current !== "object") {
|
|
@@ -9585,8 +9911,8 @@ function getNestedValue(obj, path43) {
|
|
|
9585
9911
|
}
|
|
9586
9912
|
return current;
|
|
9587
9913
|
}
|
|
9588
|
-
function setNestedValue(obj,
|
|
9589
|
-
const keys =
|
|
9914
|
+
function setNestedValue(obj, path44, value) {
|
|
9915
|
+
const keys = path44.split(".");
|
|
9590
9916
|
let current = obj;
|
|
9591
9917
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
9592
9918
|
const key = keys[i];
|
|
@@ -9807,8 +10133,8 @@ var MCPRegistryImpl = class {
|
|
|
9807
10133
|
/**
|
|
9808
10134
|
* Ensure directory exists
|
|
9809
10135
|
*/
|
|
9810
|
-
async ensureDir(
|
|
9811
|
-
await mkdir(dirname(
|
|
10136
|
+
async ensureDir(path44) {
|
|
10137
|
+
await mkdir(dirname(path44), { recursive: true });
|
|
9812
10138
|
}
|
|
9813
10139
|
};
|
|
9814
10140
|
function createMCPRegistry(registryPath) {
|
|
@@ -10327,9 +10653,9 @@ function createEmptyMemoryContext() {
|
|
|
10327
10653
|
errors: []
|
|
10328
10654
|
};
|
|
10329
10655
|
}
|
|
10330
|
-
function createMissingMemoryFile(
|
|
10656
|
+
function createMissingMemoryFile(path44, level) {
|
|
10331
10657
|
return {
|
|
10332
|
-
path:
|
|
10658
|
+
path: path44,
|
|
10333
10659
|
level,
|
|
10334
10660
|
content: "",
|
|
10335
10661
|
sections: [],
|
|
@@ -10383,14 +10709,42 @@ function generateToolCatalog(registry) {
|
|
|
10383
10709
|
}
|
|
10384
10710
|
var COCO_SYSTEM_PROMPT = `You are Corbat-Coco, an autonomous coding assistant with an extensive toolkit.
|
|
10385
10711
|
|
|
10386
|
-
##
|
|
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.
|
|
10730
|
+
|
|
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)
|
|
10387
10741
|
|
|
10388
|
-
|
|
10389
|
-
|
|
10390
|
-
|
|
10391
|
-
|
|
10392
|
-
|
|
10393
|
-
|
|
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
|
|
10394
10748
|
|
|
10395
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:
|
|
10396
10750
|
- Need information from the internet? Use **web_search** and **web_fetch**
|
|
@@ -10408,13 +10762,19 @@ When the user asks you to do something, follow this process:
|
|
|
10408
10762
|
{TOOL_CATALOG}
|
|
10409
10763
|
|
|
10410
10764
|
## Guidelines
|
|
10411
|
-
- Be
|
|
10412
|
-
-
|
|
10413
|
-
- Always verify
|
|
10414
|
-
-
|
|
10415
|
-
-
|
|
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
|
|
10416
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.
|
|
10417
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
|
+
|
|
10418
10778
|
## File Access
|
|
10419
10779
|
File operations are restricted to the project directory by default.
|
|
10420
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.
|
|
@@ -10506,9 +10866,45 @@ function getConversationContext(session, toolRegistry) {
|
|
|
10506
10866
|
# Project Instructions (from COCO.md/CLAUDE.md)
|
|
10507
10867
|
|
|
10508
10868
|
${session.memoryContext.combinedContent}`;
|
|
10869
|
+
}
|
|
10870
|
+
if (session.projectContext) {
|
|
10871
|
+
const stackInfo = formatStackContext(session.projectContext);
|
|
10872
|
+
systemPrompt = `${systemPrompt}
|
|
10873
|
+
|
|
10874
|
+
${stackInfo}`;
|
|
10509
10875
|
}
|
|
10510
10876
|
return [{ role: "system", content: systemPrompt }, ...session.messages];
|
|
10511
10877
|
}
|
|
10878
|
+
function formatStackContext(ctx) {
|
|
10879
|
+
const parts = [];
|
|
10880
|
+
parts.push("# Project Technology Stack");
|
|
10881
|
+
parts.push("");
|
|
10882
|
+
parts.push(`**Language/Runtime:** ${ctx.stack}`);
|
|
10883
|
+
if (ctx.packageManager) {
|
|
10884
|
+
parts.push(`**Package Manager:** ${ctx.packageManager}`);
|
|
10885
|
+
}
|
|
10886
|
+
if (ctx.frameworks.length > 0) {
|
|
10887
|
+
parts.push(`**Frameworks:** ${ctx.frameworks.join(", ")}`);
|
|
10888
|
+
}
|
|
10889
|
+
if (ctx.languages.length > 0) {
|
|
10890
|
+
parts.push(`**Languages:** ${ctx.languages.join(", ")}`);
|
|
10891
|
+
}
|
|
10892
|
+
if (ctx.testingFrameworks.length > 0) {
|
|
10893
|
+
parts.push(`**Testing Frameworks:** ${ctx.testingFrameworks.join(", ")}`);
|
|
10894
|
+
}
|
|
10895
|
+
if (ctx.buildTools.length > 0) {
|
|
10896
|
+
parts.push(`**Build Tools:** ${ctx.buildTools.join(", ")}`);
|
|
10897
|
+
}
|
|
10898
|
+
const keyDeps = Object.entries(ctx.dependencies).slice(0, 10).map(([name, version]) => `${name}@${version}`).join(", ");
|
|
10899
|
+
if (keyDeps) {
|
|
10900
|
+
parts.push(`**Key Dependencies:** ${keyDeps}`);
|
|
10901
|
+
}
|
|
10902
|
+
parts.push("");
|
|
10903
|
+
parts.push(
|
|
10904
|
+
"**IMPORTANT:** When suggesting libraries, frameworks, or dependencies, ONLY recommend technologies compatible with the stack above. Do not suggest installing Node.js packages in a Java project, or Java libraries in a Python project."
|
|
10905
|
+
);
|
|
10906
|
+
return parts.join("\n");
|
|
10907
|
+
}
|
|
10512
10908
|
function clearSession(session) {
|
|
10513
10909
|
session.messages = [];
|
|
10514
10910
|
}
|
|
@@ -13259,8 +13655,8 @@ async function listTrustedProjects2(trustStore) {
|
|
|
13259
13655
|
p9.log.message("");
|
|
13260
13656
|
for (const project of projects) {
|
|
13261
13657
|
const level = project.approvalLevel.toUpperCase().padEnd(5);
|
|
13262
|
-
const
|
|
13263
|
-
p9.log.message(` [${level}] ${
|
|
13658
|
+
const path44 = project.path.length > 50 ? "..." + project.path.slice(-47) : project.path;
|
|
13659
|
+
p9.log.message(` [${level}] ${path44}`);
|
|
13264
13660
|
p9.log.message(` Last accessed: ${new Date(project.lastAccessed).toLocaleString()}`);
|
|
13265
13661
|
}
|
|
13266
13662
|
p9.log.message("");
|
|
@@ -14430,7 +14826,7 @@ async function getCheckpoint(session, checkpointId) {
|
|
|
14430
14826
|
return store.checkpoints.find((cp) => cp.id === checkpointId) ?? null;
|
|
14431
14827
|
}
|
|
14432
14828
|
async function restoreFiles(checkpoint, excludeFiles) {
|
|
14433
|
-
const
|
|
14829
|
+
const fs44 = await import('fs/promises');
|
|
14434
14830
|
const restored = [];
|
|
14435
14831
|
const failed = [];
|
|
14436
14832
|
for (const fileCheckpoint of checkpoint.files) {
|
|
@@ -14438,7 +14834,7 @@ async function restoreFiles(checkpoint, excludeFiles) {
|
|
|
14438
14834
|
continue;
|
|
14439
14835
|
}
|
|
14440
14836
|
try {
|
|
14441
|
-
await
|
|
14837
|
+
await fs44.writeFile(fileCheckpoint.filePath, fileCheckpoint.originalContent, "utf-8");
|
|
14442
14838
|
restored.push(fileCheckpoint.filePath);
|
|
14443
14839
|
} catch (error) {
|
|
14444
14840
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
@@ -14520,8 +14916,8 @@ function displayRewindResult(result) {
|
|
|
14520
14916
|
const fileName = filePath.split("/").pop() ?? filePath;
|
|
14521
14917
|
console.log(`${chalk42.green(String.fromCodePoint(10003))} Restored: ${fileName}`);
|
|
14522
14918
|
}
|
|
14523
|
-
for (const { path:
|
|
14524
|
-
const fileName =
|
|
14919
|
+
for (const { path: path44, error } of result.filesFailed) {
|
|
14920
|
+
const fileName = path44.split("/").pop() ?? path44;
|
|
14525
14921
|
console.log(`${chalk42.red(String.fromCodePoint(10007))} Failed: ${fileName} (${error})`);
|
|
14526
14922
|
}
|
|
14527
14923
|
if (result.conversationRestored) {
|
|
@@ -15954,8 +16350,8 @@ function formatToolSummary(toolName, input) {
|
|
|
15954
16350
|
return String(input.path || ".");
|
|
15955
16351
|
case "search_files": {
|
|
15956
16352
|
const pattern = String(input.pattern || "");
|
|
15957
|
-
const
|
|
15958
|
-
return `"${pattern}"${
|
|
16353
|
+
const path44 = input.path ? ` in ${input.path}` : "";
|
|
16354
|
+
return `"${pattern}"${path44}`;
|
|
15959
16355
|
}
|
|
15960
16356
|
case "bash_exec": {
|
|
15961
16357
|
const cmd = String(input.command || "");
|
|
@@ -20989,10 +21385,10 @@ var CoverageAnalyzer = class {
|
|
|
20989
21385
|
join(this.projectPath, ".coverage", "coverage-summary.json"),
|
|
20990
21386
|
join(this.projectPath, "coverage", "lcov-report", "coverage-summary.json")
|
|
20991
21387
|
];
|
|
20992
|
-
for (const
|
|
21388
|
+
for (const path44 of possiblePaths) {
|
|
20993
21389
|
try {
|
|
20994
|
-
await access(
|
|
20995
|
-
const content = await readFile(
|
|
21390
|
+
await access(path44, constants.R_OK);
|
|
21391
|
+
const content = await readFile(path44, "utf-8");
|
|
20996
21392
|
const report = JSON.parse(content);
|
|
20997
21393
|
return parseCoverageSummary(report);
|
|
20998
21394
|
} catch {
|
|
@@ -24071,7 +24467,21 @@ Examples:
|
|
|
24071
24467
|
const projectDir = cwd ?? process.cwd();
|
|
24072
24468
|
const startTime = performance.now();
|
|
24073
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
|
+
});
|
|
24074
24483
|
try {
|
|
24484
|
+
heartbeat.start();
|
|
24075
24485
|
const pm = packageManager ?? await detectPackageManager(projectDir);
|
|
24076
24486
|
const cmdArgs = ["run", script];
|
|
24077
24487
|
if (args && args.length > 0) {
|
|
@@ -24082,13 +24492,30 @@ Examples:
|
|
|
24082
24492
|
timeout: timeoutMs,
|
|
24083
24493
|
env: { ...process.env, ...env2 },
|
|
24084
24494
|
reject: false,
|
|
24495
|
+
buffer: false,
|
|
24496
|
+
// Enable streaming
|
|
24085
24497
|
maxBuffer: MAX_OUTPUT_SIZE2
|
|
24086
24498
|
};
|
|
24087
|
-
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;
|
|
24088
24515
|
return {
|
|
24089
24516
|
success: result.exitCode === 0,
|
|
24090
|
-
stdout: truncateOutput2(
|
|
24091
|
-
stderr: truncateOutput2(
|
|
24517
|
+
stdout: truncateOutput2(stdoutBuffer),
|
|
24518
|
+
stderr: truncateOutput2(stderrBuffer),
|
|
24092
24519
|
exitCode: result.exitCode ?? 0,
|
|
24093
24520
|
duration: performance.now() - startTime,
|
|
24094
24521
|
packageManager: pm
|
|
@@ -24104,6 +24531,9 @@ Examples:
|
|
|
24104
24531
|
`Failed to run script '${script}': ${error instanceof Error ? error.message : String(error)}`,
|
|
24105
24532
|
{ tool: "run_script", cause: error instanceof Error ? error : void 0 }
|
|
24106
24533
|
);
|
|
24534
|
+
} finally {
|
|
24535
|
+
heartbeat.stop();
|
|
24536
|
+
process.stderr.write("\r \r");
|
|
24107
24537
|
}
|
|
24108
24538
|
}
|
|
24109
24539
|
});
|
|
@@ -24129,7 +24559,21 @@ Examples:
|
|
|
24129
24559
|
const projectDir = cwd ?? process.cwd();
|
|
24130
24560
|
const startTime = performance.now();
|
|
24131
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
|
+
});
|
|
24132
24575
|
try {
|
|
24576
|
+
heartbeat.start();
|
|
24133
24577
|
const pm = packageManager ?? await detectPackageManager(projectDir);
|
|
24134
24578
|
let cmdArgs;
|
|
24135
24579
|
if (packages && packages.length > 0) {
|
|
@@ -24169,13 +24613,30 @@ Examples:
|
|
|
24169
24613
|
cwd: projectDir,
|
|
24170
24614
|
timeout: timeoutMs,
|
|
24171
24615
|
reject: false,
|
|
24616
|
+
buffer: false,
|
|
24617
|
+
// Enable streaming
|
|
24172
24618
|
maxBuffer: MAX_OUTPUT_SIZE2
|
|
24173
24619
|
};
|
|
24174
|
-
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;
|
|
24175
24636
|
return {
|
|
24176
24637
|
success: result.exitCode === 0,
|
|
24177
|
-
stdout: truncateOutput2(
|
|
24178
|
-
stderr: truncateOutput2(
|
|
24638
|
+
stdout: truncateOutput2(stdoutBuffer),
|
|
24639
|
+
stderr: truncateOutput2(stderrBuffer),
|
|
24179
24640
|
exitCode: result.exitCode ?? 0,
|
|
24180
24641
|
duration: performance.now() - startTime,
|
|
24181
24642
|
packageManager: pm
|
|
@@ -24191,6 +24652,9 @@ Examples:
|
|
|
24191
24652
|
`Failed to install dependencies: ${error instanceof Error ? error.message : String(error)}`,
|
|
24192
24653
|
{ tool: "install_deps", cause: error instanceof Error ? error : void 0 }
|
|
24193
24654
|
);
|
|
24655
|
+
} finally {
|
|
24656
|
+
heartbeat.stop();
|
|
24657
|
+
process.stderr.write("\r \r");
|
|
24194
24658
|
}
|
|
24195
24659
|
}
|
|
24196
24660
|
});
|
|
@@ -24215,12 +24679,26 @@ Examples:
|
|
|
24215
24679
|
const projectDir = cwd ?? process.cwd();
|
|
24216
24680
|
const startTime = performance.now();
|
|
24217
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
|
+
});
|
|
24218
24695
|
try {
|
|
24219
24696
|
try {
|
|
24220
24697
|
await fs23__default.access(path20__default.join(projectDir, "Makefile"));
|
|
24221
24698
|
} catch {
|
|
24222
24699
|
throw new ToolError("No Makefile found in directory", { tool: "make" });
|
|
24223
24700
|
}
|
|
24701
|
+
heartbeat.start();
|
|
24224
24702
|
const cmdArgs = [];
|
|
24225
24703
|
if (target) {
|
|
24226
24704
|
cmdArgs.push(...target.split(/\s+/));
|
|
@@ -24233,13 +24711,30 @@ Examples:
|
|
|
24233
24711
|
timeout: timeoutMs,
|
|
24234
24712
|
env: { ...process.env, ...env2 },
|
|
24235
24713
|
reject: false,
|
|
24714
|
+
buffer: false,
|
|
24715
|
+
// Enable streaming
|
|
24236
24716
|
maxBuffer: MAX_OUTPUT_SIZE2
|
|
24237
24717
|
};
|
|
24238
|
-
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;
|
|
24239
24734
|
return {
|
|
24240
24735
|
success: result.exitCode === 0,
|
|
24241
|
-
stdout: truncateOutput2(
|
|
24242
|
-
stderr: truncateOutput2(
|
|
24736
|
+
stdout: truncateOutput2(stdoutBuffer),
|
|
24737
|
+
stderr: truncateOutput2(stderrBuffer),
|
|
24243
24738
|
exitCode: result.exitCode ?? 0,
|
|
24244
24739
|
duration: performance.now() - startTime
|
|
24245
24740
|
};
|
|
@@ -24255,6 +24750,9 @@ Examples:
|
|
|
24255
24750
|
`Make failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
24256
24751
|
{ tool: "make", cause: error instanceof Error ? error : void 0 }
|
|
24257
24752
|
);
|
|
24753
|
+
} finally {
|
|
24754
|
+
heartbeat.stop();
|
|
24755
|
+
process.stderr.write("\r \r");
|
|
24258
24756
|
}
|
|
24259
24757
|
}
|
|
24260
24758
|
});
|
|
@@ -24280,7 +24778,21 @@ Examples:
|
|
|
24280
24778
|
const projectDir = cwd ?? process.cwd();
|
|
24281
24779
|
const startTime = performance.now();
|
|
24282
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
|
+
});
|
|
24283
24794
|
try {
|
|
24795
|
+
heartbeat.start();
|
|
24284
24796
|
const cmdArgs = [];
|
|
24285
24797
|
if (project) {
|
|
24286
24798
|
cmdArgs.push("--project", project);
|
|
@@ -24298,13 +24810,30 @@ Examples:
|
|
|
24298
24810
|
cwd: projectDir,
|
|
24299
24811
|
timeout: timeoutMs,
|
|
24300
24812
|
reject: false,
|
|
24813
|
+
buffer: false,
|
|
24814
|
+
// Enable streaming
|
|
24301
24815
|
maxBuffer: MAX_OUTPUT_SIZE2
|
|
24302
24816
|
};
|
|
24303
|
-
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;
|
|
24304
24833
|
return {
|
|
24305
24834
|
success: result.exitCode === 0,
|
|
24306
|
-
stdout: truncateOutput2(
|
|
24307
|
-
stderr: truncateOutput2(
|
|
24835
|
+
stdout: truncateOutput2(stdoutBuffer),
|
|
24836
|
+
stderr: truncateOutput2(stderrBuffer),
|
|
24308
24837
|
exitCode: result.exitCode ?? 0,
|
|
24309
24838
|
duration: performance.now() - startTime
|
|
24310
24839
|
};
|
|
@@ -24319,6 +24848,9 @@ Examples:
|
|
|
24319
24848
|
`TypeScript compile failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
24320
24849
|
{ tool: "tsc", cause: error instanceof Error ? error : void 0 }
|
|
24321
24850
|
);
|
|
24851
|
+
} finally {
|
|
24852
|
+
heartbeat.stop();
|
|
24853
|
+
process.stderr.write("\r \r");
|
|
24322
24854
|
}
|
|
24323
24855
|
}
|
|
24324
24856
|
});
|
|
@@ -25202,20 +25734,10 @@ var diffTools = [showDiffTool];
|
|
|
25202
25734
|
// src/tools/review.ts
|
|
25203
25735
|
init_registry();
|
|
25204
25736
|
init_errors();
|
|
25205
|
-
|
|
25206
|
-
|
|
25207
|
-
init_errors();
|
|
25208
|
-
async function fileExists(filePath) {
|
|
25209
|
-
try {
|
|
25210
|
-
await fs23__default.access(filePath);
|
|
25211
|
-
return true;
|
|
25212
|
-
} catch {
|
|
25213
|
-
return false;
|
|
25214
|
-
}
|
|
25215
|
-
}
|
|
25216
|
-
async function fileExists2(path43) {
|
|
25737
|
+
init_files();
|
|
25738
|
+
async function fileExists2(path44) {
|
|
25217
25739
|
try {
|
|
25218
|
-
await access(
|
|
25740
|
+
await access(path44);
|
|
25219
25741
|
return true;
|
|
25220
25742
|
} catch {
|
|
25221
25743
|
return false;
|
|
@@ -25305,7 +25827,7 @@ async function detectMaturity(cwd) {
|
|
|
25305
25827
|
if (!hasLintConfig && hasPackageJson) {
|
|
25306
25828
|
try {
|
|
25307
25829
|
const pkgRaw = await import('fs/promises').then(
|
|
25308
|
-
(
|
|
25830
|
+
(fs44) => fs44.readFile(join(cwd, "package.json"), "utf-8")
|
|
25309
25831
|
);
|
|
25310
25832
|
const pkg = JSON.parse(pkgRaw);
|
|
25311
25833
|
if (pkg.scripts?.lint || pkg.scripts?.["lint:fix"]) {
|
|
@@ -29964,6 +30486,13 @@ var terminalOptions = {
|
|
|
29964
30486
|
var marked = new Marked();
|
|
29965
30487
|
marked.use(markedTerminal(terminalOptions));
|
|
29966
30488
|
init_bash();
|
|
30489
|
+
init_files();
|
|
30490
|
+
|
|
30491
|
+
// src/cli/repl/skills/builtin/ship/version-detector.ts
|
|
30492
|
+
init_files();
|
|
30493
|
+
|
|
30494
|
+
// src/cli/repl/skills/builtin/ship/changelog.ts
|
|
30495
|
+
init_files();
|
|
29967
30496
|
|
|
29968
30497
|
// src/cli/repl/skills/builtin/ship/steps/test-coverage.ts
|
|
29969
30498
|
init_bash();
|
|
@@ -30038,6 +30567,8 @@ async function startRepl(options = {}) {
|
|
|
30038
30567
|
process.exit(1);
|
|
30039
30568
|
}
|
|
30040
30569
|
initializeContextManager(session, provider);
|
|
30570
|
+
const { detectProjectStack: detectProjectStack2 } = await Promise.resolve().then(() => (init_stack_detector(), stack_detector_exports));
|
|
30571
|
+
session.projectContext = await detectProjectStack2(projectPath);
|
|
30041
30572
|
await loadAllowedPaths(projectPath);
|
|
30042
30573
|
if (await shouldShowPermissionSuggestion()) {
|
|
30043
30574
|
await showPermissionSuggestion();
|
|
@@ -30189,7 +30720,11 @@ async function startRepl(options = {}) {
|
|
|
30189
30720
|
clearSpinner();
|
|
30190
30721
|
renderToolStart(result2.name, result2.input);
|
|
30191
30722
|
renderToolEnd(result2);
|
|
30192
|
-
|
|
30723
|
+
if (isCocoMode()) {
|
|
30724
|
+
setSpinner("Processing results & checking quality...");
|
|
30725
|
+
} else {
|
|
30726
|
+
setSpinner("Processing...");
|
|
30727
|
+
}
|
|
30193
30728
|
},
|
|
30194
30729
|
onToolSkipped: (tc, reason) => {
|
|
30195
30730
|
clearSpinner();
|
|
@@ -30202,10 +30737,18 @@ async function startRepl(options = {}) {
|
|
|
30202
30737
|
if (!thinkingStartTime) return;
|
|
30203
30738
|
const elapsed = Math.floor((Date.now() - thinkingStartTime) / 1e3);
|
|
30204
30739
|
if (elapsed < 4) return;
|
|
30205
|
-
if (
|
|
30206
|
-
|
|
30207
|
-
|
|
30208
|
-
|
|
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
|
+
}
|
|
30209
30752
|
}, 2e3);
|
|
30210
30753
|
},
|
|
30211
30754
|
onThinkingEnd: () => {
|