@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 CHANGED
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import { existsSync, mkdirSync, writeFileSync, readdirSync, readFileSync, statSync, rmSync, mkdtempSync, realpathSync } from 'fs';
3
- import { join, isAbsolute, resolve, basename, relative, dirname } from 'path';
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+([^\[\n]+)(?:\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((input, key) => {
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 args = [];
6326
- if (config.provider === "claude-code") {
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
- if (config.provider === "codex") {
6338
- const tempDir = mkdtempSync(join(tmpdir(), "whiterose-fix-"));
6339
- const outputFile = join(tempDir, "output.txt");
6340
- try {
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
- } else {
6382
- const result = await execa(providerCommand, args, {
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 { unmount, waitUntilExit } = render(
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(reject);
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(options) {
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("0.2.7").hook("preAction", () => {
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);