@wundam/orchex 1.0.0-rc.22 → 1.0.0-rc.24

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.js CHANGED
@@ -4,6 +4,7 @@ import { exec as execChildProcess } from 'child_process';
4
4
  import { registerTools, setProjectDir } from './tools.js';
5
5
  import { ORCHEX_INSTRUCTIONS } from './mcp-instructions.js';
6
6
  import { registerResources } from './mcp-resources.js';
7
+ import { broadcaster } from './execution-broadcaster.js';
7
8
  import { loadConfig, saveConfig, maskConfigForDisplay, resolveApiUrl, PRODUCTION_URL, LLMProviderSchema } from './config.js';
8
9
  import { buildVerificationMessage, buildStatusMessage, parseLoginApiResponse, } from './login-helpers.js';
9
10
  /** Opens browser cross-platform. Errors are silently ignored — URL already printed to terminal. */
@@ -381,6 +382,7 @@ async function handleRunCommand(args) {
381
382
  // Parse flags
382
383
  let providerFlag;
383
384
  let modelFlag;
385
+ let planFileFlag;
384
386
  let autoApprove = false;
385
387
  let dryRun = false;
386
388
  let projectDir = process.cwd();
@@ -404,13 +406,16 @@ async function handleRunCommand(args) {
404
406
  case '--project-dir':
405
407
  projectDir = args[++i];
406
408
  break;
409
+ case '--plan-file':
410
+ planFileFlag = args[++i];
411
+ break;
407
412
  default:
408
413
  if (!flag.startsWith('--')) {
409
414
  positionalArgs.push(flag);
410
415
  }
411
416
  else {
412
417
  console.error(`Unknown flag: ${flag}`);
413
- console.error('Usage: orchex run "intent" [--yes] [--dry-run] [--provider NAME] [--model NAME]');
418
+ console.error('Usage: orchex run "intent" [--yes] [--dry-run] [--provider NAME] [--model NAME] [--plan-file PATH]');
414
419
  process.exit(1);
415
420
  }
416
421
  }
@@ -499,14 +504,29 @@ async function handleRunCommand(args) {
499
504
  effectiveTier = getEffectiveLimits(effectiveTierId, null);
500
505
  }
501
506
  const maxStreams = effectiveTier.maxParallelAgents === -1 ? undefined : effectiveTier.maxParallelAgents;
502
- // Generate plan
507
+ // Generate plan (or load from file)
503
508
  let planResult;
504
- try {
505
- planResult = await generatePlan(intent, projectDir, exec, { model: modelFlag, provider: resolvedProvider, maxStreams });
509
+ if (planFileFlag) {
510
+ const { readFile } = await import('node:fs/promises');
511
+ const planPath = await import('node:path').then(p => p.resolve(projectDir, planFileFlag));
512
+ try {
513
+ const planMarkdown = await readFile(planPath, 'utf-8');
514
+ planResult = { planMarkdown, tokensUsed: { input: 0, output: 0 } };
515
+ console.log(`Using plan file: ${planFileFlag}`);
516
+ }
517
+ catch (err) {
518
+ console.error(`Failed to read plan file "${planFileFlag}": ${err.message}`);
519
+ process.exit(1);
520
+ }
506
521
  }
507
- catch (err) {
508
- console.error(`Plan generation failed: ${err.message}`);
509
- process.exit(1);
522
+ else {
523
+ try {
524
+ planResult = await generatePlan(intent, projectDir, exec, { model: modelFlag, provider: resolvedProvider, maxStreams });
525
+ }
526
+ catch (err) {
527
+ console.error(`Plan generation failed: ${err.message}`);
528
+ process.exit(1);
529
+ }
510
530
  }
511
531
  // Run through learn pipeline
512
532
  const diagnostics = createDiagnostics();
@@ -606,12 +626,34 @@ async function handleRunCommand(args) {
606
626
  let done = false;
607
627
  let waveNum = 1;
608
628
  while (!done) {
609
- console.log(`Executing wave ${waveNum}...`);
629
+ // Subscribe to broadcaster for per-stream progress during this wave
630
+ const orchestrationId = plan.title;
631
+ const cliProgressListener = (event) => {
632
+ switch (event.type) {
633
+ case 'stream_started':
634
+ process.stdout.write(` ⟳ ${event.data.streamId} — running...\n`);
635
+ break;
636
+ case 'stream_completed': {
637
+ const dur = event.data.duration ? ` (${Math.round(event.data.duration / 1000)}s)` : '';
638
+ process.stdout.write(` ✓ ${event.data.streamId} — complete${dur}\n`);
639
+ break;
640
+ }
641
+ case 'stream_failed':
642
+ process.stdout.write(` ✗ ${event.data.streamId} — failed: ${String(event.data.error).slice(0, 100)}\n`);
643
+ break;
644
+ case 'stream_rate_limited':
645
+ process.stdout.write(` ⏳ ${event.data.streamId} — rate limited (retry in ${Math.round((event.data.retryAfterMs ?? 0) / 1000)}s)\n`);
646
+ break;
647
+ }
648
+ };
649
+ broadcaster.subscribe(orchestrationId, cliProgressListener);
650
+ console.log(`\nExecuting wave ${waveNum}...`);
610
651
  const response = await executeWave(projectDir, exec, { model: modelFlag });
611
652
  allResponses.push(response);
653
+ broadcaster.unsubscribe(orchestrationId, cliProgressListener);
612
654
  const completed = response.streams.filter(s => s.status === 'complete').length;
613
655
  const failed = response.streams.filter(s => s.status === 'failed').length;
614
- console.log(` Wave ${waveNum}: ${completed} complete, ${failed} failed`);
656
+ console.log(` Wave ${waveNum} summary: ${completed} complete, ${failed} failed`);
615
657
  done = response.done;
616
658
  waveNum++;
617
659
  }
@@ -27,7 +27,7 @@ export type { InteractiveSuggestion } from './split-suggester.js';
27
27
  export { autoMergeOwnershipConflicts } from './ownership-resolver.js';
28
28
  export { suggestProvider, classifyTask } from './model-routing.js';
29
29
  export { applyPartialApproval, rollbackStream } from './interactive-approval.js';
30
- export { generateFixStream } from './self-healer.js';
30
+ export { generateFixStream, generateRootCauseFixStream, analyzeFailureCorrelation, detectUpstreamSuspect, type FailureCorrelation, type UpstreamSuspect } from './self-healer.js';
31
31
  export { cleanupOrphanFixStreams, getFixChainInfo, isFixStream, getOriginalStreamId, onStreamComplete } from './fix-stream-manager.js';
32
32
  export { routeStream, loadRoutingRules } from './smart-router.js';
33
33
  export type { RouteDecision, RouteOptions } from './smart-router.js';