wiggum-cli 0.3.2 → 0.4.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.
Files changed (84) hide show
  1. package/README.md +6 -4
  2. package/dist/ai/agents/codebase-analyst.d.ts +3 -0
  3. package/dist/ai/agents/codebase-analyst.d.ts.map +1 -1
  4. package/dist/ai/agents/codebase-analyst.js +3 -0
  5. package/dist/ai/agents/codebase-analyst.js.map +1 -1
  6. package/dist/ai/agents/context-enricher.d.ts +11 -0
  7. package/dist/ai/agents/context-enricher.d.ts.map +1 -0
  8. package/dist/ai/agents/context-enricher.js +163 -0
  9. package/dist/ai/agents/context-enricher.js.map +1 -0
  10. package/dist/ai/agents/evaluator-optimizer.d.ts +13 -0
  11. package/dist/ai/agents/evaluator-optimizer.d.ts.map +1 -0
  12. package/dist/ai/agents/evaluator-optimizer.js +231 -0
  13. package/dist/ai/agents/evaluator-optimizer.js.map +1 -0
  14. package/dist/ai/agents/index.d.ts +21 -3
  15. package/dist/ai/agents/index.d.ts.map +1 -1
  16. package/dist/ai/agents/index.js +148 -86
  17. package/dist/ai/agents/index.js.map +1 -1
  18. package/dist/ai/agents/mcp-detector.d.ts +26 -0
  19. package/dist/ai/agents/mcp-detector.d.ts.map +1 -0
  20. package/dist/ai/agents/mcp-detector.js +186 -0
  21. package/dist/ai/agents/mcp-detector.js.map +1 -0
  22. package/dist/ai/agents/orchestrator.d.ts +3 -0
  23. package/dist/ai/agents/orchestrator.d.ts.map +1 -1
  24. package/dist/ai/agents/orchestrator.js +3 -0
  25. package/dist/ai/agents/orchestrator.js.map +1 -1
  26. package/dist/ai/agents/planning-orchestrator.d.ts +12 -0
  27. package/dist/ai/agents/planning-orchestrator.d.ts.map +1 -0
  28. package/dist/ai/agents/planning-orchestrator.js +133 -0
  29. package/dist/ai/agents/planning-orchestrator.js.map +1 -0
  30. package/dist/ai/agents/stack-researcher.d.ts +3 -0
  31. package/dist/ai/agents/stack-researcher.d.ts.map +1 -1
  32. package/dist/ai/agents/stack-researcher.js +3 -0
  33. package/dist/ai/agents/stack-researcher.js.map +1 -1
  34. package/dist/ai/agents/stack-utils.d.ts +11 -0
  35. package/dist/ai/agents/stack-utils.d.ts.map +1 -0
  36. package/dist/ai/agents/stack-utils.js +27 -0
  37. package/dist/ai/agents/stack-utils.js.map +1 -0
  38. package/dist/ai/agents/synthesis-agent.d.ts +11 -0
  39. package/dist/ai/agents/synthesis-agent.d.ts.map +1 -0
  40. package/dist/ai/agents/synthesis-agent.js +202 -0
  41. package/dist/ai/agents/synthesis-agent.js.map +1 -0
  42. package/dist/ai/agents/tech-researcher.d.ts +16 -0
  43. package/dist/ai/agents/tech-researcher.d.ts.map +1 -0
  44. package/dist/ai/agents/tech-researcher.js +208 -0
  45. package/dist/ai/agents/tech-researcher.js.map +1 -0
  46. package/dist/ai/agents/types.d.ts +127 -0
  47. package/dist/ai/agents/types.d.ts.map +1 -1
  48. package/dist/ai/agents/types.js +6 -0
  49. package/dist/ai/agents/types.js.map +1 -1
  50. package/dist/ai/enhancer.d.ts +4 -0
  51. package/dist/ai/enhancer.d.ts.map +1 -1
  52. package/dist/ai/enhancer.js +3 -0
  53. package/dist/ai/enhancer.js.map +1 -1
  54. package/dist/ai/index.d.ts +1 -1
  55. package/dist/ai/index.d.ts.map +1 -1
  56. package/dist/ai/index.js +14 -2
  57. package/dist/ai/index.js.map +1 -1
  58. package/dist/commands/init.d.ts.map +1 -1
  59. package/dist/commands/init.js +20 -4
  60. package/dist/commands/init.js.map +1 -1
  61. package/dist/utils/tracing.d.ts +5 -0
  62. package/dist/utils/tracing.d.ts.map +1 -1
  63. package/dist/utils/tracing.js +40 -1
  64. package/dist/utils/tracing.js.map +1 -1
  65. package/package.json +5 -2
  66. package/src/ai/agents/codebase-analyst.ts +3 -0
  67. package/src/ai/agents/context-enricher.ts +189 -0
  68. package/src/ai/agents/evaluator-optimizer.ts +277 -0
  69. package/src/ai/agents/index.ts +198 -111
  70. package/src/ai/agents/mcp-detector.test.ts +290 -0
  71. package/src/ai/agents/mcp-detector.ts +210 -0
  72. package/src/ai/agents/orchestrator.ts +3 -0
  73. package/src/ai/agents/planning-orchestrator.ts +140 -0
  74. package/src/ai/agents/stack-researcher.ts +3 -0
  75. package/src/ai/agents/stack-utils.ts +34 -0
  76. package/src/ai/agents/synthesis-agent.ts +240 -0
  77. package/src/ai/agents/tech-researcher.ts +262 -0
  78. package/src/ai/agents/types.ts +160 -0
  79. package/src/ai/enhancer.ts +6 -1
  80. package/src/ai/index.ts +26 -5
  81. package/src/commands/init.ts +20 -4
  82. package/src/utils/tracing.ts +44 -1
  83. package/tsconfig.json +1 -1
  84. package/vitest.config.ts +7 -0
@@ -8,7 +8,7 @@ import type { ScanResult, DetectedStack, DetectionResult } from '../scanner/type
8
8
  import { getModel, type AIProvider, hasApiKey, getApiKeyEnvVar, isReasoningModel } from './providers.js';
9
9
  import { SYSTEM_PROMPT, SYSTEM_PROMPT_AGENTIC, createAnalysisPrompt } from './prompts.js';
10
10
  import { createExplorationTools } from './tools.js';
11
- import { runMultiAgentAnalysis, type MultiAgentAnalysis } from './agents/index.js';
11
+ import { runMultiAgentAnalysis, type MultiAgentAnalysis, type ProgressCallback } from './agents/index.js';
12
12
  import { logger } from '../utils/logger.js';
13
13
  import { parseJsonSafe } from '../utils/json-repair.js';
14
14
  import { getTracedAI, traced } from '../utils/tracing.js';
@@ -116,6 +116,8 @@ export interface EnhancerOptions {
116
116
  tavilyApiKey?: string;
117
117
  /** Context7 API key for documentation lookup (optional) */
118
118
  context7ApiKey?: string;
119
+ /** Progress callback for phase updates */
120
+ onProgress?: ProgressCallback;
119
121
  }
120
122
 
121
123
  /**
@@ -192,6 +194,7 @@ export class AIEnhancer {
192
194
  private agentic: boolean;
193
195
  private tavilyApiKey?: string;
194
196
  private context7ApiKey?: string;
197
+ private onProgress?: ProgressCallback;
195
198
 
196
199
  constructor(options: EnhancerOptions = {}) {
197
200
  this.provider = options.provider || 'anthropic';
@@ -200,6 +203,7 @@ export class AIEnhancer {
200
203
  this.agentic = options.agentic || false;
201
204
  this.tavilyApiKey = options.tavilyApiKey;
202
205
  this.context7ApiKey = options.context7ApiKey;
206
+ this.onProgress = options.onProgress;
203
207
  }
204
208
 
205
209
  /**
@@ -327,6 +331,7 @@ export class AIEnhancer {
327
331
  tavilyApiKey: this.tavilyApiKey,
328
332
  context7ApiKey: this.context7ApiKey,
329
333
  verbose: this.verbose,
334
+ onProgress: this.onProgress,
330
335
  }
331
336
  );
332
337
 
package/src/ai/index.ts CHANGED
@@ -44,19 +44,40 @@ export {
44
44
  canUseContext7,
45
45
  } from './tools/index.js';
46
46
 
47
- // Agents
47
+ // Agents - New 4-phase architecture
48
48
  export {
49
+ // Main orchestration
49
50
  runMultiAgentAnalysis,
50
- runCodebaseAnalyst,
51
- runStackResearcher,
52
- runOrchestrator,
53
- mergeAgentResults,
51
+ // Phase 1: Planning
52
+ runPlanningOrchestrator,
53
+ // Phase 2: Parallel workers
54
+ runContextEnricher,
55
+ runTechResearcher,
56
+ runTechResearchPool,
57
+ // Phase 3: Synthesis + MCP detection
58
+ runSynthesisAgent,
59
+ detectRalphMcpServers,
60
+ convertToLegacyMcpRecommendations,
61
+ // Phase 4: QA loop
62
+ runEvaluatorOptimizer,
63
+ // New types
64
+ type AnalysisPlan,
65
+ type EnrichedContext,
66
+ type TechResearchResult,
67
+ type RalphMcpServers,
68
+ type EvaluationResult,
69
+ // Legacy types (backward compatibility)
54
70
  type CodebaseAnalysis,
55
71
  type StackResearch,
56
72
  type McpRecommendations,
57
73
  type MultiAgentAnalysis,
58
74
  type AgentCapabilities,
59
75
  type AgentOptions,
76
+ // Legacy agents (deprecated, kept for backward compatibility)
77
+ runCodebaseAnalyst,
78
+ runStackResearcher,
79
+ runOrchestrator,
80
+ mergeAgentResults,
60
81
  } from './agents/index.js';
61
82
 
62
83
  // AI enhancer
@@ -26,6 +26,7 @@ import pc from 'picocolors';
26
26
  import fs from 'fs';
27
27
  import path from 'path';
28
28
  import { simpson, sectionHeader, drawLine } from '../utils/colors.js';
29
+ import { flushTracing } from '../utils/tracing.js';
29
30
 
30
31
  export interface InitOptions {
31
32
  provider?: AIProvider;
@@ -109,8 +110,8 @@ async function collectApiKeys(
109
110
  const providerChoice = await prompts.select({
110
111
  message: 'Select your AI provider:',
111
112
  options: [
112
- { value: 'anthropic', label: 'Anthropic (Claude)', hint: 'recommended' },
113
- { value: 'openai', label: 'OpenAI (GPT-4/5)' },
113
+ { value: 'anthropic', label: 'Anthropic', hint: 'recommended' },
114
+ { value: 'openai', label: 'OpenAI' },
114
115
  { value: 'openrouter', label: 'OpenRouter', hint: 'multiple providers' },
115
116
  ],
116
117
  });
@@ -261,6 +262,7 @@ export async function initCommand(options: InitOptions): Promise<void> {
261
262
  if (!apiKeys) {
262
263
  // In --yes mode, null means missing API key (hard failure)
263
264
  // In interactive mode, null means user cancelled
265
+ await flushTracing();
264
266
  if (options.yes) {
265
267
  process.exit(1);
266
268
  }
@@ -281,6 +283,7 @@ export async function initCommand(options: InitOptions): Promise<void> {
281
283
  } catch (error) {
282
284
  spinner.stop('Scan failed');
283
285
  logger.error(`Failed to scan project: ${error instanceof Error ? error.message : String(error)}`);
286
+ await flushTracing();
284
287
  process.exit(1);
285
288
  }
286
289
 
@@ -297,15 +300,23 @@ export async function initCommand(options: InitOptions): Promise<void> {
297
300
  console.log(pc.dim(`Capabilities: ${capabilities.join(' • ')}`));
298
301
  console.log('');
299
302
 
300
- spinner.start('Running AI analysis...');
303
+ spinner.start('Starting AI analysis...');
301
304
 
302
305
  const aiEnhancer = new AIEnhancer({
303
306
  provider: apiKeys.provider,
304
307
  model: apiKeys.model,
305
- verbose: true,
308
+ verbose: false, // Disable verbose logging when using progress callback
306
309
  agentic: true, // Always use agentic mode for deeper analysis
307
310
  tavilyApiKey: apiKeys.tavilyKey,
308
311
  context7ApiKey: apiKeys.context7Key,
312
+ onProgress: (phase, detail) => {
313
+ // Update spinner with current phase
314
+ if (detail) {
315
+ spinner.message(`${phase} - ${detail}`);
316
+ } else {
317
+ spinner.message(phase);
318
+ }
319
+ },
309
320
  });
310
321
 
311
322
  let enhancedResult: EnhancedScanResult;
@@ -342,6 +353,7 @@ export async function initCommand(options: InitOptions): Promise<void> {
342
353
  });
343
354
 
344
355
  if (prompts.isCancel(shouldContinue) || !shouldContinue) {
356
+ await flushTracing();
345
357
  logger.info('Initialization cancelled');
346
358
  return;
347
359
  }
@@ -365,6 +377,9 @@ export async function initCommand(options: InitOptions): Promise<void> {
365
377
  console.log(simpson.yellow('─── Generation Results ───'));
366
378
  console.log(formatGenerationResult(generationResult));
367
379
 
380
+ // Flush tracing spans before completing
381
+ await flushTracing();
382
+
368
383
  if (generationResult.success) {
369
384
  console.log('');
370
385
  logger.success('Ralph initialized successfully!');
@@ -380,6 +395,7 @@ export async function initCommand(options: InitOptions): Promise<void> {
380
395
  } catch (error) {
381
396
  spinner.stop('Generation failed');
382
397
  logger.error(`Failed to generate files: ${error instanceof Error ? error.message : String(error)}`);
398
+ await flushTracing();
383
399
  process.exit(1);
384
400
  }
385
401
  }
@@ -3,7 +3,7 @@
3
3
  * Provides AI call tracing for debugging and analysis
4
4
  */
5
5
 
6
- import { initLogger, wrapAISDK } from 'braintrust';
6
+ import { initLogger, wrapAISDK, flush as braintrustFlush } from 'braintrust';
7
7
  import * as ai from 'ai';
8
8
 
9
9
  // Re-export traced utilities
@@ -13,6 +13,7 @@ export { traced, currentSpan, wrapTraced } from 'braintrust';
13
13
  * Initialize Braintrust logger if API key is available
14
14
  */
15
15
  let loggerInitialized = false;
16
+ let exitHandlersRegistered = false;
16
17
 
17
18
  export function initTracing(): void {
18
19
  if (loggerInitialized) return;
@@ -29,11 +30,53 @@ export function initTracing(): void {
29
30
  projectName: process.env.BRAINTRUST_PROJECT_NAME || 'wiggum-cli',
30
31
  });
31
32
  loggerInitialized = true;
33
+
34
+ // Register exit handlers to flush spans before process exits
35
+ registerExitHandlers();
32
36
  } catch {
33
37
  // Silently fail if tracing can't be initialized
34
38
  }
35
39
  }
36
40
 
41
+ /**
42
+ * Register process exit handlers to flush tracing spans
43
+ */
44
+ function registerExitHandlers(): void {
45
+ if (exitHandlersRegistered) return;
46
+ exitHandlersRegistered = true;
47
+
48
+ // Flush on normal exit
49
+ process.on('beforeExit', async () => {
50
+ await flushTracing();
51
+ });
52
+
53
+ // Flush on SIGINT (Ctrl+C)
54
+ process.on('SIGINT', async () => {
55
+ await flushTracing();
56
+ process.exit(0);
57
+ });
58
+
59
+ // Flush on SIGTERM
60
+ process.on('SIGTERM', async () => {
61
+ await flushTracing();
62
+ process.exit(0);
63
+ });
64
+ }
65
+
66
+ /**
67
+ * Flush all pending tracing spans to Braintrust
68
+ * Call this before process exit to ensure all spans are recorded
69
+ */
70
+ export async function flushTracing(): Promise<void> {
71
+ if (!loggerInitialized) return;
72
+
73
+ try {
74
+ await braintrustFlush();
75
+ } catch {
76
+ // Silently fail if flush fails
77
+ }
78
+ }
79
+
37
80
  /**
38
81
  * Check if tracing is enabled
39
82
  */
package/tsconfig.json CHANGED
@@ -15,5 +15,5 @@
15
15
  "resolveJsonModule": true
16
16
  },
17
17
  "include": ["src/**/*"],
18
- "exclude": ["node_modules", "dist"]
18
+ "exclude": ["node_modules", "dist", "**/*.test.ts"]
19
19
  }
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ include: ['src/**/*.test.ts'],
6
+ },
7
+ });