@hyperdrive.bot/bmad-workflow 1.0.2
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/LICENSE +21 -0
- package/README.md +1017 -0
- package/bin/dev +5 -0
- package/bin/dev.cmd +3 -0
- package/bin/dev.js +5 -0
- package/bin/run +5 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +5 -0
- package/dist/commands/config/show.d.ts +34 -0
- package/dist/commands/config/show.js +108 -0
- package/dist/commands/config/validate.d.ts +29 -0
- package/dist/commands/config/validate.js +131 -0
- package/dist/commands/decompose.d.ts +79 -0
- package/dist/commands/decompose.js +327 -0
- package/dist/commands/demo.d.ts +18 -0
- package/dist/commands/demo.js +107 -0
- package/dist/commands/epics/create.d.ts +123 -0
- package/dist/commands/epics/create.js +459 -0
- package/dist/commands/epics/list.d.ts +120 -0
- package/dist/commands/epics/list.js +280 -0
- package/dist/commands/hello/index.d.ts +12 -0
- package/dist/commands/hello/index.js +34 -0
- package/dist/commands/hello/world.d.ts +8 -0
- package/dist/commands/hello/world.js +24 -0
- package/dist/commands/prd/fix.d.ts +39 -0
- package/dist/commands/prd/fix.js +140 -0
- package/dist/commands/prd/validate.d.ts +112 -0
- package/dist/commands/prd/validate.js +302 -0
- package/dist/commands/stories/create.d.ts +95 -0
- package/dist/commands/stories/create.js +431 -0
- package/dist/commands/stories/develop.d.ts +91 -0
- package/dist/commands/stories/develop.js +460 -0
- package/dist/commands/stories/list.d.ts +84 -0
- package/dist/commands/stories/list.js +291 -0
- package/dist/commands/stories/move.d.ts +66 -0
- package/dist/commands/stories/move.js +273 -0
- package/dist/commands/stories/qa.d.ts +99 -0
- package/dist/commands/stories/qa.js +530 -0
- package/dist/commands/workflow.d.ts +97 -0
- package/dist/commands/workflow.js +390 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/models/agent-options.d.ts +50 -0
- package/dist/models/agent-options.js +1 -0
- package/dist/models/agent-result.d.ts +29 -0
- package/dist/models/agent-result.js +1 -0
- package/dist/models/index.d.ts +10 -0
- package/dist/models/index.js +10 -0
- package/dist/models/phase-result.d.ts +65 -0
- package/dist/models/phase-result.js +7 -0
- package/dist/models/provider.d.ts +28 -0
- package/dist/models/provider.js +18 -0
- package/dist/models/story.d.ts +154 -0
- package/dist/models/story.js +18 -0
- package/dist/models/workflow-config.d.ts +148 -0
- package/dist/models/workflow-config.js +1 -0
- package/dist/models/workflow-result.d.ts +164 -0
- package/dist/models/workflow-result.js +7 -0
- package/dist/services/agents/agent-runner-factory.d.ts +31 -0
- package/dist/services/agents/agent-runner-factory.js +44 -0
- package/dist/services/agents/agent-runner.d.ts +46 -0
- package/dist/services/agents/agent-runner.js +29 -0
- package/dist/services/agents/claude-agent-runner.d.ts +81 -0
- package/dist/services/agents/claude-agent-runner.js +332 -0
- package/dist/services/agents/gemini-agent-runner.d.ts +82 -0
- package/dist/services/agents/gemini-agent-runner.js +350 -0
- package/dist/services/agents/index.d.ts +7 -0
- package/dist/services/agents/index.js +7 -0
- package/dist/services/file-system/file-manager.d.ts +110 -0
- package/dist/services/file-system/file-manager.js +223 -0
- package/dist/services/file-system/glob-matcher.d.ts +75 -0
- package/dist/services/file-system/glob-matcher.js +126 -0
- package/dist/services/file-system/path-resolver.d.ts +183 -0
- package/dist/services/file-system/path-resolver.js +400 -0
- package/dist/services/logging/workflow-logger.d.ts +232 -0
- package/dist/services/logging/workflow-logger.js +552 -0
- package/dist/services/orchestration/batch-processor.d.ts +113 -0
- package/dist/services/orchestration/batch-processor.js +187 -0
- package/dist/services/orchestration/dependency-graph-executor.d.ts +60 -0
- package/dist/services/orchestration/dependency-graph-executor.js +447 -0
- package/dist/services/orchestration/index.d.ts +10 -0
- package/dist/services/orchestration/index.js +8 -0
- package/dist/services/orchestration/input-detector.d.ts +125 -0
- package/dist/services/orchestration/input-detector.js +381 -0
- package/dist/services/orchestration/story-queue.d.ts +94 -0
- package/dist/services/orchestration/story-queue.js +170 -0
- package/dist/services/orchestration/story-type-detector.d.ts +80 -0
- package/dist/services/orchestration/story-type-detector.js +258 -0
- package/dist/services/orchestration/task-decomposition-service.d.ts +67 -0
- package/dist/services/orchestration/task-decomposition-service.js +607 -0
- package/dist/services/orchestration/workflow-orchestrator.d.ts +659 -0
- package/dist/services/orchestration/workflow-orchestrator.js +2201 -0
- package/dist/services/parsers/epic-parser.d.ts +117 -0
- package/dist/services/parsers/epic-parser.js +264 -0
- package/dist/services/parsers/prd-fixer.d.ts +86 -0
- package/dist/services/parsers/prd-fixer.js +194 -0
- package/dist/services/parsers/prd-parser.d.ts +123 -0
- package/dist/services/parsers/prd-parser.js +286 -0
- package/dist/services/parsers/standalone-story-parser.d.ts +114 -0
- package/dist/services/parsers/standalone-story-parser.js +255 -0
- package/dist/services/parsers/story-parser-factory.d.ts +81 -0
- package/dist/services/parsers/story-parser-factory.js +108 -0
- package/dist/services/parsers/story-parser.d.ts +122 -0
- package/dist/services/parsers/story-parser.js +262 -0
- package/dist/services/scaffolding/decompose-session-scaffolder.d.ts +74 -0
- package/dist/services/scaffolding/decompose-session-scaffolder.js +315 -0
- package/dist/services/scaffolding/file-scaffolder.d.ts +94 -0
- package/dist/services/scaffolding/file-scaffolder.js +314 -0
- package/dist/services/validation/config-validator.d.ts +88 -0
- package/dist/services/validation/config-validator.js +167 -0
- package/dist/types/task-graph.d.ts +142 -0
- package/dist/types/task-graph.js +5 -0
- package/dist/utils/colors.d.ts +49 -0
- package/dist/utils/colors.js +50 -0
- package/dist/utils/error-formatter.d.ts +64 -0
- package/dist/utils/error-formatter.js +279 -0
- package/dist/utils/errors.d.ts +170 -0
- package/dist/utils/errors.js +233 -0
- package/dist/utils/formatters.d.ts +84 -0
- package/dist/utils/formatters.js +162 -0
- package/dist/utils/logger.d.ts +63 -0
- package/dist/utils/logger.js +78 -0
- package/dist/utils/progress.d.ts +104 -0
- package/dist/utils/progress.js +161 -0
- package/dist/utils/retry.d.ts +114 -0
- package/dist/utils/retry.js +160 -0
- package/dist/utils/shared-flags.d.ts +28 -0
- package/dist/utils/shared-flags.js +43 -0
- package/package.json +119 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Graph System Types
|
|
3
|
+
* Defines the structure for decomposing large goals into executable task graphs
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Individual task node in the dependency graph
|
|
7
|
+
*/
|
|
8
|
+
export interface TaskNode {
|
|
9
|
+
/** Optional: Agent type to use (dev, architect, qa, etc.) */
|
|
10
|
+
agentType?: string;
|
|
11
|
+
/** Array of task IDs that must complete before this task can start */
|
|
12
|
+
dependencies: string[];
|
|
13
|
+
/** Detailed description of what this task accomplishes */
|
|
14
|
+
description: string;
|
|
15
|
+
/** Estimated time in minutes for Claude agent to complete */
|
|
16
|
+
estimatedMinutes: number;
|
|
17
|
+
/** Unique task identifier (e.g., "task-001") */
|
|
18
|
+
id: string;
|
|
19
|
+
/** File path where task output will be written */
|
|
20
|
+
outputFile: string;
|
|
21
|
+
/** Whether this task can run in parallel with other tasks in the same layer */
|
|
22
|
+
parallelizable: boolean;
|
|
23
|
+
/** Full prompt for the agent to execute this task */
|
|
24
|
+
prompt: string;
|
|
25
|
+
/** Optional: Specific files this task operates on (for per-file tasks) */
|
|
26
|
+
targetFiles?: string[];
|
|
27
|
+
/** Human-readable task title */
|
|
28
|
+
title: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Complete task graph representing a decomposed goal
|
|
32
|
+
*/
|
|
33
|
+
export interface TaskGraph {
|
|
34
|
+
/** The original big goal being decomposed */
|
|
35
|
+
goal: string;
|
|
36
|
+
/** Master prompt template reusable across similar goals */
|
|
37
|
+
masterPrompt: string;
|
|
38
|
+
/** Metadata about the task graph */
|
|
39
|
+
metadata: TaskGraphMetadata;
|
|
40
|
+
/** Session-specific information */
|
|
41
|
+
session: {
|
|
42
|
+
createdAt: string;
|
|
43
|
+
id: string;
|
|
44
|
+
outputDirectory: string;
|
|
45
|
+
};
|
|
46
|
+
/** Array of all tasks in the graph */
|
|
47
|
+
tasks: TaskNode[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Metadata about the task graph
|
|
51
|
+
*/
|
|
52
|
+
export interface TaskGraphMetadata {
|
|
53
|
+
/** Estimated total duration in minutes */
|
|
54
|
+
estimatedDuration: number;
|
|
55
|
+
/** Execution layers (each layer runs in parallel, layers run sequentially) */
|
|
56
|
+
executionLayers: string[][];
|
|
57
|
+
/** Maximum number of tasks that can run in parallel */
|
|
58
|
+
maxParallelism: number;
|
|
59
|
+
/** Whether per-file task generation was used */
|
|
60
|
+
perFileMode: boolean;
|
|
61
|
+
/** Whether tasks are formatted as BMAD stories */
|
|
62
|
+
storyFormat?: boolean;
|
|
63
|
+
/** Optional: Total files targeted for per-file mode */
|
|
64
|
+
totalFiles?: number;
|
|
65
|
+
/** Total number of tasks */
|
|
66
|
+
totalTasks: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Result of executing a single task
|
|
70
|
+
*/
|
|
71
|
+
export interface TaskExecutionResult {
|
|
72
|
+
duration: number;
|
|
73
|
+
errors?: string;
|
|
74
|
+
exitCode: number;
|
|
75
|
+
output: string;
|
|
76
|
+
success: boolean;
|
|
77
|
+
taskId: string;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Result of executing entire task graph
|
|
81
|
+
*/
|
|
82
|
+
export interface GraphExecutionResult {
|
|
83
|
+
completedTasks: number;
|
|
84
|
+
executionSummary: {
|
|
85
|
+
layerResults: LayerExecutionResult[];
|
|
86
|
+
};
|
|
87
|
+
failedTasks: number;
|
|
88
|
+
skippedTasks: number;
|
|
89
|
+
success: boolean;
|
|
90
|
+
taskResults: TaskExecutionResult[];
|
|
91
|
+
totalDuration: number;
|
|
92
|
+
totalTasks: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Result of executing a single layer
|
|
96
|
+
*/
|
|
97
|
+
export interface LayerExecutionResult {
|
|
98
|
+
duration: number;
|
|
99
|
+
layerIndex: number;
|
|
100
|
+
parallelTasksExecuted: number;
|
|
101
|
+
success: boolean;
|
|
102
|
+
taskIds: string[];
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Options for task decomposition
|
|
106
|
+
*/
|
|
107
|
+
export interface DecomposeOptions {
|
|
108
|
+
/** BMAD agent to use for planning/decomposition */
|
|
109
|
+
agent?: string;
|
|
110
|
+
/** Optional context files to provide to the planner */
|
|
111
|
+
contextFiles?: string[];
|
|
112
|
+
/** Working directory for task execution */
|
|
113
|
+
cwd?: string;
|
|
114
|
+
/** Execute immediately without confirmation */
|
|
115
|
+
execute?: boolean;
|
|
116
|
+
/** File glob pattern for per-file mode (e.g., "src/*.js") */
|
|
117
|
+
filePattern?: string;
|
|
118
|
+
/** The big goal to decompose */
|
|
119
|
+
goal: string;
|
|
120
|
+
/** Maximum number of tasks to run in parallel */
|
|
121
|
+
maxParallel?: number;
|
|
122
|
+
/** Enable per-file task generation for file-heavy operations */
|
|
123
|
+
perFile?: boolean;
|
|
124
|
+
/** Plan only without executing */
|
|
125
|
+
planOnly?: boolean;
|
|
126
|
+
/** Format tasks as proper BMAD stories instead of simple tasks */
|
|
127
|
+
storyFormat?: boolean;
|
|
128
|
+
/** Project prefix for story IDs (e.g., "MIGRATE", "REFACTOR") - required when storyFormat is true */
|
|
129
|
+
storyPrefix?: string;
|
|
130
|
+
/** Timeout per task in milliseconds */
|
|
131
|
+
taskTimeout?: number;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Configuration for the decompose session
|
|
135
|
+
*/
|
|
136
|
+
export interface DecomposeSessionConfig {
|
|
137
|
+
createdAt: Date;
|
|
138
|
+
goal: string;
|
|
139
|
+
options: DecomposeOptions;
|
|
140
|
+
outputDir: string;
|
|
141
|
+
sessionId: string;
|
|
142
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a success message with green color and checkmark icon
|
|
3
|
+
*
|
|
4
|
+
* @param text - Message text to format
|
|
5
|
+
* @returns Formatted string with ANSI color codes and ✓ icon
|
|
6
|
+
*/
|
|
7
|
+
export declare const success: (text: string) => string;
|
|
8
|
+
/**
|
|
9
|
+
* Format an error message with red color and X icon
|
|
10
|
+
*
|
|
11
|
+
* @param text - Message text to format
|
|
12
|
+
* @returns Formatted string with ANSI color codes and ✗ icon
|
|
13
|
+
*/
|
|
14
|
+
export declare const error: (text: string) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Format a warning message with yellow color and warning icon
|
|
17
|
+
*
|
|
18
|
+
* @param text - Message text to format
|
|
19
|
+
* @returns Formatted string with ANSI color codes and ⚠ icon
|
|
20
|
+
*/
|
|
21
|
+
export declare const warning: (text: string) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Format an info message with blue color and info icon
|
|
24
|
+
*
|
|
25
|
+
* @param text - Message text to format
|
|
26
|
+
* @returns Formatted string with ANSI color codes and ℹ icon
|
|
27
|
+
*/
|
|
28
|
+
export declare const info: (text: string) => string;
|
|
29
|
+
/**
|
|
30
|
+
* Highlight text with cyan color for emphasis
|
|
31
|
+
*
|
|
32
|
+
* @param text - Text to highlight
|
|
33
|
+
* @returns Formatted string with ANSI color codes
|
|
34
|
+
*/
|
|
35
|
+
export declare const highlight: (text: string) => string;
|
|
36
|
+
/**
|
|
37
|
+
* Format text in bold style
|
|
38
|
+
*
|
|
39
|
+
* @param text - Text to make bold
|
|
40
|
+
* @returns Formatted string with ANSI bold codes
|
|
41
|
+
*/
|
|
42
|
+
export declare const bold: (text: string) => string;
|
|
43
|
+
/**
|
|
44
|
+
* Format text in dim style (lower intensity)
|
|
45
|
+
*
|
|
46
|
+
* @param text - Text to dim
|
|
47
|
+
* @returns Formatted string with ANSI dim codes
|
|
48
|
+
*/
|
|
49
|
+
export declare const dim: (text: string) => string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
/**
|
|
3
|
+
* Format a success message with green color and checkmark icon
|
|
4
|
+
*
|
|
5
|
+
* @param text - Message text to format
|
|
6
|
+
* @returns Formatted string with ANSI color codes and ✓ icon
|
|
7
|
+
*/
|
|
8
|
+
export const success = (text) => chalk.green(`✓ ${text}`);
|
|
9
|
+
/**
|
|
10
|
+
* Format an error message with red color and X icon
|
|
11
|
+
*
|
|
12
|
+
* @param text - Message text to format
|
|
13
|
+
* @returns Formatted string with ANSI color codes and ✗ icon
|
|
14
|
+
*/
|
|
15
|
+
export const error = (text) => chalk.red(`✗ ${text}`);
|
|
16
|
+
/**
|
|
17
|
+
* Format a warning message with yellow color and warning icon
|
|
18
|
+
*
|
|
19
|
+
* @param text - Message text to format
|
|
20
|
+
* @returns Formatted string with ANSI color codes and ⚠ icon
|
|
21
|
+
*/
|
|
22
|
+
export const warning = (text) => chalk.yellow(`⚠ ${text}`);
|
|
23
|
+
/**
|
|
24
|
+
* Format an info message with blue color and info icon
|
|
25
|
+
*
|
|
26
|
+
* @param text - Message text to format
|
|
27
|
+
* @returns Formatted string with ANSI color codes and ℹ icon
|
|
28
|
+
*/
|
|
29
|
+
export const info = (text) => chalk.blue(`ℹ ${text}`);
|
|
30
|
+
/**
|
|
31
|
+
* Highlight text with cyan color for emphasis
|
|
32
|
+
*
|
|
33
|
+
* @param text - Text to highlight
|
|
34
|
+
* @returns Formatted string with ANSI color codes
|
|
35
|
+
*/
|
|
36
|
+
export const highlight = (text) => chalk.cyan(text);
|
|
37
|
+
/**
|
|
38
|
+
* Format text in bold style
|
|
39
|
+
*
|
|
40
|
+
* @param text - Text to make bold
|
|
41
|
+
* @returns Formatted string with ANSI bold codes
|
|
42
|
+
*/
|
|
43
|
+
export const bold = (text) => chalk.bold(text);
|
|
44
|
+
/**
|
|
45
|
+
* Format text in dim style (lower intensity)
|
|
46
|
+
*
|
|
47
|
+
* @param text - Text to dim
|
|
48
|
+
* @returns Formatted string with ANSI dim codes
|
|
49
|
+
*/
|
|
50
|
+
export const dim = (text) => chalk.dim(text);
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Formatter Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to format errors into user-friendly messages with
|
|
5
|
+
* actionable suggestions and colored output.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Options for error formatting
|
|
9
|
+
*/
|
|
10
|
+
export interface FormatErrorOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Use colored output
|
|
13
|
+
* @default true
|
|
14
|
+
*/
|
|
15
|
+
colored?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Include error code in output
|
|
18
|
+
* @default true
|
|
19
|
+
*/
|
|
20
|
+
showCode?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Include stack trace in output
|
|
23
|
+
* @default false
|
|
24
|
+
*/
|
|
25
|
+
verbose?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Format an error into a user-friendly message
|
|
29
|
+
*
|
|
30
|
+
* Converts errors into plain English with actionable suggestions.
|
|
31
|
+
* Supports custom error types with specific formatting.
|
|
32
|
+
*
|
|
33
|
+
* @param error - Error to format
|
|
34
|
+
* @param options - Formatting options
|
|
35
|
+
* @returns Formatted error message
|
|
36
|
+
* @example
|
|
37
|
+
* const message = formatError(error, { verbose: true })
|
|
38
|
+
* console.error(message)
|
|
39
|
+
*/
|
|
40
|
+
export declare function formatError(error: Error, options?: FormatErrorOptions): string;
|
|
41
|
+
/**
|
|
42
|
+
* Format error with stack trace for verbose logging
|
|
43
|
+
*
|
|
44
|
+
* This is a convenience function that always includes the stack trace.
|
|
45
|
+
*
|
|
46
|
+
* @param error - Error to format
|
|
47
|
+
* @returns Formatted error message with stack trace
|
|
48
|
+
* @example
|
|
49
|
+
* const message = formatErrorVerbose(error)
|
|
50
|
+
* console.error(message)
|
|
51
|
+
*/
|
|
52
|
+
export declare function formatErrorVerbose(error: Error): string;
|
|
53
|
+
/**
|
|
54
|
+
* Format error for plain text output without colors
|
|
55
|
+
*
|
|
56
|
+
* Useful for logging to files or non-terminal outputs.
|
|
57
|
+
*
|
|
58
|
+
* @param error - Error to format
|
|
59
|
+
* @returns Formatted error message without colors
|
|
60
|
+
* @example
|
|
61
|
+
* const message = formatErrorPlain(error)
|
|
62
|
+
* fs.writeFileSync('error.log', message)
|
|
63
|
+
*/
|
|
64
|
+
export declare function formatErrorPlain(error: Error): string;
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Formatter Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to format errors into user-friendly messages with
|
|
5
|
+
* actionable suggestions and colored output.
|
|
6
|
+
*/
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { AgentError, BaseError, ConfigurationError, FileSystemError, ParserError, ValidationError } from './errors.js';
|
|
9
|
+
/**
|
|
10
|
+
* Format an error into a user-friendly message
|
|
11
|
+
*
|
|
12
|
+
* Converts errors into plain English with actionable suggestions.
|
|
13
|
+
* Supports custom error types with specific formatting.
|
|
14
|
+
*
|
|
15
|
+
* @param error - Error to format
|
|
16
|
+
* @param options - Formatting options
|
|
17
|
+
* @returns Formatted error message
|
|
18
|
+
* @example
|
|
19
|
+
* const message = formatError(error, { verbose: true })
|
|
20
|
+
* console.error(message)
|
|
21
|
+
*/
|
|
22
|
+
export function formatError(error, options = {}) {
|
|
23
|
+
const { colored = true, showCode = true, verbose = false } = options;
|
|
24
|
+
// Use chalk or plain text based on colored option
|
|
25
|
+
const errorStyle = colored ? chalk.red.bold : (text) => text;
|
|
26
|
+
const warningStyle = colored ? chalk.yellow : (text) => text;
|
|
27
|
+
const contextStyle = colored ? chalk.gray : (text) => text;
|
|
28
|
+
let message = '';
|
|
29
|
+
// Add error indicator
|
|
30
|
+
message += `${errorStyle('✗')} ${errorStyle('Error')}: `;
|
|
31
|
+
// Format based on error type
|
|
32
|
+
message += getFormattedErrorMessage(error, { colored });
|
|
33
|
+
// Add suggestion if available
|
|
34
|
+
if (error instanceof BaseError && error.suggestion) {
|
|
35
|
+
message += `\n${warningStyle('💡 Suggestion:')} ${error.suggestion}`;
|
|
36
|
+
}
|
|
37
|
+
// Add error code if requested
|
|
38
|
+
if (showCode && error instanceof BaseError) {
|
|
39
|
+
message += `\n${contextStyle(`[${error.code}]`)}`;
|
|
40
|
+
}
|
|
41
|
+
// Add context information
|
|
42
|
+
if (error instanceof BaseError && error.context) {
|
|
43
|
+
message += `\n${contextStyle('Context:')} ${formatContext(error.context, { colored })}`;
|
|
44
|
+
}
|
|
45
|
+
// Add stack trace in verbose mode
|
|
46
|
+
if (verbose && error.stack) {
|
|
47
|
+
message += `\n\n${contextStyle('Stack Trace:')}\n${contextStyle(error.stack)}`;
|
|
48
|
+
}
|
|
49
|
+
return message;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get formatted error message based on error type
|
|
53
|
+
*
|
|
54
|
+
* @param error - Error to format
|
|
55
|
+
* @param options - Formatting options
|
|
56
|
+
* @param options.colored - Whether to use colored output
|
|
57
|
+
* @returns Formatted error message
|
|
58
|
+
* @private
|
|
59
|
+
*/
|
|
60
|
+
function getFormattedErrorMessage(error, options) {
|
|
61
|
+
if (error instanceof ValidationError) {
|
|
62
|
+
return formatValidationError(error, options);
|
|
63
|
+
}
|
|
64
|
+
if (error instanceof FileSystemError) {
|
|
65
|
+
return formatFileSystemError(error, options);
|
|
66
|
+
}
|
|
67
|
+
if (error instanceof AgentError) {
|
|
68
|
+
return formatAgentError(error, options);
|
|
69
|
+
}
|
|
70
|
+
if (error instanceof ConfigurationError) {
|
|
71
|
+
return formatConfigurationError(error, options);
|
|
72
|
+
}
|
|
73
|
+
if (error instanceof ParserError) {
|
|
74
|
+
return formatParserError(error, options);
|
|
75
|
+
}
|
|
76
|
+
if (error instanceof BaseError) {
|
|
77
|
+
return formatBaseError(error, options);
|
|
78
|
+
}
|
|
79
|
+
return error.message;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Format a validation error with specific suggestions
|
|
83
|
+
*
|
|
84
|
+
* @param error - ValidationError to format
|
|
85
|
+
* @param options - Formatting options
|
|
86
|
+
* @param options.colored - Whether to use colored output
|
|
87
|
+
* @returns Formatted error message
|
|
88
|
+
* @private
|
|
89
|
+
*/
|
|
90
|
+
function formatValidationError(error, options) {
|
|
91
|
+
const suggestStyle = options.colored ? chalk.yellow : (text) => text;
|
|
92
|
+
let { message } = error;
|
|
93
|
+
// Add field-specific suggestions
|
|
94
|
+
if (error.context?.field) {
|
|
95
|
+
message += `\n${suggestStyle('→')} Field: ${error.context.field}`;
|
|
96
|
+
}
|
|
97
|
+
// Add generic validation suggestion
|
|
98
|
+
message += `\n${suggestStyle('→')} Check your input and try again.`;
|
|
99
|
+
return message;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Format a file system error with path information
|
|
103
|
+
*
|
|
104
|
+
* @param error - FileSystemError to format
|
|
105
|
+
* @param options - Formatting options
|
|
106
|
+
* @param options.colored - Whether to use colored output
|
|
107
|
+
* @returns Formatted error message
|
|
108
|
+
* @private
|
|
109
|
+
*/
|
|
110
|
+
function formatFileSystemError(error, options) {
|
|
111
|
+
const suggestStyle = options.colored ? chalk.yellow : (text) => text;
|
|
112
|
+
const pathStyle = options.colored ? chalk.cyan : (text) => text;
|
|
113
|
+
let { message } = error;
|
|
114
|
+
// Add file path if available
|
|
115
|
+
if (error.context?.filePath) {
|
|
116
|
+
message += `\n${suggestStyle('→')} Path: ${pathStyle(error.context.filePath)}`;
|
|
117
|
+
}
|
|
118
|
+
// Add suggestions based on error message
|
|
119
|
+
if (error.message.includes('not found') || error.message.includes('ENOENT')) {
|
|
120
|
+
message += `\n${suggestStyle('→')} Check the path and ensure the file exists.`;
|
|
121
|
+
message += `\n${suggestStyle('→')} Verify your current working directory.`;
|
|
122
|
+
}
|
|
123
|
+
else if (error.message.includes('permission') || error.message.includes('EACCES')) {
|
|
124
|
+
message += `\n${suggestStyle('→')} Check file permissions.`;
|
|
125
|
+
message += `\n${suggestStyle('→')} Ensure you have write access to the directory.`;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
message += `\n${suggestStyle('→')} Check the path and file permissions.`;
|
|
129
|
+
}
|
|
130
|
+
return message;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Format an agent error with execution details
|
|
134
|
+
*
|
|
135
|
+
* @param error - AgentError to format
|
|
136
|
+
* @param options - Formatting options
|
|
137
|
+
* @param options.colored - Whether to use colored output
|
|
138
|
+
* @returns Formatted error message
|
|
139
|
+
* @private
|
|
140
|
+
*/
|
|
141
|
+
function formatAgentError(error, options) {
|
|
142
|
+
const suggestStyle = options.colored ? chalk.yellow : (text) => text;
|
|
143
|
+
const codeStyle = options.colored ? chalk.cyan : (text) => text;
|
|
144
|
+
let { message } = error;
|
|
145
|
+
// Add exit code if available
|
|
146
|
+
if (error.context?.exitCode !== undefined) {
|
|
147
|
+
message += `\n${suggestStyle('→')} Exit code: ${codeStyle(String(error.context.exitCode))}`;
|
|
148
|
+
}
|
|
149
|
+
// Add stderr if available
|
|
150
|
+
if (error.context?.stderr) {
|
|
151
|
+
const stderr = String(error.context.stderr).trim();
|
|
152
|
+
if (stderr) {
|
|
153
|
+
message += `\n${suggestStyle('→')} Error output: ${stderr.slice(0, 200)}`;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Add agent type if available
|
|
157
|
+
if (error.context?.agentType) {
|
|
158
|
+
message += `\n${suggestStyle('→')} Agent: ${error.context.agentType}`;
|
|
159
|
+
}
|
|
160
|
+
// Add suggestions
|
|
161
|
+
message += `\n${suggestStyle('→')} Check Claude CLI installation and authentication.`;
|
|
162
|
+
message += `\n${suggestStyle('→')} Verify the agent prompt and arguments.`;
|
|
163
|
+
return message;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Format a configuration error with field information
|
|
167
|
+
*
|
|
168
|
+
* @param error - ConfigurationError to format
|
|
169
|
+
* @param options - Formatting options
|
|
170
|
+
* @param options.colored - Whether to use colored output
|
|
171
|
+
* @returns Formatted error message
|
|
172
|
+
* @private
|
|
173
|
+
*/
|
|
174
|
+
function formatConfigurationError(error, options) {
|
|
175
|
+
const suggestStyle = options.colored ? chalk.yellow : (text) => text;
|
|
176
|
+
const fieldStyle = options.colored ? chalk.cyan : (text) => text;
|
|
177
|
+
let { message } = error;
|
|
178
|
+
// Add field information
|
|
179
|
+
if (error.context?.field) {
|
|
180
|
+
message += `\n${suggestStyle('→')} Field: ${fieldStyle(error.context.field)}`;
|
|
181
|
+
}
|
|
182
|
+
// Add expected value if available
|
|
183
|
+
if (error.context?.expected) {
|
|
184
|
+
message += `\n${suggestStyle('→')} Expected: ${error.context.expected}`;
|
|
185
|
+
}
|
|
186
|
+
// Add suggestions
|
|
187
|
+
message += `\n${suggestStyle('→')} Check .bmad-core/core-config.yaml for correct configuration.`;
|
|
188
|
+
message += `\n${suggestStyle('→')} Run 'bmad-workflow config validate' for detailed validation.`;
|
|
189
|
+
return message;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Format a parser error with line information
|
|
193
|
+
*
|
|
194
|
+
* @param error - ParserError to format
|
|
195
|
+
* @param options - Formatting options
|
|
196
|
+
* @param options.colored - Whether to use colored output
|
|
197
|
+
* @returns Formatted error message
|
|
198
|
+
* @private
|
|
199
|
+
*/
|
|
200
|
+
function formatParserError(error, options) {
|
|
201
|
+
const suggestStyle = options.colored ? chalk.yellow : (text) => text;
|
|
202
|
+
const lineStyle = options.colored ? chalk.cyan : (text) => text;
|
|
203
|
+
let { message } = error;
|
|
204
|
+
// Add file path if available
|
|
205
|
+
if (error.context?.filePath) {
|
|
206
|
+
message += `\n${suggestStyle('→')} File: ${error.context.filePath}`;
|
|
207
|
+
}
|
|
208
|
+
// Add line number if available
|
|
209
|
+
if (error.context?.line !== undefined) {
|
|
210
|
+
message += `\n${suggestStyle('→')} Line: ${lineStyle(String(error.context.line))}`;
|
|
211
|
+
}
|
|
212
|
+
// Add expected format if available
|
|
213
|
+
if (error.context?.expectedFormat) {
|
|
214
|
+
message += `\n${suggestStyle('→')} Expected format: ${error.context.expectedFormat}`;
|
|
215
|
+
}
|
|
216
|
+
// Add generic parsing suggestion
|
|
217
|
+
message += `\n${suggestStyle('→')} Check the file format against documentation.`;
|
|
218
|
+
message += `\n${suggestStyle('→')} Ensure proper markdown structure.`;
|
|
219
|
+
return message;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Format a base error
|
|
223
|
+
*
|
|
224
|
+
* @param error - BaseError to format
|
|
225
|
+
* @param _options - Formatting options (not used but required for interface consistency)
|
|
226
|
+
* @param _options.colored - Whether to use colored output (not used)
|
|
227
|
+
* @returns Formatted error message
|
|
228
|
+
* @private
|
|
229
|
+
*/
|
|
230
|
+
function formatBaseError(error, _options) {
|
|
231
|
+
return error.message;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Format error context object into readable string
|
|
235
|
+
*
|
|
236
|
+
* @param context - Context object to format
|
|
237
|
+
* @param options - Formatting options
|
|
238
|
+
* @param options.colored - Whether to use colored output
|
|
239
|
+
* @returns Formatted context string
|
|
240
|
+
* @private
|
|
241
|
+
*/
|
|
242
|
+
function formatContext(context, options) {
|
|
243
|
+
const keyStyle = options.colored ? chalk.cyan : (text) => text;
|
|
244
|
+
return Object.entries(context)
|
|
245
|
+
.filter(([key]) => key !== 'stderr' && key !== 'exitCode' && key !== 'agentType') // Skip already formatted fields
|
|
246
|
+
.map(([key, value]) => {
|
|
247
|
+
const valueStr = typeof value === 'object' ? JSON.stringify(value) : String(value);
|
|
248
|
+
return `${keyStyle(key)}: ${valueStr}`;
|
|
249
|
+
})
|
|
250
|
+
.join(', ');
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Format error with stack trace for verbose logging
|
|
254
|
+
*
|
|
255
|
+
* This is a convenience function that always includes the stack trace.
|
|
256
|
+
*
|
|
257
|
+
* @param error - Error to format
|
|
258
|
+
* @returns Formatted error message with stack trace
|
|
259
|
+
* @example
|
|
260
|
+
* const message = formatErrorVerbose(error)
|
|
261
|
+
* console.error(message)
|
|
262
|
+
*/
|
|
263
|
+
export function formatErrorVerbose(error) {
|
|
264
|
+
return formatError(error, { verbose: true });
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Format error for plain text output without colors
|
|
268
|
+
*
|
|
269
|
+
* Useful for logging to files or non-terminal outputs.
|
|
270
|
+
*
|
|
271
|
+
* @param error - Error to format
|
|
272
|
+
* @returns Formatted error message without colors
|
|
273
|
+
* @example
|
|
274
|
+
* const message = formatErrorPlain(error)
|
|
275
|
+
* fs.writeFileSync('error.log', message)
|
|
276
|
+
*/
|
|
277
|
+
export function formatErrorPlain(error) {
|
|
278
|
+
return formatError(error, { colored: false });
|
|
279
|
+
}
|