@caliber-ai/cli 0.19.0 → 0.20.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/bin.js +74 -45
- package/dist/bin.js.map +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -1503,6 +1503,7 @@ function stageFiles(files, projectDir) {
|
|
|
1503
1503
|
cleanupStaging();
|
|
1504
1504
|
let newFiles = 0;
|
|
1505
1505
|
let modifiedFiles = 0;
|
|
1506
|
+
const stagedFiles = [];
|
|
1506
1507
|
for (const file of files) {
|
|
1507
1508
|
const proposedPath = path14.join(PROPOSED_DIR, file.path);
|
|
1508
1509
|
fs15.mkdirSync(path14.dirname(proposedPath), { recursive: true });
|
|
@@ -1513,14 +1514,13 @@ function stageFiles(files, projectDir) {
|
|
|
1513
1514
|
fs15.mkdirSync(path14.dirname(currentPath), { recursive: true });
|
|
1514
1515
|
fs15.copyFileSync(originalPath, currentPath);
|
|
1515
1516
|
modifiedFiles++;
|
|
1517
|
+
stagedFiles.push({ relativePath: file.path, proposedPath, currentPath, isNew: false });
|
|
1516
1518
|
} else {
|
|
1517
1519
|
newFiles++;
|
|
1520
|
+
stagedFiles.push({ relativePath: file.path, proposedPath, isNew: true });
|
|
1518
1521
|
}
|
|
1519
1522
|
}
|
|
1520
|
-
return { newFiles, modifiedFiles };
|
|
1521
|
-
}
|
|
1522
|
-
function getStagedProposedDir() {
|
|
1523
|
-
return PROPOSED_DIR;
|
|
1523
|
+
return { newFiles, modifiedFiles, stagedFiles };
|
|
1524
1524
|
}
|
|
1525
1525
|
function cleanupStaging() {
|
|
1526
1526
|
if (fs15.existsSync(STAGED_DIR)) {
|
|
@@ -1529,7 +1529,7 @@ function cleanupStaging() {
|
|
|
1529
1529
|
}
|
|
1530
1530
|
|
|
1531
1531
|
// src/utils/editor.ts
|
|
1532
|
-
import { execSync as execSync2 } from "child_process";
|
|
1532
|
+
import { execSync as execSync2, spawnSync } from "child_process";
|
|
1533
1533
|
function commandExists(cmd) {
|
|
1534
1534
|
try {
|
|
1535
1535
|
execSync2(`which ${cmd}`, { stdio: "ignore" });
|
|
@@ -1538,40 +1538,31 @@ function commandExists(cmd) {
|
|
|
1538
1538
|
return false;
|
|
1539
1539
|
}
|
|
1540
1540
|
}
|
|
1541
|
-
function
|
|
1542
|
-
const
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
return true;
|
|
1552
|
-
} catch {
|
|
1553
|
-
continue;
|
|
1554
|
-
}
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
}
|
|
1558
|
-
const envEditor = process.env.EDITOR;
|
|
1559
|
-
if (envEditor && commandExists(envEditor)) {
|
|
1541
|
+
function detectAvailableEditors() {
|
|
1542
|
+
const methods = [];
|
|
1543
|
+
if (commandExists("cursor")) methods.push("cursor");
|
|
1544
|
+
if (commandExists("code")) methods.push("vscode");
|
|
1545
|
+
methods.push("terminal");
|
|
1546
|
+
return methods;
|
|
1547
|
+
}
|
|
1548
|
+
function openDiffsInEditor(editor, files) {
|
|
1549
|
+
const cmd = editor === "cursor" ? "cursor" : "code";
|
|
1550
|
+
for (const file of files) {
|
|
1560
1551
|
try {
|
|
1561
|
-
|
|
1562
|
-
|
|
1552
|
+
if (file.currentPath) {
|
|
1553
|
+
spawnSync(cmd, ["--diff", file.currentPath, file.proposedPath], { stdio: "ignore" });
|
|
1554
|
+
} else {
|
|
1555
|
+
spawnSync(cmd, [file.proposedPath], { stdio: "ignore" });
|
|
1556
|
+
}
|
|
1563
1557
|
} catch {
|
|
1558
|
+
continue;
|
|
1564
1559
|
}
|
|
1565
1560
|
}
|
|
1566
|
-
try {
|
|
1567
|
-
const openCmd = process.platform === "darwin" ? "open" : "xdg-open";
|
|
1568
|
-
execSync2(`${openCmd} "${dirPath}"`, { stdio: "ignore" });
|
|
1569
|
-
return true;
|
|
1570
|
-
} catch {
|
|
1571
|
-
return false;
|
|
1572
|
-
}
|
|
1573
1561
|
}
|
|
1574
1562
|
|
|
1563
|
+
// src/commands/init.ts
|
|
1564
|
+
import { createTwoFilesPatch } from "diff";
|
|
1565
|
+
|
|
1575
1566
|
// src/lib/hooks.ts
|
|
1576
1567
|
import fs16 from "fs";
|
|
1577
1568
|
import path15 from "path";
|
|
@@ -1949,16 +1940,11 @@ async function initCommand(options) {
|
|
|
1949
1940
|
printSetupSummary(generatedSetup);
|
|
1950
1941
|
console.log(chalk3.hex("#6366f1").bold(" Step 5/6 \u2014 Review\n"));
|
|
1951
1942
|
const setupFiles = collectSetupFiles(generatedSetup);
|
|
1952
|
-
const
|
|
1953
|
-
|
|
1954
|
-
const editorOpened = openInEditor(stagedDir);
|
|
1955
|
-
if (editorOpened) {
|
|
1956
|
-
console.log(chalk3.dim(" Proposed files opened in your editor for review."));
|
|
1957
|
-
} else {
|
|
1958
|
-
console.log(chalk3.dim(" Staged files written to .caliber/staged/proposed/ for review."));
|
|
1959
|
-
}
|
|
1960
|
-
console.log(chalk3.dim(` ${chalk3.green(`${newFiles} new`)} / ${chalk3.yellow(`${modifiedFiles} modified`)} file${newFiles + modifiedFiles !== 1 ? "s" : ""}
|
|
1943
|
+
const staged = stageFiles(setupFiles, process.cwd());
|
|
1944
|
+
console.log(chalk3.dim(` ${chalk3.green(`${staged.newFiles} new`)} / ${chalk3.yellow(`${staged.modifiedFiles} modified`)} file${staged.newFiles + staged.modifiedFiles !== 1 ? "s" : ""}
|
|
1961
1945
|
`));
|
|
1946
|
+
const reviewMethod = await promptReviewMethod();
|
|
1947
|
+
openReview(reviewMethod, staged.stagedFiles);
|
|
1962
1948
|
let action = await promptReviewAction();
|
|
1963
1949
|
while (action === "refine") {
|
|
1964
1950
|
generatedSetup = await refineLoop(generatedSetup, targetAgent);
|
|
@@ -1970,11 +1956,9 @@ async function initCommand(options) {
|
|
|
1970
1956
|
}
|
|
1971
1957
|
const updatedFiles = collectSetupFiles(generatedSetup);
|
|
1972
1958
|
const restaged = stageFiles(updatedFiles, process.cwd());
|
|
1973
|
-
if (editorOpened) {
|
|
1974
|
-
console.log(chalk3.dim(" Updated files re-staged. Check your editor for changes."));
|
|
1975
|
-
}
|
|
1976
1959
|
console.log(chalk3.dim(` ${chalk3.green(`${restaged.newFiles} new`)} / ${chalk3.yellow(`${restaged.modifiedFiles} modified`)} file${restaged.newFiles + restaged.modifiedFiles !== 1 ? "s" : ""}
|
|
1977
1960
|
`));
|
|
1961
|
+
openReview(reviewMethod, restaged.stagedFiles);
|
|
1978
1962
|
printSetupSummary(generatedSetup);
|
|
1979
1963
|
action = await promptReviewAction();
|
|
1980
1964
|
}
|
|
@@ -2133,6 +2117,51 @@ async function promptAgent() {
|
|
|
2133
2117
|
]
|
|
2134
2118
|
});
|
|
2135
2119
|
}
|
|
2120
|
+
async function promptReviewMethod() {
|
|
2121
|
+
const available = detectAvailableEditors();
|
|
2122
|
+
if (available.length === 1) return "terminal";
|
|
2123
|
+
const choices = available.map((method) => {
|
|
2124
|
+
switch (method) {
|
|
2125
|
+
case "cursor":
|
|
2126
|
+
return { name: "Cursor (diff view)", value: "cursor" };
|
|
2127
|
+
case "vscode":
|
|
2128
|
+
return { name: "VS Code (diff view)", value: "vscode" };
|
|
2129
|
+
case "terminal":
|
|
2130
|
+
return { name: "Terminal", value: "terminal" };
|
|
2131
|
+
}
|
|
2132
|
+
});
|
|
2133
|
+
return select({ message: "How would you like to review the changes?", choices });
|
|
2134
|
+
}
|
|
2135
|
+
function openReview(method, stagedFiles) {
|
|
2136
|
+
if (method === "cursor" || method === "vscode") {
|
|
2137
|
+
openDiffsInEditor(method, stagedFiles.map((f) => ({
|
|
2138
|
+
currentPath: f.currentPath,
|
|
2139
|
+
proposedPath: f.proposedPath
|
|
2140
|
+
})));
|
|
2141
|
+
console.log(chalk3.dim(" Diffs opened in your editor.\n"));
|
|
2142
|
+
} else {
|
|
2143
|
+
for (const file of stagedFiles) {
|
|
2144
|
+
console.log(chalk3.bold(` ${file.relativePath}`));
|
|
2145
|
+
if (file.currentPath) {
|
|
2146
|
+
const current = fs18.readFileSync(file.currentPath, "utf-8");
|
|
2147
|
+
const proposed = fs18.readFileSync(file.proposedPath, "utf-8");
|
|
2148
|
+
const patch = createTwoFilesPatch(file.relativePath, file.relativePath, current, proposed, "current", "proposed");
|
|
2149
|
+
for (const line of patch.split("\n").slice(2)) {
|
|
2150
|
+
if (line.startsWith("+")) console.log(chalk3.green(` ${line}`));
|
|
2151
|
+
else if (line.startsWith("-")) console.log(chalk3.red(` ${line}`));
|
|
2152
|
+
else console.log(chalk3.dim(` ${line}`));
|
|
2153
|
+
}
|
|
2154
|
+
} else {
|
|
2155
|
+
console.log(chalk3.green(" (new file)"));
|
|
2156
|
+
const content = fs18.readFileSync(file.proposedPath, "utf-8");
|
|
2157
|
+
const preview = content.split("\n").slice(0, 20);
|
|
2158
|
+
for (const line of preview) console.log(chalk3.green(` +${line}`));
|
|
2159
|
+
if (content.split("\n").length > 20) console.log(chalk3.dim(` ... ${content.split("\n").length - 20} more lines`));
|
|
2160
|
+
}
|
|
2161
|
+
console.log("");
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2136
2165
|
async function promptReviewAction() {
|
|
2137
2166
|
return select({
|
|
2138
2167
|
message: "What would you like to do?",
|