@paths.design/caws-cli 3.0.0 ā 3.1.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.
- package/README.md +295 -150
- package/dist/budget-derivation.d.ts +35 -0
- package/dist/budget-derivation.d.ts.map +1 -0
- package/dist/budget-derivation.js +204 -0
- package/dist/cicd-optimizer.d.ts +142 -0
- package/dist/cicd-optimizer.d.ts.map +1 -0
- package/dist/cicd-optimizer.js +504 -0
- package/dist/commands/burnup.d.ts +6 -0
- package/dist/commands/burnup.d.ts.map +1 -0
- package/dist/commands/burnup.js +90 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +514 -0
- package/dist/commands/provenance.d.ts +22 -0
- package/dist/commands/provenance.d.ts.map +1 -0
- package/dist/commands/provenance.js +594 -0
- package/dist/commands/tool.d.ts +13 -0
- package/dist/commands/tool.d.ts.map +1 -0
- package/dist/commands/tool.js +138 -0
- package/dist/commands/validate.d.ts +7 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +80 -0
- package/dist/config/index.d.ts +29 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +132 -0
- package/dist/error-handler.d.ts +50 -0
- package/dist/error-handler.d.ts.map +1 -0
- package/dist/error-handler.js +253 -0
- package/dist/generators/working-spec.d.ts +13 -0
- package/dist/generators/working-spec.d.ts.map +1 -0
- package/dist/generators/working-spec.js +204 -0
- package/dist/index-new.d.ts +5 -0
- package/dist/index-new.d.ts.map +1 -0
- package/dist/index-new.js +317 -0
- package/dist/index.d.ts +3 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +100 -1659
- package/dist/index.js.backup +4711 -0
- package/dist/scaffold/cursor-hooks.d.ts +7 -0
- package/dist/scaffold/cursor-hooks.d.ts.map +1 -0
- package/dist/scaffold/cursor-hooks.js +152 -0
- package/dist/scaffold/index.d.ts +20 -0
- package/dist/scaffold/index.d.ts.map +1 -0
- package/dist/scaffold/index.js +486 -0
- package/dist/test-analysis.d.ts +182 -0
- package/dist/test-analysis.d.ts.map +1 -0
- package/dist/test-analysis.js +580 -0
- package/dist/tool-interface.d.ts +236 -0
- package/dist/tool-interface.d.ts.map +1 -0
- package/dist/tool-interface.js +314 -0
- package/dist/tool-loader.d.ts +77 -0
- package/dist/tool-loader.d.ts.map +1 -0
- package/dist/tool-loader.js +298 -0
- package/dist/tool-validator.d.ts +72 -0
- package/dist/tool-validator.d.ts.map +1 -0
- package/dist/tool-validator.js +387 -0
- package/dist/utils/detection.d.ts +7 -0
- package/dist/utils/detection.d.ts.map +1 -0
- package/dist/utils/detection.js +174 -0
- package/dist/utils/finalization.d.ts +17 -0
- package/dist/utils/finalization.d.ts.map +1 -0
- package/dist/utils/finalization.js +229 -0
- package/dist/utils/project-analysis.d.ts +14 -0
- package/dist/utils/project-analysis.d.ts.map +1 -0
- package/dist/utils/project-analysis.js +105 -0
- package/dist/validation/spec-validation.d.ts +29 -0
- package/dist/validation/spec-validation.d.ts.map +1 -0
- package/dist/validation/spec-validation.js +376 -0
- package/dist/waivers-manager.d.ts +167 -0
- package/dist/waivers-manager.d.ts.map +1 -0
- package/dist/waivers-manager.js +549 -0
- package/package.json +10 -12
- package/templates/.cursor/README.md +311 -0
- package/templates/.cursor/hooks/audit.sh +55 -0
- package/templates/.cursor/hooks/block-dangerous.sh +77 -0
- package/templates/.cursor/hooks/caws-quality-check.sh +52 -0
- package/templates/.cursor/hooks/caws-scope-guard.sh +74 -0
- package/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
- package/templates/.cursor/hooks/format.sh +38 -0
- package/templates/.cursor/hooks/naming-check.sh +64 -0
- package/templates/.cursor/hooks/scan-secrets.sh +46 -0
- package/templates/.cursor/hooks/scope-guard.sh +52 -0
- package/templates/.cursor/hooks/validate-spec.sh +38 -0
- package/templates/.cursor/hooks.json +59 -0
- package/templates/.github/copilot/instructions.md +311 -0
- package/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
- package/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
- package/templates/.vscode/launch.json +56 -0
- package/templates/.vscode/settings.json +93 -0
- package/templates/.windsurf/workflows/caws-guided-development.md +92 -0
- package/templates/apps/tools/caws/README.md +1 -1
- package/templates/apps/tools/caws/prompt-lint.js.backup +274 -0
- package/templates/apps/tools/caws/provenance.js.backup +73 -0
- package/templates/apps/tools/caws/schemas/working-spec.schema.json +21 -3
- package/templates/codemod/test.js +93 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tool Command Handler
|
|
3
|
+
* Handles tool execution commands for CAWS CLI
|
|
4
|
+
* @author @darianrosebrook
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
|
|
10
|
+
// Import tool system
|
|
11
|
+
const ToolLoader = require('../tool-loader');
|
|
12
|
+
const ToolValidator = require('../tool-validator');
|
|
13
|
+
|
|
14
|
+
// Tool system state
|
|
15
|
+
let toolLoader = null;
|
|
16
|
+
let toolValidator = null;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Initialize tool system
|
|
20
|
+
* @returns {Promise<ToolLoader|null>} Initialized tool loader or null if failed
|
|
21
|
+
*/
|
|
22
|
+
async function initializeToolSystem() {
|
|
23
|
+
if (toolLoader) return toolLoader;
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
toolLoader = new ToolLoader({
|
|
27
|
+
toolsDir: path.join(process.cwd(), 'apps/tools/caws'),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
toolValidator = new ToolValidator();
|
|
31
|
+
|
|
32
|
+
// Set up event listeners for tool system
|
|
33
|
+
toolLoader.on('discovery:complete', ({ tools: _tools, count }) => {
|
|
34
|
+
if (count > 0) {
|
|
35
|
+
console.log(chalk.blue(`š§ Discovered ${count} tools`));
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
toolLoader.on('tool:loaded', ({ id, metadata }) => {
|
|
40
|
+
console.log(chalk.gray(` ā Loaded tool: ${metadata.name} (${id})`));
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
toolLoader.on('tool:error', ({ id, error }) => {
|
|
44
|
+
console.warn(chalk.yellow(`ā ļø Failed to load tool ${id}: ${error}`));
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Auto-discover tools on initialization
|
|
48
|
+
await toolLoader.discoverTools();
|
|
49
|
+
|
|
50
|
+
return toolLoader;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.warn(chalk.yellow('ā ļø Tool system initialization failed:'), error.message);
|
|
53
|
+
console.warn(chalk.blue('š” Continuing without dynamic tools'));
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Execute tool command handler
|
|
60
|
+
* @param {string} toolId - ID of the tool to execute
|
|
61
|
+
* @param {Object} options - Command options
|
|
62
|
+
*/
|
|
63
|
+
async function executeTool(toolId, options) {
|
|
64
|
+
try {
|
|
65
|
+
// Initialize tool system
|
|
66
|
+
const loader = await initializeToolSystem();
|
|
67
|
+
|
|
68
|
+
if (!loader) {
|
|
69
|
+
console.error(chalk.red('ā Tool system not available'));
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Load all tools first
|
|
74
|
+
await loader.loadAllTools();
|
|
75
|
+
const tool = loader.getTool(toolId);
|
|
76
|
+
|
|
77
|
+
if (!tool) {
|
|
78
|
+
console.error(chalk.red(`ā Tool '${toolId}' not found`));
|
|
79
|
+
console.log(chalk.blue('š” Available tools:'));
|
|
80
|
+
const tools = loader.getAllTools();
|
|
81
|
+
for (const [id, t] of tools) {
|
|
82
|
+
console.log(` - ${id}: ${t.metadata.name}`);
|
|
83
|
+
}
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Validate tool before execution
|
|
88
|
+
const validation = await toolValidator.validateTool(tool);
|
|
89
|
+
if (!validation.valid) {
|
|
90
|
+
console.error(chalk.red('ā Tool validation failed:'));
|
|
91
|
+
validation.errors.forEach((error) => {
|
|
92
|
+
console.error(` ${chalk.red('ā')} ${error}`);
|
|
93
|
+
});
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Parse parameters
|
|
98
|
+
let params = {};
|
|
99
|
+
if (options.params) {
|
|
100
|
+
try {
|
|
101
|
+
params = JSON.parse(options.params);
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error(chalk.red('ā Invalid JSON parameters:'), error.message);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.log(chalk.blue(`š Executing tool: ${tool.metadata.name}`));
|
|
109
|
+
|
|
110
|
+
// Execute tool
|
|
111
|
+
const result = await tool.module.execute(params, {
|
|
112
|
+
workingDirectory: process.cwd(),
|
|
113
|
+
timeout: options.timeout,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Display results
|
|
117
|
+
if (result.success) {
|
|
118
|
+
console.log(chalk.green('ā
Tool execution successful'));
|
|
119
|
+
if (result.output && typeof result.output === 'object') {
|
|
120
|
+
console.log(chalk.gray('Output:'), JSON.stringify(result.output, null, 2));
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
console.error(chalk.red('ā Tool execution failed'));
|
|
124
|
+
result.errors.forEach((error) => {
|
|
125
|
+
console.error(` ${chalk.red('ā')} ${error}`);
|
|
126
|
+
});
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error(chalk.red(`ā Error executing tool ${toolId}:`), error.message);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
module.exports = {
|
|
136
|
+
initializeToolSystem,
|
|
137
|
+
executeTool,
|
|
138
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.js"],"names":[],"mappings":"AAcA;;;;GAIG;AACH,0CAHW,MAAM,+BA2DhB"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Validate Command Handler
|
|
3
|
+
* Handles validation commands for CAWS CLI
|
|
4
|
+
* @author @darianrosebrook
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs-extra');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const yaml = require('js-yaml');
|
|
10
|
+
const chalk = require('chalk');
|
|
11
|
+
|
|
12
|
+
// Import validation functionality
|
|
13
|
+
const { validateWorkingSpecWithSuggestions } = require('../validation/spec-validation');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Validate command handler
|
|
17
|
+
* @param {string} specFile - Path to spec file
|
|
18
|
+
* @param {Object} options - Command options
|
|
19
|
+
*/
|
|
20
|
+
async function validateCommand(specFile, options) {
|
|
21
|
+
try {
|
|
22
|
+
let specPath = specFile || path.join('.caws', 'working-spec.yaml');
|
|
23
|
+
|
|
24
|
+
if (!fs.existsSync(specPath)) {
|
|
25
|
+
console.error(chalk.red(`ā Spec file not found: ${specPath}`));
|
|
26
|
+
console.error(chalk.blue('š” Run "caws init" first to create a working spec'));
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const specContent = fs.readFileSync(specPath, 'utf8');
|
|
31
|
+
const spec = yaml.load(specContent);
|
|
32
|
+
|
|
33
|
+
console.log(chalk.cyan('š Validating CAWS working spec...'));
|
|
34
|
+
|
|
35
|
+
const result = validateWorkingSpecWithSuggestions(spec, {
|
|
36
|
+
autoFix: options.autoFix,
|
|
37
|
+
suggestions: !options.quiet,
|
|
38
|
+
checkBudget: true,
|
|
39
|
+
projectRoot: path.dirname(specPath),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (result.valid) {
|
|
43
|
+
console.log(chalk.green('ā
Working spec validation passed'));
|
|
44
|
+
if (!options.quiet) {
|
|
45
|
+
console.log(chalk.gray(` Risk tier: ${spec.risk_tier}`));
|
|
46
|
+
console.log(chalk.gray(` Mode: ${spec.mode}`));
|
|
47
|
+
if (spec.title) {
|
|
48
|
+
console.log(chalk.gray(` Title: ${spec.title}`));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
console.log(chalk.red('ā Working spec validation failed'));
|
|
53
|
+
|
|
54
|
+
// Show errors
|
|
55
|
+
result.errors.forEach((error, index) => {
|
|
56
|
+
console.log(` ${index + 1}. ${chalk.red(error.message)}`);
|
|
57
|
+
if (error.suggestion) {
|
|
58
|
+
console.log(` ${chalk.blue('š” ' + error.suggestion)}`);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Show warnings
|
|
63
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
64
|
+
console.log(chalk.yellow('\nā ļø Warnings:'));
|
|
65
|
+
result.warnings.forEach((warning, index) => {
|
|
66
|
+
console.log(` ${index + 1}. ${chalk.yellow(warning.message)}`);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error(chalk.red('ā Error during validation:'), error.message);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
module.exports = {
|
|
79
|
+
validateCommand,
|
|
80
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import CLI_VERSION_1 = require("../../package.json");
|
|
2
|
+
import CLI_VERSION = CLI_VERSION_1.version;
|
|
3
|
+
/**
|
|
4
|
+
* Initialize global setup detection
|
|
5
|
+
* @returns {Object} Setup configuration
|
|
6
|
+
*/
|
|
7
|
+
export function initializeGlobalSetup(): any;
|
|
8
|
+
/**
|
|
9
|
+
* Load provenance tools dynamically
|
|
10
|
+
* @returns {Object|null} Provenance tools or null if not available
|
|
11
|
+
*/
|
|
12
|
+
export function loadProvenanceTools(): any | null;
|
|
13
|
+
/**
|
|
14
|
+
* Initialize language support tools
|
|
15
|
+
* @returns {Object|null} Language support tools or null if not available
|
|
16
|
+
*/
|
|
17
|
+
export function initializeLanguageSupport(): any | null;
|
|
18
|
+
/**
|
|
19
|
+
* Get global CAWS setup
|
|
20
|
+
* @returns {Object} CAWS setup configuration
|
|
21
|
+
*/
|
|
22
|
+
export function getGlobalCAWSSetup(): any;
|
|
23
|
+
/**
|
|
24
|
+
* Set global CAWS setup (for testing or override)
|
|
25
|
+
* @param {Object} setup - Setup configuration
|
|
26
|
+
*/
|
|
27
|
+
export function setGlobalCAWSSetup(setup: any): void;
|
|
28
|
+
export { CLI_VERSION };
|
|
29
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.js"],"names":[],"mappings":";mCAakD,OAAO;AAOzD;;;GAGG;AACH,6CAkBC;AAED;;;GAGG;AACH,uCAFa,MAAO,IAAI,CAqBvB;AAED;;;GAGG;AACH,6CAFa,MAAO,IAAI,CAmCvB;AAED;;;GAGG;AACH,0CAEC;AAED;;;GAGG;AACH,qDAEC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CAWS Configuration Module
|
|
3
|
+
* Global configuration and provenance tools management
|
|
4
|
+
* @author @darianrosebrook
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
|
|
10
|
+
// Import detection utilities
|
|
11
|
+
const { detectCAWSSetup } = require('../utils/detection');
|
|
12
|
+
|
|
13
|
+
// CLI version from package.json
|
|
14
|
+
const CLI_VERSION = require('../../package.json').version;
|
|
15
|
+
|
|
16
|
+
// Global state
|
|
17
|
+
let provenanceTools = null;
|
|
18
|
+
let cawsSetup = null;
|
|
19
|
+
let languageSupport = null;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Initialize global setup detection
|
|
23
|
+
* @returns {Object} Setup configuration
|
|
24
|
+
*/
|
|
25
|
+
function initializeGlobalSetup() {
|
|
26
|
+
if (cawsSetup) return cawsSetup;
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
cawsSetup = detectCAWSSetup();
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.warn(chalk.yellow('ā ļø Failed to detect CAWS setup:'), error.message);
|
|
32
|
+
cawsSetup = {
|
|
33
|
+
type: 'unknown',
|
|
34
|
+
hasCAWSDir: false,
|
|
35
|
+
cawsDir: null,
|
|
36
|
+
capabilities: [],
|
|
37
|
+
hasTemplateDir: false,
|
|
38
|
+
templateDir: null,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return cawsSetup;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Load provenance tools dynamically
|
|
47
|
+
* @returns {Object|null} Provenance tools or null if not available
|
|
48
|
+
*/
|
|
49
|
+
function loadProvenanceTools() {
|
|
50
|
+
if (provenanceTools) return provenanceTools; // Already loaded
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
const setup = cawsSetup || initializeGlobalSetup();
|
|
54
|
+
if (setup?.hasTemplateDir && setup?.templateDir) {
|
|
55
|
+
const { generateProvenance, saveProvenance } = require(
|
|
56
|
+
path.join(setup.templateDir, 'apps/tools/caws/provenance.js')
|
|
57
|
+
);
|
|
58
|
+
provenanceTools = { generateProvenance, saveProvenance };
|
|
59
|
+
console.log('ā
Loaded provenance tools from:', setup.templateDir);
|
|
60
|
+
}
|
|
61
|
+
} catch (error) {
|
|
62
|
+
// Fallback for environments without template
|
|
63
|
+
provenanceTools = null;
|
|
64
|
+
console.warn('ā ļø Provenance tools not available:', error.message);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return provenanceTools;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Initialize language support tools
|
|
72
|
+
* @returns {Object|null} Language support tools or null if not available
|
|
73
|
+
*/
|
|
74
|
+
function initializeLanguageSupport() {
|
|
75
|
+
if (languageSupport) return languageSupport;
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
// Try multiple possible locations for language support
|
|
79
|
+
const possiblePaths = [
|
|
80
|
+
path.join(__dirname, '../../../caws-template/apps/tools/caws/language-support.js'),
|
|
81
|
+
path.join(__dirname, '../../../../caws-template/apps/tools/caws/language-support.js'),
|
|
82
|
+
path.join(process.cwd(), 'packages/caws-template/apps/tools/caws/language-support.js'),
|
|
83
|
+
path.join(process.cwd(), 'caws-template/apps/tools/caws/language-support.js'),
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
for (const testPath of possiblePaths) {
|
|
87
|
+
try {
|
|
88
|
+
languageSupport = require(testPath);
|
|
89
|
+
// Only log if not running version command
|
|
90
|
+
if (!process.argv.includes('--version') && !process.argv.includes('-V')) {
|
|
91
|
+
console.log(`ā
Loaded language support from: ${testPath}`);
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
} catch (pathError) {
|
|
95
|
+
// Continue to next path
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.warn(chalk.yellow('ā ļø Language support tools not available'));
|
|
100
|
+
console.warn(chalk.blue('š” This may limit language-specific configuration features'));
|
|
101
|
+
console.warn(
|
|
102
|
+
chalk.blue('š” For full functionality, ensure caws-template package is available')
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return languageSupport;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Get global CAWS setup
|
|
111
|
+
* @returns {Object} CAWS setup configuration
|
|
112
|
+
*/
|
|
113
|
+
function getGlobalCAWSSetup() {
|
|
114
|
+
return cawsSetup || initializeGlobalSetup();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Set global CAWS setup (for testing or override)
|
|
119
|
+
* @param {Object} setup - Setup configuration
|
|
120
|
+
*/
|
|
121
|
+
function setGlobalCAWSSetup(setup) {
|
|
122
|
+
cawsSetup = setup;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
module.exports = {
|
|
126
|
+
CLI_VERSION,
|
|
127
|
+
initializeGlobalSetup,
|
|
128
|
+
loadProvenanceTools,
|
|
129
|
+
initializeLanguageSupport,
|
|
130
|
+
getGlobalCAWSSetup,
|
|
131
|
+
setGlobalCAWSSetup,
|
|
132
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced error class with category and recovery suggestions
|
|
3
|
+
*/
|
|
4
|
+
export class CAWSError extends Error {
|
|
5
|
+
constructor(message: any, category?: any, suggestions?: any[]);
|
|
6
|
+
category: any;
|
|
7
|
+
suggestions: any[];
|
|
8
|
+
}
|
|
9
|
+
export namespace ERROR_CATEGORIES {
|
|
10
|
+
let VALIDATION: string;
|
|
11
|
+
let PERMISSION: string;
|
|
12
|
+
let FILESYSTEM: string;
|
|
13
|
+
let NETWORK: string;
|
|
14
|
+
let CONFIGURATION: string;
|
|
15
|
+
let USER_INPUT: string;
|
|
16
|
+
let DEPENDENCY: string;
|
|
17
|
+
let UNKNOWN: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get error category from error object or message
|
|
21
|
+
* @param {Error|string} error - Error object or message
|
|
22
|
+
* @returns {string} Error category
|
|
23
|
+
*/
|
|
24
|
+
export function getErrorCategory(error: Error | string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Wrap async operations with consistent error handling
|
|
27
|
+
* @param {Function} operation - Async operation to wrap
|
|
28
|
+
* @param {string} context - Context for error messages
|
|
29
|
+
* @returns {Promise<any>} Operation result or throws handled error
|
|
30
|
+
*/
|
|
31
|
+
export function safeAsync(operation: Function, context?: string): Promise<any>;
|
|
32
|
+
/**
|
|
33
|
+
* Handle CLI errors with consistent formatting and user guidance
|
|
34
|
+
* @param {Error} error - Error to handle
|
|
35
|
+
* @param {boolean} exit - Whether to exit the process (default: true)
|
|
36
|
+
*/
|
|
37
|
+
export function handleCliError(error: Error, exit?: boolean): void;
|
|
38
|
+
/**
|
|
39
|
+
* Validate required environment and dependencies
|
|
40
|
+
* @returns {Object} Validation result with any errors
|
|
41
|
+
*/
|
|
42
|
+
export function validateEnvironment(): any;
|
|
43
|
+
/**
|
|
44
|
+
* Get recovery suggestions based on error category
|
|
45
|
+
* @param {Error} error - Original error
|
|
46
|
+
* @param {string} category - Error category
|
|
47
|
+
* @returns {string[]} Array of recovery suggestions
|
|
48
|
+
*/
|
|
49
|
+
export function getRecoverySuggestions(error: Error, category: string): string[];
|
|
50
|
+
//# sourceMappingURL=error-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../src/error-handler.js"],"names":[],"mappings":"AA0GA;;GAEG;AACH;IACE,+DAKC;IAFC,cAAqD;IACrD,mBAA2F;CAE9F;;;;;;;;;;;AA9ED;;;;GAIG;AACH,wCAHW,KAAK,GAAC,MAAM,GACV,MAAM,CA+DlB;AAcD;;;;;GAKG;AACH,yDAHW,MAAM,GACJ,OAAO,CAAC,GAAG,CAAC,CAexB;AAkDD;;;;GAIG;AACH,sCAHW,KAAK,SACL,OAAO,QAyBjB;AAED;;;GAGG;AACH,2CAqBC;AAvGD;;;;;GAKG;AACH,8CAJW,KAAK,YACL,MAAM,GACJ,MAAM,EAAE,CA0CpB"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CAWS CLI Error Handler - Centralized error handling utilities
|
|
3
|
+
* Provides consistent error categorization, formatting, and recovery suggestions
|
|
4
|
+
* @author @darianrosebrook
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Error categories for better user experience
|
|
11
|
+
*/
|
|
12
|
+
const ERROR_CATEGORIES = {
|
|
13
|
+
VALIDATION: 'validation',
|
|
14
|
+
PERMISSION: 'permission',
|
|
15
|
+
FILESYSTEM: 'filesystem',
|
|
16
|
+
NETWORK: 'network',
|
|
17
|
+
CONFIGURATION: 'configuration',
|
|
18
|
+
USER_INPUT: 'user_input',
|
|
19
|
+
DEPENDENCY: 'dependency',
|
|
20
|
+
UNKNOWN: 'unknown',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Error code mappings for common system errors
|
|
25
|
+
*/
|
|
26
|
+
const ERROR_CODES = {
|
|
27
|
+
EACCES: ERROR_CATEGORIES.PERMISSION,
|
|
28
|
+
EPERM: ERROR_CATEGORIES.PERMISSION,
|
|
29
|
+
ENOENT: ERROR_CATEGORIES.FILESYSTEM,
|
|
30
|
+
ENOTFOUND: ERROR_CATEGORIES.NETWORK,
|
|
31
|
+
ECONNREFUSED: ERROR_CATEGORIES.NETWORK,
|
|
32
|
+
ETIMEDOUT: ERROR_CATEGORIES.NETWORK,
|
|
33
|
+
ENOSPC: ERROR_CATEGORIES.FILESYSTEM,
|
|
34
|
+
EEXIST: ERROR_CATEGORIES.FILESYSTEM,
|
|
35
|
+
EISDIR: ERROR_CATEGORIES.FILESYSTEM,
|
|
36
|
+
ENOTDIR: ERROR_CATEGORIES.FILESYSTEM,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get error category from error object or message
|
|
41
|
+
* @param {Error|string} error - Error object or message
|
|
42
|
+
* @returns {string} Error category
|
|
43
|
+
*/
|
|
44
|
+
function getErrorCategory(error) {
|
|
45
|
+
const errorMessage = typeof error === 'string' ? error : error.message;
|
|
46
|
+
const errorCode = typeof error === 'object' && error.code ? error.code : null;
|
|
47
|
+
|
|
48
|
+
// Check error codes first
|
|
49
|
+
if (errorCode && ERROR_CODES[errorCode]) {
|
|
50
|
+
return ERROR_CODES[errorCode];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Check message patterns
|
|
54
|
+
const lowerMessage = errorMessage.toLowerCase();
|
|
55
|
+
|
|
56
|
+
if (
|
|
57
|
+
lowerMessage.includes('validation') ||
|
|
58
|
+
lowerMessage.includes('invalid') ||
|
|
59
|
+
lowerMessage.includes('required')
|
|
60
|
+
) {
|
|
61
|
+
return ERROR_CATEGORIES.VALIDATION;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (
|
|
65
|
+
lowerMessage.includes('permission') ||
|
|
66
|
+
lowerMessage.includes('access') ||
|
|
67
|
+
lowerMessage.includes('denied')
|
|
68
|
+
) {
|
|
69
|
+
return ERROR_CATEGORIES.PERMISSION;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (
|
|
73
|
+
lowerMessage.includes('file') ||
|
|
74
|
+
lowerMessage.includes('directory') ||
|
|
75
|
+
lowerMessage.includes('path')
|
|
76
|
+
) {
|
|
77
|
+
return ERROR_CATEGORIES.FILESYSTEM;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (
|
|
81
|
+
lowerMessage.includes('network') ||
|
|
82
|
+
lowerMessage.includes('connection') ||
|
|
83
|
+
lowerMessage.includes('timeout')
|
|
84
|
+
) {
|
|
85
|
+
return ERROR_CATEGORIES.NETWORK;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (
|
|
89
|
+
lowerMessage.includes('config') ||
|
|
90
|
+
lowerMessage.includes('setting') ||
|
|
91
|
+
lowerMessage.includes('option')
|
|
92
|
+
) {
|
|
93
|
+
return ERROR_CATEGORIES.CONFIGURATION;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (
|
|
97
|
+
lowerMessage.includes('input') ||
|
|
98
|
+
lowerMessage.includes('prompt') ||
|
|
99
|
+
lowerMessage.includes('answer')
|
|
100
|
+
) {
|
|
101
|
+
return ERROR_CATEGORIES.USER_INPUT;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return ERROR_CATEGORIES.UNKNOWN;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Enhanced error class with category and recovery suggestions
|
|
109
|
+
*/
|
|
110
|
+
class CAWSError extends Error {
|
|
111
|
+
constructor(message, category = null, suggestions = []) {
|
|
112
|
+
super(message);
|
|
113
|
+
this.name = 'CAWSError';
|
|
114
|
+
this.category = category || getErrorCategory(message);
|
|
115
|
+
this.suggestions = Array.isArray(suggestions) ? suggestions : [suggestions].filter(Boolean);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Wrap async operations with consistent error handling
|
|
121
|
+
* @param {Function} operation - Async operation to wrap
|
|
122
|
+
* @param {string} context - Context for error messages
|
|
123
|
+
* @returns {Promise<any>} Operation result or throws handled error
|
|
124
|
+
*/
|
|
125
|
+
async function safeAsync(operation, context = '') {
|
|
126
|
+
try {
|
|
127
|
+
return await operation();
|
|
128
|
+
} catch (error) {
|
|
129
|
+
const category = getErrorCategory(error);
|
|
130
|
+
const enhancedError = new CAWSError(
|
|
131
|
+
`${context}: ${error.message}`,
|
|
132
|
+
category,
|
|
133
|
+
getRecoverySuggestions(error, category)
|
|
134
|
+
);
|
|
135
|
+
enhancedError.originalError = error;
|
|
136
|
+
throw enhancedError;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get recovery suggestions based on error category
|
|
142
|
+
* @param {Error} error - Original error
|
|
143
|
+
* @param {string} category - Error category
|
|
144
|
+
* @returns {string[]} Array of recovery suggestions
|
|
145
|
+
*/
|
|
146
|
+
function getRecoverySuggestions(error, category) {
|
|
147
|
+
const suggestions = [];
|
|
148
|
+
|
|
149
|
+
switch (category) {
|
|
150
|
+
case ERROR_CATEGORIES.PERMISSION:
|
|
151
|
+
suggestions.push('Try running the command with elevated privileges (sudo)');
|
|
152
|
+
suggestions.push('Check file/directory permissions with `ls -la`');
|
|
153
|
+
break;
|
|
154
|
+
|
|
155
|
+
case ERROR_CATEGORIES.FILESYSTEM:
|
|
156
|
+
if (error.code === 'ENOENT') {
|
|
157
|
+
suggestions.push('Verify the file/directory path exists');
|
|
158
|
+
suggestions.push('Check for typos in file names');
|
|
159
|
+
} else if (error.code === 'EEXIST') {
|
|
160
|
+
suggestions.push('The file/directory already exists');
|
|
161
|
+
suggestions.push('Use a different name or remove the existing item');
|
|
162
|
+
}
|
|
163
|
+
break;
|
|
164
|
+
|
|
165
|
+
case ERROR_CATEGORIES.VALIDATION:
|
|
166
|
+
suggestions.push('Run `caws validate --suggestions` for detailed validation help');
|
|
167
|
+
suggestions.push('Check your working spec format against the documentation');
|
|
168
|
+
break;
|
|
169
|
+
|
|
170
|
+
case ERROR_CATEGORIES.CONFIGURATION:
|
|
171
|
+
suggestions.push('Run `caws init --interactive` to reconfigure your project');
|
|
172
|
+
suggestions.push('Check your .caws directory and configuration files');
|
|
173
|
+
break;
|
|
174
|
+
|
|
175
|
+
case ERROR_CATEGORIES.NETWORK:
|
|
176
|
+
suggestions.push('Check your internet connection');
|
|
177
|
+
suggestions.push('Verify the URL/service is accessible');
|
|
178
|
+
break;
|
|
179
|
+
|
|
180
|
+
default:
|
|
181
|
+
suggestions.push('Run the command with --help for usage information');
|
|
182
|
+
suggestions.push('Check the CAWS documentation at docs/README.md');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return suggestions;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Handle CLI errors with consistent formatting and user guidance
|
|
190
|
+
* @param {Error} error - Error to handle
|
|
191
|
+
* @param {boolean} exit - Whether to exit the process (default: true)
|
|
192
|
+
*/
|
|
193
|
+
function handleCliError(error, exit = true) {
|
|
194
|
+
const category = error.category || getErrorCategory(error);
|
|
195
|
+
const suggestions = error.suggestions || getRecoverySuggestions(error, category);
|
|
196
|
+
|
|
197
|
+
// Format error output
|
|
198
|
+
console.error(chalk.red(`\nā Error (${category}): ${error.message}`));
|
|
199
|
+
|
|
200
|
+
if (suggestions && suggestions.length > 0) {
|
|
201
|
+
console.error(chalk.yellow('\nš” Suggestions:'));
|
|
202
|
+
suggestions.forEach((suggestion) => {
|
|
203
|
+
console.error(chalk.yellow(` ⢠${suggestion}`));
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
console.error(
|
|
208
|
+
chalk.gray(
|
|
209
|
+
'\nš For more help, visit: https://github.com/Paths-Design/coding-agent-working-standard'
|
|
210
|
+
)
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
if (exit) {
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Validate required environment and dependencies
|
|
220
|
+
* @returns {Object} Validation result with any errors
|
|
221
|
+
*/
|
|
222
|
+
function validateEnvironment() {
|
|
223
|
+
const errors = [];
|
|
224
|
+
const warnings = [];
|
|
225
|
+
|
|
226
|
+
// Check Node.js version
|
|
227
|
+
const nodeVersion = process.versions.node;
|
|
228
|
+
const majorVersion = parseInt(nodeVersion.split('.')[0], 10);
|
|
229
|
+
if (majorVersion < 18) {
|
|
230
|
+
errors.push(`Node.js version ${nodeVersion} is not supported. Minimum required: 18.0.0`);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Check if running in supported environment
|
|
234
|
+
if (!process.cwd()) {
|
|
235
|
+
errors.push('Unable to determine current working directory');
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
valid: errors.length === 0,
|
|
240
|
+
errors,
|
|
241
|
+
warnings,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
module.exports = {
|
|
246
|
+
CAWSError,
|
|
247
|
+
ERROR_CATEGORIES,
|
|
248
|
+
getErrorCategory,
|
|
249
|
+
safeAsync,
|
|
250
|
+
handleCliError,
|
|
251
|
+
validateEnvironment,
|
|
252
|
+
getRecoverySuggestions,
|
|
253
|
+
};
|