@caliber-ai/cli 0.19.0 → 0.20.1
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 +80 -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, originalPath, 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, spawn } from "child_process";
|
|
1533
1533
|
function commandExists(cmd) {
|
|
1534
1534
|
try {
|
|
1535
1535
|
execSync2(`which ${cmd}`, { stdio: "ignore" });
|
|
@@ -1538,40 +1538,37 @@ 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.originalPath) {
|
|
1553
|
+
spawn(cmd, ["--diff", file.originalPath, file.proposedPath], {
|
|
1554
|
+
stdio: "ignore",
|
|
1555
|
+
detached: true
|
|
1556
|
+
}).unref();
|
|
1557
|
+
} else {
|
|
1558
|
+
spawn(cmd, [file.proposedPath], {
|
|
1559
|
+
stdio: "ignore",
|
|
1560
|
+
detached: true
|
|
1561
|
+
}).unref();
|
|
1562
|
+
}
|
|
1563
1563
|
} catch {
|
|
1564
|
+
continue;
|
|
1564
1565
|
}
|
|
1565
1566
|
}
|
|
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
1567
|
}
|
|
1574
1568
|
|
|
1569
|
+
// src/commands/init.ts
|
|
1570
|
+
import { createTwoFilesPatch } from "diff";
|
|
1571
|
+
|
|
1575
1572
|
// src/lib/hooks.ts
|
|
1576
1573
|
import fs16 from "fs";
|
|
1577
1574
|
import path15 from "path";
|
|
@@ -1949,16 +1946,11 @@ async function initCommand(options) {
|
|
|
1949
1946
|
printSetupSummary(generatedSetup);
|
|
1950
1947
|
console.log(chalk3.hex("#6366f1").bold(" Step 5/6 \u2014 Review\n"));
|
|
1951
1948
|
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" : ""}
|
|
1949
|
+
const staged = stageFiles(setupFiles, process.cwd());
|
|
1950
|
+
console.log(chalk3.dim(` ${chalk3.green(`${staged.newFiles} new`)} / ${chalk3.yellow(`${staged.modifiedFiles} modified`)} file${staged.newFiles + staged.modifiedFiles !== 1 ? "s" : ""}
|
|
1961
1951
|
`));
|
|
1952
|
+
const reviewMethod = await promptReviewMethod();
|
|
1953
|
+
openReview(reviewMethod, staged.stagedFiles);
|
|
1962
1954
|
let action = await promptReviewAction();
|
|
1963
1955
|
while (action === "refine") {
|
|
1964
1956
|
generatedSetup = await refineLoop(generatedSetup, targetAgent);
|
|
@@ -1970,11 +1962,9 @@ async function initCommand(options) {
|
|
|
1970
1962
|
}
|
|
1971
1963
|
const updatedFiles = collectSetupFiles(generatedSetup);
|
|
1972
1964
|
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
1965
|
console.log(chalk3.dim(` ${chalk3.green(`${restaged.newFiles} new`)} / ${chalk3.yellow(`${restaged.modifiedFiles} modified`)} file${restaged.newFiles + restaged.modifiedFiles !== 1 ? "s" : ""}
|
|
1977
1966
|
`));
|
|
1967
|
+
openReview(reviewMethod, restaged.stagedFiles);
|
|
1978
1968
|
printSetupSummary(generatedSetup);
|
|
1979
1969
|
action = await promptReviewAction();
|
|
1980
1970
|
}
|
|
@@ -2133,6 +2123,51 @@ async function promptAgent() {
|
|
|
2133
2123
|
]
|
|
2134
2124
|
});
|
|
2135
2125
|
}
|
|
2126
|
+
async function promptReviewMethod() {
|
|
2127
|
+
const available = detectAvailableEditors();
|
|
2128
|
+
if (available.length === 1) return "terminal";
|
|
2129
|
+
const choices = available.map((method) => {
|
|
2130
|
+
switch (method) {
|
|
2131
|
+
case "cursor":
|
|
2132
|
+
return { name: "Cursor (diff view)", value: "cursor" };
|
|
2133
|
+
case "vscode":
|
|
2134
|
+
return { name: "VS Code (diff view)", value: "vscode" };
|
|
2135
|
+
case "terminal":
|
|
2136
|
+
return { name: "Terminal", value: "terminal" };
|
|
2137
|
+
}
|
|
2138
|
+
});
|
|
2139
|
+
return select({ message: "How would you like to review the changes?", choices });
|
|
2140
|
+
}
|
|
2141
|
+
function openReview(method, stagedFiles) {
|
|
2142
|
+
if (method === "cursor" || method === "vscode") {
|
|
2143
|
+
openDiffsInEditor(method, stagedFiles.map((f) => ({
|
|
2144
|
+
originalPath: f.originalPath,
|
|
2145
|
+
proposedPath: f.proposedPath
|
|
2146
|
+
})));
|
|
2147
|
+
console.log(chalk3.dim(" Diffs opened in your editor.\n"));
|
|
2148
|
+
} else {
|
|
2149
|
+
for (const file of stagedFiles) {
|
|
2150
|
+
console.log(chalk3.bold(` ${file.relativePath}`));
|
|
2151
|
+
if (file.currentPath) {
|
|
2152
|
+
const current = fs18.readFileSync(file.currentPath, "utf-8");
|
|
2153
|
+
const proposed = fs18.readFileSync(file.proposedPath, "utf-8");
|
|
2154
|
+
const patch = createTwoFilesPatch(file.relativePath, file.relativePath, current, proposed, "current", "proposed");
|
|
2155
|
+
for (const line of patch.split("\n").slice(2)) {
|
|
2156
|
+
if (line.startsWith("+")) console.log(chalk3.green(` ${line}`));
|
|
2157
|
+
else if (line.startsWith("-")) console.log(chalk3.red(` ${line}`));
|
|
2158
|
+
else console.log(chalk3.dim(` ${line}`));
|
|
2159
|
+
}
|
|
2160
|
+
} else {
|
|
2161
|
+
console.log(chalk3.green(" (new file)"));
|
|
2162
|
+
const content = fs18.readFileSync(file.proposedPath, "utf-8");
|
|
2163
|
+
const preview = content.split("\n").slice(0, 20);
|
|
2164
|
+
for (const line of preview) console.log(chalk3.green(` +${line}`));
|
|
2165
|
+
if (content.split("\n").length > 20) console.log(chalk3.dim(` ... ${content.split("\n").length - 20} more lines`));
|
|
2166
|
+
}
|
|
2167
|
+
console.log("");
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2136
2171
|
async function promptReviewAction() {
|
|
2137
2172
|
return select({
|
|
2138
2173
|
message: "What would you like to do?",
|