@shakecodeslikecray/whiterose 1.0.3 → 1.0.5

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/index.d.ts CHANGED
@@ -1048,7 +1048,20 @@ declare class CoreScanner {
1048
1048
  private executor;
1049
1049
  private config;
1050
1050
  private progress;
1051
+ private passErrors;
1051
1052
  constructor(executor: PromptExecutor, config?: Partial<ScannerConfig>, progress?: ScanProgress);
1053
+ /**
1054
+ * Get errors that occurred during the last scan.
1055
+ * Returns an array of pass names and their error messages.
1056
+ */
1057
+ getPassErrors(): Array<{
1058
+ passName: string;
1059
+ error: string;
1060
+ }>;
1061
+ /**
1062
+ * Check if any passes failed during the last scan.
1063
+ */
1064
+ hasPassErrors(): boolean;
1052
1065
  /**
1053
1066
  * Run a thorough 19-pass scan with findings flowing through pipeline:
1054
1067
  *
@@ -1213,6 +1226,7 @@ declare function mergeIntentWithUnderstanding(understanding: CodebaseUnderstandi
1213
1226
  interface FixOptions {
1214
1227
  dryRun: boolean;
1215
1228
  branch?: string;
1229
+ onProgress?: (message: string) => void;
1216
1230
  }
1217
1231
  interface FixResult {
1218
1232
  success: boolean;
package/dist/index.js CHANGED
@@ -2463,11 +2463,25 @@ var CoreScanner = class {
2463
2463
  executor;
2464
2464
  config;
2465
2465
  progress;
2466
+ passErrors = [];
2466
2467
  constructor(executor, config = {}, progress = {}) {
2467
2468
  this.executor = executor;
2468
2469
  this.config = { ...DEFAULT_SCANNER_CONFIG, ...config };
2469
2470
  this.progress = progress;
2470
2471
  }
2472
+ /**
2473
+ * Get errors that occurred during the last scan.
2474
+ * Returns an array of pass names and their error messages.
2475
+ */
2476
+ getPassErrors() {
2477
+ return this.passErrors;
2478
+ }
2479
+ /**
2480
+ * Check if any passes failed during the last scan.
2481
+ */
2482
+ hasPassErrors() {
2483
+ return this.passErrors.length > 0;
2484
+ }
2471
2485
  /**
2472
2486
  * Run a thorough 19-pass scan with findings flowing through pipeline:
2473
2487
  *
@@ -2481,6 +2495,7 @@ var CoreScanner = class {
2481
2495
  async scan(context) {
2482
2496
  const cwd = process.cwd();
2483
2497
  const startTime = Date.now();
2498
+ this.passErrors = [];
2484
2499
  const pipeline = getFullAnalysisPipeline();
2485
2500
  const unitPasses = pipeline[0].passes;
2486
2501
  const integrationPasses = pipeline[1].passes;
@@ -2561,8 +2576,10 @@ var CoreScanner = class {
2561
2576
  this.report(` \u2713 ${pass.name}: ${bugs.length} bugs`);
2562
2577
  return bugs;
2563
2578
  } catch (error) {
2564
- this.progress.onPassError?.(pass.name, error.message);
2565
- this.report(` \u2717 ${pass.name}: ${error.message}`);
2579
+ const errorMsg = error.message || String(error);
2580
+ this.progress.onPassError?.(pass.name, errorMsg);
2581
+ this.report(` \u2717 ${pass.name}: ${errorMsg}`);
2582
+ this.passErrors.push({ passName: pass.name, error: errorMsg });
2566
2583
  return [];
2567
2584
  }
2568
2585
  });
@@ -3979,7 +3996,7 @@ In: ${bug.file}:${bug.line}`
3979
3996
  }
3980
3997
  let agenticResult;
3981
3998
  try {
3982
- agenticResult = await runAgenticFix(bug, config, projectDir);
3999
+ agenticResult = await runAgenticFix(bug, config, projectDir, options.onProgress);
3983
4000
  } catch (error) {
3984
4001
  return {
3985
4002
  success: false,
@@ -4019,7 +4036,7 @@ In: ${bug.file}:${bug.line}`
4019
4036
  commitHash
4020
4037
  };
4021
4038
  }
4022
- async function runAgenticFix(bug, config, projectDir) {
4039
+ async function runAgenticFix(bug, config, projectDir, onProgress) {
4023
4040
  const providerCommand = getProviderCommand(config.provider);
4024
4041
  const prompt = buildAgenticFixPrompt(bug);
4025
4042
  const controller = new AbortController();
@@ -4073,9 +4090,13 @@ async function runAgenticFix(bug, config, projectDir) {
4073
4090
  }
4074
4091
  }
4075
4092
  } else if (config.provider === "claude-code") {
4076
- const result = await execa(
4093
+ const args = ["--dangerously-skip-permissions", "-p"];
4094
+ if (onProgress) {
4095
+ args.push("--verbose", "--output-format", "stream-json");
4096
+ }
4097
+ const subprocess = execa(
4077
4098
  providerCommand,
4078
- ["--dangerously-skip-permissions", "-p"],
4099
+ args,
4079
4100
  {
4080
4101
  cwd: projectDir,
4081
4102
  input: prompt,
@@ -4086,6 +4107,43 @@ async function runAgenticFix(bug, config, projectDir) {
4086
4107
  cancelSignal: controller.signal
4087
4108
  }
4088
4109
  );
4110
+ if (onProgress && subprocess.stdout) {
4111
+ let lineBuffer = "";
4112
+ subprocess.stdout.on("data", (chunk) => {
4113
+ const text = chunk.toString();
4114
+ lineBuffer += text;
4115
+ const lines = lineBuffer.split("\n");
4116
+ lineBuffer = lines.pop() || "";
4117
+ for (const line of lines) {
4118
+ const trimmed = line.trim();
4119
+ if (trimmed) {
4120
+ try {
4121
+ const event = JSON.parse(trimmed);
4122
+ if (event.type === "assistant" && event.message?.content) {
4123
+ for (const block of event.message.content) {
4124
+ if (block.type === "tool_use") {
4125
+ const toolName = block.name || "tool";
4126
+ const friendlyNames = {
4127
+ "Read": "Reading file",
4128
+ "Edit": "Editing file",
4129
+ "Write": "Writing file",
4130
+ "Bash": "Running command",
4131
+ "Glob": "Searching files",
4132
+ "Grep": "Searching content",
4133
+ "Task": "Running task"
4134
+ };
4135
+ const displayName = friendlyNames[toolName] || `Using ${toolName}`;
4136
+ onProgress(`${displayName}...`);
4137
+ }
4138
+ }
4139
+ }
4140
+ } catch {
4141
+ }
4142
+ }
4143
+ }
4144
+ });
4145
+ }
4146
+ const result = await subprocess;
4089
4147
  stdout = result.stdout || "";
4090
4148
  stderr = result.stderr || "";
4091
4149
  } else if (config.provider === "gemini") {