@shakecodeslikecray/whiterose 1.0.1 → 1.0.3
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 +116 -63
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +93 -55
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { existsSync, mkdirSync, writeFileSync, readdirSync,
|
|
3
|
-
import { join, isAbsolute, resolve, basename, relative
|
|
2
|
+
import { readFileSync, existsSync, mkdirSync, writeFileSync, readdirSync, statSync, rmSync, mkdtempSync, realpathSync } from 'fs';
|
|
3
|
+
import { join, dirname, isAbsolute, resolve, basename, relative } from 'path';
|
|
4
4
|
import chalk3 from 'chalk';
|
|
5
5
|
import * as readline from 'readline';
|
|
6
6
|
import { Command } from 'commander';
|
|
7
7
|
import * as p3 from '@clack/prompts';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
8
9
|
import { execa } from 'execa';
|
|
9
10
|
import { homedir, tmpdir } from 'os';
|
|
10
11
|
import fg3 from 'fast-glob';
|
|
@@ -2934,7 +2935,7 @@ function parseListItems(content) {
|
|
|
2934
2935
|
return items;
|
|
2935
2936
|
}
|
|
2936
2937
|
function parseFeatureSection(section) {
|
|
2937
|
-
const titleMatch = section.match(/###\s+([
|
|
2938
|
+
const titleMatch = section.match(/###\s+([^[\n]+)(?:\s*\[([^\]]+)\])?/);
|
|
2938
2939
|
if (!titleMatch) return null;
|
|
2939
2940
|
const name = titleMatch[1].trim();
|
|
2940
2941
|
const badge = titleMatch[2]?.trim().toLowerCase();
|
|
@@ -4328,7 +4329,18 @@ function loadAccumulatedBugs(cwd) {
|
|
|
4328
4329
|
}
|
|
4329
4330
|
stored.bugs = stored.bugs.map((b) => ({ ...b, kind: b.kind || "bug" }));
|
|
4330
4331
|
return stored;
|
|
4331
|
-
} catch {
|
|
4332
|
+
} catch (error) {
|
|
4333
|
+
const backupPath = `${bugsPath}.corrupted.${Date.now()}`;
|
|
4334
|
+
try {
|
|
4335
|
+
const corruptedContent = readFileSync(bugsPath, "utf-8");
|
|
4336
|
+
writeFileSync(backupPath, corruptedContent);
|
|
4337
|
+
console.warn(`Warning: ${BUGS_FILENAME} is corrupted and could not be parsed.`);
|
|
4338
|
+
console.warn(`Corrupted file backed up to: ${backupPath}`);
|
|
4339
|
+
console.warn("Bug history has been reset. Previous bugs will appear as new.");
|
|
4340
|
+
} catch {
|
|
4341
|
+
console.warn(`Warning: ${BUGS_FILENAME} is corrupted and could not be parsed.`);
|
|
4342
|
+
console.warn("Bug history has been reset. Previous bugs will appear as new.");
|
|
4343
|
+
}
|
|
4332
4344
|
return {
|
|
4333
4345
|
version: STORAGE_VERSION,
|
|
4334
4346
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -5473,7 +5485,7 @@ var Dashboard = ({ bugs, onSelectCategory }) => {
|
|
|
5473
5485
|
color: categoryColors[category] || "white"
|
|
5474
5486
|
});
|
|
5475
5487
|
}
|
|
5476
|
-
useInput((
|
|
5488
|
+
useInput((_input, key) => {
|
|
5477
5489
|
if (key.upArrow) {
|
|
5478
5490
|
setSelectedIndex((i) => Math.max(0, i - 1));
|
|
5479
5491
|
} else if (key.downArrow) {
|
|
@@ -6322,73 +6334,111 @@ In: ${bug.file}:${bug.line}`
|
|
|
6322
6334
|
async function runAgenticFix(bug, config, projectDir) {
|
|
6323
6335
|
const providerCommand = getProviderCommand(config.provider);
|
|
6324
6336
|
const prompt = buildAgenticFixPrompt(bug);
|
|
6325
|
-
const
|
|
6326
|
-
|
|
6327
|
-
args.push("-p", prompt, "--dangerously-skip-permissions");
|
|
6328
|
-
} else if (config.provider === "gemini") {
|
|
6329
|
-
args.push("-p", prompt);
|
|
6330
|
-
} else if (config.provider === "aider") {
|
|
6331
|
-
args.push("--message", prompt, bug.file);
|
|
6332
|
-
} else if (config.provider === "codex") ; else {
|
|
6333
|
-
args.push("-p", prompt);
|
|
6334
|
-
}
|
|
6337
|
+
const controller = new AbortController();
|
|
6338
|
+
const timeoutId = setTimeout(() => controller.abort(), 3e5);
|
|
6335
6339
|
let stdout = "";
|
|
6336
6340
|
let stderr = "";
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
+
try {
|
|
6342
|
+
if (config.provider === "codex") {
|
|
6343
|
+
const tempDir = mkdtempSync(join(tmpdir(), "whiterose-fix-"));
|
|
6344
|
+
const outputFile = join(tempDir, "output.txt");
|
|
6345
|
+
try {
|
|
6346
|
+
const result = await execa(
|
|
6347
|
+
providerCommand,
|
|
6348
|
+
[
|
|
6349
|
+
"exec",
|
|
6350
|
+
"--full-auto",
|
|
6351
|
+
// Allow workspace writes without approval prompts
|
|
6352
|
+
"--skip-git-repo-check",
|
|
6353
|
+
"-C",
|
|
6354
|
+
projectDir,
|
|
6355
|
+
// Set working directory for codex
|
|
6356
|
+
"-o",
|
|
6357
|
+
outputFile,
|
|
6358
|
+
"-"
|
|
6359
|
+
// Read prompt from stdin
|
|
6360
|
+
],
|
|
6361
|
+
{
|
|
6362
|
+
cwd: projectDir,
|
|
6363
|
+
input: prompt,
|
|
6364
|
+
// Pass prompt via stdin
|
|
6365
|
+
timeout: 3e5,
|
|
6366
|
+
env: { ...process.env, NO_COLOR: "1" },
|
|
6367
|
+
reject: false,
|
|
6368
|
+
cancelSignal: controller.signal
|
|
6369
|
+
}
|
|
6370
|
+
);
|
|
6371
|
+
stderr = result.stderr || "";
|
|
6372
|
+
if (existsSync(outputFile)) {
|
|
6373
|
+
try {
|
|
6374
|
+
stdout = readFileSync(outputFile, "utf-8");
|
|
6375
|
+
} catch {
|
|
6376
|
+
stdout = result.stdout || "";
|
|
6377
|
+
}
|
|
6378
|
+
} else {
|
|
6379
|
+
stdout = result.stdout || "";
|
|
6380
|
+
}
|
|
6381
|
+
} finally {
|
|
6382
|
+
try {
|
|
6383
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
6384
|
+
} catch {
|
|
6385
|
+
}
|
|
6386
|
+
}
|
|
6387
|
+
} else if (config.provider === "claude-code") {
|
|
6341
6388
|
const result = await execa(
|
|
6342
6389
|
providerCommand,
|
|
6343
|
-
[
|
|
6344
|
-
"exec",
|
|
6345
|
-
"--full-auto",
|
|
6346
|
-
// Allow workspace writes without approval prompts
|
|
6347
|
-
"--skip-git-repo-check",
|
|
6348
|
-
"-C",
|
|
6349
|
-
projectDir,
|
|
6350
|
-
// Set working directory for codex
|
|
6351
|
-
"-o",
|
|
6352
|
-
outputFile,
|
|
6353
|
-
"-"
|
|
6354
|
-
// Read prompt from stdin
|
|
6355
|
-
],
|
|
6390
|
+
["--dangerously-skip-permissions", "-p"],
|
|
6356
6391
|
{
|
|
6357
6392
|
cwd: projectDir,
|
|
6358
6393
|
input: prompt,
|
|
6359
|
-
// Pass prompt via stdin
|
|
6394
|
+
// Pass prompt via stdin (Claude reads from stdin when no prompt arg provided)
|
|
6360
6395
|
timeout: 3e5,
|
|
6361
6396
|
env: { ...process.env, NO_COLOR: "1" },
|
|
6362
|
-
reject: false
|
|
6397
|
+
reject: false,
|
|
6398
|
+
cancelSignal: controller.signal
|
|
6363
6399
|
}
|
|
6364
6400
|
);
|
|
6401
|
+
stdout = result.stdout || "";
|
|
6402
|
+
stderr = result.stderr || "";
|
|
6403
|
+
} else if (config.provider === "gemini") {
|
|
6404
|
+
const result = await execa(providerCommand, ["-p", prompt], {
|
|
6405
|
+
cwd: projectDir,
|
|
6406
|
+
timeout: 3e5,
|
|
6407
|
+
env: { ...process.env, NO_COLOR: "1" },
|
|
6408
|
+
reject: false,
|
|
6409
|
+
stdin: "ignore",
|
|
6410
|
+
// Prevent stdin hangs
|
|
6411
|
+
cancelSignal: controller.signal
|
|
6412
|
+
});
|
|
6413
|
+
stdout = result.stdout || "";
|
|
6414
|
+
stderr = result.stderr || "";
|
|
6415
|
+
} else if (config.provider === "aider") {
|
|
6416
|
+
const result = await execa(providerCommand, ["--message", prompt, bug.file], {
|
|
6417
|
+
cwd: projectDir,
|
|
6418
|
+
timeout: 3e5,
|
|
6419
|
+
env: { ...process.env, NO_COLOR: "1" },
|
|
6420
|
+
reject: false,
|
|
6421
|
+
stdin: "ignore",
|
|
6422
|
+
// Prevent stdin hangs
|
|
6423
|
+
cancelSignal: controller.signal
|
|
6424
|
+
});
|
|
6425
|
+
stdout = result.stdout || "";
|
|
6426
|
+
stderr = result.stderr || "";
|
|
6427
|
+
} else {
|
|
6428
|
+
const result = await execa(providerCommand, ["-p", prompt], {
|
|
6429
|
+
cwd: projectDir,
|
|
6430
|
+
timeout: 3e5,
|
|
6431
|
+
env: { ...process.env, NO_COLOR: "1" },
|
|
6432
|
+
reject: false,
|
|
6433
|
+
stdin: "ignore",
|
|
6434
|
+
// Prevent stdin hangs
|
|
6435
|
+
cancelSignal: controller.signal
|
|
6436
|
+
});
|
|
6437
|
+
stdout = result.stdout || "";
|
|
6365
6438
|
stderr = result.stderr || "";
|
|
6366
|
-
if (existsSync(outputFile)) {
|
|
6367
|
-
try {
|
|
6368
|
-
stdout = readFileSync(outputFile, "utf-8");
|
|
6369
|
-
} catch {
|
|
6370
|
-
stdout = result.stdout || "";
|
|
6371
|
-
}
|
|
6372
|
-
} else {
|
|
6373
|
-
stdout = result.stdout || "";
|
|
6374
|
-
}
|
|
6375
|
-
} finally {
|
|
6376
|
-
try {
|
|
6377
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
6378
|
-
} catch {
|
|
6379
|
-
}
|
|
6380
6439
|
}
|
|
6381
|
-
}
|
|
6382
|
-
|
|
6383
|
-
cwd: projectDir,
|
|
6384
|
-
timeout: 3e5,
|
|
6385
|
-
// 5 minute timeout for agentic operations
|
|
6386
|
-
env: { ...process.env, NO_COLOR: "1" },
|
|
6387
|
-
reject: false
|
|
6388
|
-
// Don't throw on non-zero exit
|
|
6389
|
-
});
|
|
6390
|
-
stdout = result.stdout || "";
|
|
6391
|
-
stderr = result.stderr || "";
|
|
6440
|
+
} finally {
|
|
6441
|
+
clearTimeout(timeoutId);
|
|
6392
6442
|
}
|
|
6393
6443
|
if (stderr) {
|
|
6394
6444
|
const lowerStderr = stderr.toLowerCase();
|
|
@@ -6539,7 +6589,7 @@ async function startFixTUI(bugs, config, options, cwd) {
|
|
|
6539
6589
|
const handleExit = () => {
|
|
6540
6590
|
resolve6();
|
|
6541
6591
|
};
|
|
6542
|
-
const {
|
|
6592
|
+
const { waitUntilExit } = render(
|
|
6543
6593
|
/* @__PURE__ */ jsx(
|
|
6544
6594
|
App,
|
|
6545
6595
|
{
|
|
@@ -6551,7 +6601,7 @@ async function startFixTUI(bugs, config, options, cwd) {
|
|
|
6551
6601
|
}
|
|
6552
6602
|
)
|
|
6553
6603
|
);
|
|
6554
|
-
waitUntilExit().then(resolve6).catch(
|
|
6604
|
+
waitUntilExit().then(resolve6).catch(() => resolve6());
|
|
6555
6605
|
});
|
|
6556
6606
|
}
|
|
6557
6607
|
|
|
@@ -7002,7 +7052,7 @@ function mapSarifLevel(level) {
|
|
|
7002
7052
|
return "medium";
|
|
7003
7053
|
}
|
|
7004
7054
|
}
|
|
7005
|
-
async function refreshCommand(
|
|
7055
|
+
async function refreshCommand(_options) {
|
|
7006
7056
|
const cwd = process.cwd();
|
|
7007
7057
|
const whiterosePath = join(cwd, ".whiterose");
|
|
7008
7058
|
if (!existsSync(whiterosePath)) {
|
|
@@ -7255,6 +7305,9 @@ async function clearCommand(options) {
|
|
|
7255
7305
|
}
|
|
7256
7306
|
|
|
7257
7307
|
// src/cli/index.ts
|
|
7308
|
+
var __filename$1 = fileURLToPath(import.meta.url);
|
|
7309
|
+
var __dirname$1 = dirname(__filename$1);
|
|
7310
|
+
var pkg = JSON.parse(readFileSync(join(__dirname$1, "../../package.json"), "utf-8"));
|
|
7258
7311
|
process.setMaxListeners(50);
|
|
7259
7312
|
var BANNER = `
|
|
7260
7313
|
${chalk3.red("\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557")}
|
|
@@ -7267,7 +7320,7 @@ ${chalk3.red(" \u255A\u2550\u2550\u255D\u255A\u2550\u2550\u255D \u255A\u2550\u25
|
|
|
7267
7320
|
${chalk3.dim(` "I've been staring at your code for a long time."`)}
|
|
7268
7321
|
`;
|
|
7269
7322
|
var program = new Command();
|
|
7270
|
-
program.name("whiterose").description("AI-powered bug hunter that uses your existing LLM subscription").version(
|
|
7323
|
+
program.name("whiterose").description("AI-powered bug hunter that uses your existing LLM subscription").version(pkg.version).hook("preAction", () => {
|
|
7271
7324
|
const args = process.argv.slice(2);
|
|
7272
7325
|
if (!args.includes("--help") && !args.includes("-h") && args.length > 0) {
|
|
7273
7326
|
console.log(BANNER);
|