@defai.digital/ax-cli 3.15.26 ā 4.0.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 +67 -21
- package/config-defaults/prompts.yaml +5 -0
- package/dist/agent/execution/tool-executor.js +47 -1
- package/dist/agent/execution/tool-executor.js.map +1 -1
- package/dist/agent/llm-agent.js +4 -4
- package/dist/agent/llm-agent.js.map +1 -1
- package/dist/agent/parallel-tools.js +1 -0
- package/dist/agent/parallel-tools.js.map +1 -1
- package/dist/commands/cache.js +37 -34
- package/dist/commands/cache.js.map +1 -1
- package/dist/commands/doctor.js +111 -65
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init/wizard.js +10 -12
- package/dist/commands/init/wizard.js.map +1 -1
- package/dist/commands/init.d.ts +3 -3
- package/dist/commands/init.js +173 -25
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mcp.js +106 -55
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/setup.d.ts +0 -1
- package/dist/commands/setup.js +33 -194
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/usage.js +45 -51
- package/dist/commands/usage.js.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/llm/tools.d.ts +2 -9
- package/dist/llm/tools.js +8 -579
- package/dist/llm/tools.js.map +1 -1
- package/dist/mcp/content-length-transport.d.ts +18 -0
- package/dist/mcp/content-length-transport.js +121 -3
- package/dist/mcp/content-length-transport.js.map +1 -1
- package/dist/mcp/error-remediation.js +54 -17
- package/dist/mcp/error-remediation.js.map +1 -1
- package/dist/planner/types.d.ts +4 -4
- package/dist/tools/ax-agent.d.ts +32 -0
- package/dist/tools/ax-agent.js +105 -0
- package/dist/tools/ax-agent.js.map +1 -1
- package/dist/tools/definitions/ask-user.d.ts +8 -0
- package/dist/tools/definitions/ask-user.js +168 -0
- package/dist/tools/definitions/ask-user.js.map +1 -0
- package/dist/tools/definitions/ax-agent.d.ts +8 -0
- package/dist/tools/definitions/ax-agent.js +276 -0
- package/dist/tools/definitions/ax-agent.js.map +1 -0
- package/dist/tools/definitions/bash-output.d.ts +7 -0
- package/dist/tools/definitions/bash-output.js +78 -0
- package/dist/tools/definitions/bash-output.js.map +1 -0
- package/dist/tools/definitions/bash.d.ts +8 -0
- package/dist/tools/definitions/bash.js +152 -0
- package/dist/tools/definitions/bash.js.map +1 -0
- package/dist/tools/definitions/create-file.d.ts +7 -0
- package/dist/tools/definitions/create-file.js +129 -0
- package/dist/tools/definitions/create-file.js.map +1 -0
- package/dist/tools/definitions/design.d.ts +12 -0
- package/dist/tools/definitions/design.js +368 -0
- package/dist/tools/definitions/design.js.map +1 -0
- package/dist/tools/definitions/index.d.ts +49 -0
- package/dist/tools/definitions/index.js +87 -0
- package/dist/tools/definitions/index.js.map +1 -0
- package/dist/tools/definitions/multi-edit.d.ts +7 -0
- package/dist/tools/definitions/multi-edit.js +123 -0
- package/dist/tools/definitions/multi-edit.js.map +1 -0
- package/dist/tools/definitions/search.d.ts +7 -0
- package/dist/tools/definitions/search.js +159 -0
- package/dist/tools/definitions/search.js.map +1 -0
- package/dist/tools/definitions/str-replace-editor.d.ts +7 -0
- package/dist/tools/definitions/str-replace-editor.js +145 -0
- package/dist/tools/definitions/str-replace-editor.js.map +1 -0
- package/dist/tools/definitions/todo.d.ts +8 -0
- package/dist/tools/definitions/todo.js +261 -0
- package/dist/tools/definitions/todo.js.map +1 -0
- package/dist/tools/definitions/view-file.d.ts +7 -0
- package/dist/tools/definitions/view-file.js +111 -0
- package/dist/tools/definitions/view-file.js.map +1 -0
- package/dist/tools/format-generators.d.ts +62 -0
- package/dist/tools/format-generators.js +291 -0
- package/dist/tools/format-generators.js.map +1 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.js +5 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/types.d.ts +175 -0
- package/dist/tools/types.js +11 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/ui/utils/image-handler.js +3 -0
- package/dist/ui/utils/image-handler.js.map +1 -1
- package/dist/utils/enhanced-error-messages.js +43 -23
- package/dist/utils/enhanced-error-messages.js.map +1 -1
- package/dist/utils/init-validator.d.ts +4 -0
- package/dist/utils/init-validator.js +17 -13
- package/dist/utils/init-validator.js.map +1 -1
- package/dist/utils/llm-optimized-instruction-generator.js +97 -136
- package/dist/utils/llm-optimized-instruction-generator.js.map +1 -1
- package/dist/utils/project-analyzer.d.ts +6 -0
- package/dist/utils/project-analyzer.js +92 -189
- package/dist/utils/project-analyzer.js.map +1 -1
- package/dist/utils/template-manager.d.ts +8 -0
- package/dist/utils/template-manager.js +54 -110
- package/dist/utils/template-manager.js.map +1 -1
- package/package.json +1 -1
package/dist/commands/init.js
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Init command
|
|
2
|
+
* Init command for project setup and analysis
|
|
3
3
|
*
|
|
4
|
-
* This command
|
|
5
|
-
*
|
|
4
|
+
* This command initializes project-level configuration (.ax-cli/CUSTOM.md).
|
|
5
|
+
* For API configuration, use 'ax-cli setup'.
|
|
6
6
|
*/
|
|
7
7
|
import { Command } from 'commander';
|
|
8
|
+
import { existsSync, mkdirSync, writeFileSync, renameSync, unlinkSync } from 'fs';
|
|
9
|
+
import { join, resolve } from 'path';
|
|
10
|
+
import * as prompts from '@clack/prompts';
|
|
8
11
|
import chalk from 'chalk';
|
|
12
|
+
import { ProjectAnalyzer } from '../utils/project-analyzer.js';
|
|
13
|
+
import { LLMOptimizedInstructionGenerator } from '../utils/llm-optimized-instruction-generator.js';
|
|
14
|
+
import { InitValidator } from '../utils/init-validator.js';
|
|
15
|
+
import { InitWizard } from './init/wizard.js';
|
|
16
|
+
import { extractErrorMessage } from '../utils/error-handler.js';
|
|
17
|
+
import { CONFIG_DIR_NAME, FILE_NAMES } from '../constants.js';
|
|
9
18
|
export function createInitCommand() {
|
|
10
19
|
const initCommand = new Command('init')
|
|
11
|
-
.description('Initialize
|
|
20
|
+
.description('Initialize AX CLI for your project with intelligent analysis')
|
|
12
21
|
.option('-f, --force', 'Force regeneration even if files exist', false)
|
|
13
22
|
.option('-v, --verbose', 'Verbose output showing analysis details', false)
|
|
14
23
|
.option('-d, --directory <dir>', 'Project directory to analyze')
|
|
@@ -19,28 +28,167 @@ export function createInitCommand() {
|
|
|
19
28
|
.option('--dry-run', 'Show what would be done without making changes', false)
|
|
20
29
|
.option('--validate', 'Run validation checks only', false)
|
|
21
30
|
.action(async (options) => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
try {
|
|
32
|
+
prompts.intro(chalk.cyan('AX CLI Project Initialization'));
|
|
33
|
+
const projectRoot = options.directory ? resolve(options.directory) : process.cwd();
|
|
34
|
+
if (options.verbose) {
|
|
35
|
+
prompts.log.info(`Working directory: ${projectRoot}`);
|
|
36
|
+
}
|
|
37
|
+
// Check if in a git repo or has package.json (reasonable project indicator)
|
|
38
|
+
const hasGit = existsSync(join(projectRoot, '.git'));
|
|
39
|
+
const hasPackageJson = existsSync(join(projectRoot, 'package.json'));
|
|
40
|
+
const isProject = hasGit || hasPackageJson;
|
|
41
|
+
if (!isProject && !options.validate) {
|
|
42
|
+
prompts.log.warn('No project detected in current directory (no .git or package.json)');
|
|
43
|
+
prompts.log.info('Run from a project directory to initialize it.');
|
|
44
|
+
prompts.outro(chalk.yellow('Initialization skipped'));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Run validation (single instance, reused for --validate flag or normal flow)
|
|
48
|
+
const validator = new InitValidator(projectRoot);
|
|
49
|
+
const validationResult = validator.validate();
|
|
50
|
+
if (options.validate) {
|
|
51
|
+
console.log('\n' + InitValidator.formatValidationResult(validationResult));
|
|
52
|
+
process.exit(validationResult.valid ? 0 : 1);
|
|
53
|
+
}
|
|
54
|
+
if (!validationResult.valid) {
|
|
55
|
+
prompts.log.error('Project validation failed:');
|
|
56
|
+
console.log(InitValidator.formatValidationResult(validationResult));
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
if (options.verbose && (validationResult.warnings.length > 0 || validationResult.suggestions.length > 0)) {
|
|
60
|
+
console.log(InitValidator.formatValidationResult(validationResult));
|
|
61
|
+
}
|
|
62
|
+
// Check if already initialized
|
|
63
|
+
const axCliDir = join(projectRoot, CONFIG_DIR_NAME);
|
|
64
|
+
const customMdPath = join(axCliDir, FILE_NAMES.CUSTOM_MD);
|
|
65
|
+
const indexPath = join(axCliDir, FILE_NAMES.INDEX_JSON);
|
|
66
|
+
if (!options.force && existsSync(customMdPath)) {
|
|
67
|
+
prompts.log.success('Project already initialized!');
|
|
68
|
+
prompts.log.info(`Custom instructions: ${customMdPath}`);
|
|
69
|
+
prompts.log.info(`Project index: ${indexPath}`);
|
|
70
|
+
prompts.log.info('Use --force to regenerate');
|
|
71
|
+
prompts.outro(chalk.green('Already configured'));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Run interactive wizard for template selection (unless --yes or --no-interaction)
|
|
75
|
+
let selectedTemplate = undefined;
|
|
76
|
+
if (!options.noInteraction && !options.yes) {
|
|
77
|
+
const wizard = new InitWizard({
|
|
78
|
+
nonInteractive: options.noInteraction,
|
|
79
|
+
yes: options.yes,
|
|
80
|
+
template: options.template,
|
|
81
|
+
});
|
|
82
|
+
const wizardResult = await wizard.run();
|
|
83
|
+
selectedTemplate = wizardResult.selectedTemplate;
|
|
84
|
+
}
|
|
85
|
+
// Create config directory
|
|
86
|
+
if (!existsSync(axCliDir)) {
|
|
87
|
+
mkdirSync(axCliDir, { recursive: true });
|
|
88
|
+
if (options.verbose) {
|
|
89
|
+
prompts.log.info(`Created ${CONFIG_DIR_NAME} directory`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Analyze project
|
|
93
|
+
const spinner = prompts.spinner();
|
|
94
|
+
spinner.start('Analyzing project...');
|
|
95
|
+
const analyzer = new ProjectAnalyzer(projectRoot);
|
|
96
|
+
const result = await analyzer.analyze();
|
|
97
|
+
if (!result.success || !result.projectInfo) {
|
|
98
|
+
spinner.stop('Analysis failed');
|
|
99
|
+
prompts.log.error(`Project analysis failed: ${result.error || 'Unknown error'}`);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
const projectInfo = result.projectInfo;
|
|
103
|
+
spinner.stop('Analysis complete');
|
|
104
|
+
// Display analysis results
|
|
105
|
+
if (options.verbose) {
|
|
106
|
+
prompts.log.info(`Project: ${projectInfo.name} (${projectInfo.projectType})`);
|
|
107
|
+
prompts.log.info(`Language: ${projectInfo.primaryLanguage}`);
|
|
108
|
+
if (projectInfo.techStack.length > 0) {
|
|
109
|
+
prompts.log.info(`Stack: ${projectInfo.techStack.join(', ')}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Generate content (either from template or project analysis)
|
|
113
|
+
let instructions;
|
|
114
|
+
let index;
|
|
115
|
+
if (selectedTemplate) {
|
|
116
|
+
instructions = selectedTemplate.instructions;
|
|
117
|
+
const indexData = {
|
|
118
|
+
projectName: selectedTemplate.name,
|
|
119
|
+
version: selectedTemplate.version,
|
|
120
|
+
projectType: selectedTemplate.projectType,
|
|
121
|
+
...selectedTemplate.metadata,
|
|
122
|
+
templateId: selectedTemplate.id,
|
|
123
|
+
templateAppliedAt: new Date().toISOString(),
|
|
124
|
+
};
|
|
125
|
+
index = JSON.stringify(indexData, null, 2);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
// Generate LLM-optimized instructions
|
|
129
|
+
const generator = new LLMOptimizedInstructionGenerator({
|
|
130
|
+
compressionLevel: 'moderate',
|
|
131
|
+
hierarchyEnabled: true,
|
|
132
|
+
criticalRulesCount: 5,
|
|
133
|
+
includeDODONT: true,
|
|
134
|
+
includeTroubleshooting: true,
|
|
135
|
+
});
|
|
136
|
+
instructions = generator.generateInstructions(projectInfo);
|
|
137
|
+
index = generator.generateIndex(projectInfo);
|
|
138
|
+
}
|
|
139
|
+
// Preview or dry-run mode
|
|
140
|
+
if (options.dryRun) {
|
|
141
|
+
prompts.log.info('Dry-run mode - no changes made');
|
|
142
|
+
prompts.log.info(`Would create: ${customMdPath}`);
|
|
143
|
+
prompts.log.info(`Would create: ${indexPath}`);
|
|
144
|
+
prompts.outro(chalk.green('Dry-run complete'));
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
// Write files using atomic operations
|
|
148
|
+
const tmpCustomPath = `${customMdPath}.tmp`;
|
|
149
|
+
const tmpIndexPath = `${indexPath}.tmp`;
|
|
150
|
+
try {
|
|
151
|
+
writeFileSync(tmpCustomPath, instructions, 'utf-8');
|
|
152
|
+
writeFileSync(tmpIndexPath, index, 'utf-8');
|
|
153
|
+
// Atomic rename
|
|
154
|
+
renameSync(tmpCustomPath, customMdPath);
|
|
155
|
+
renameSync(tmpIndexPath, indexPath);
|
|
156
|
+
prompts.log.success(`Generated custom instructions: ${customMdPath}`);
|
|
157
|
+
prompts.log.success(`Generated project index: ${indexPath}`);
|
|
158
|
+
}
|
|
159
|
+
catch (writeError) {
|
|
160
|
+
// Cleanup temp files on error
|
|
161
|
+
try {
|
|
162
|
+
if (existsSync(tmpCustomPath))
|
|
163
|
+
unlinkSync(tmpCustomPath);
|
|
164
|
+
if (existsSync(tmpIndexPath))
|
|
165
|
+
unlinkSync(tmpIndexPath);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
// Ignore cleanup errors
|
|
169
|
+
}
|
|
170
|
+
throw writeError;
|
|
171
|
+
}
|
|
172
|
+
// Show completion summary
|
|
173
|
+
await prompts.note(`Project: ${projectInfo.name} (${projectInfo.projectType})\n` +
|
|
174
|
+
`Language: ${projectInfo.primaryLanguage}\n` +
|
|
175
|
+
(projectInfo.techStack.length > 0 ? `Stack: ${projectInfo.techStack.join(', ')}\n` : '') +
|
|
176
|
+
`\nFiles created:\n` +
|
|
177
|
+
` ${customMdPath}\n` +
|
|
178
|
+
` ${indexPath}`, 'Project Summary');
|
|
179
|
+
await prompts.note('1. Review .ax-cli/CUSTOM.md and customize if needed\n' +
|
|
180
|
+
'2. Start chatting: ax-cli\n' +
|
|
181
|
+
'3. Use --force to regenerate after project changes', 'Next Steps');
|
|
182
|
+
prompts.outro(chalk.green('Project initialized successfully!'));
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
prompts.log.error(`Error during initialization: ${extractErrorMessage(error)}`);
|
|
186
|
+
if (options.verbose && error instanceof Error && error.stack) {
|
|
187
|
+
console.error('\nStack trace:');
|
|
188
|
+
console.error(error.stack);
|
|
189
|
+
}
|
|
190
|
+
process.exit(1);
|
|
39
191
|
}
|
|
40
|
-
console.log(chalk.cyan('Equivalent command:'));
|
|
41
|
-
console.log(chalk.cyan(` ax-cli ${args.join(' ')}\n`));
|
|
42
|
-
// Instead of running, just inform the user
|
|
43
|
-
console.log('Run the setup command to configure your project.\n');
|
|
44
192
|
});
|
|
45
193
|
return initCommand;
|
|
46
194
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/mcp.js
CHANGED
|
@@ -4,6 +4,7 @@ import { getTemplateNames, getTemplatesByCategory } from '../mcp/templates.js';
|
|
|
4
4
|
import { getMCPManager } from '../llm/tools.js';
|
|
5
5
|
import { MCPServerIdSchema } from '@ax-cli/schemas';
|
|
6
6
|
import chalk from 'chalk';
|
|
7
|
+
import * as prompts from '@clack/prompts';
|
|
7
8
|
import { ConsoleMessenger } from '../utils/console-messenger.js';
|
|
8
9
|
import { extractErrorMessage } from '../utils/error-handler.js';
|
|
9
10
|
import { validateServerConfig, formatValidationResult } from '../mcp/validation.js';
|
|
@@ -35,6 +36,18 @@ export function createMCPCommand() {
|
|
|
35
36
|
.option('-e, --env [env...]', 'Environment variables (key=value format)', [])
|
|
36
37
|
.action(async (name, options) => {
|
|
37
38
|
try {
|
|
39
|
+
// BUG FIX: Parse command-line --env options first to supplement process.env
|
|
40
|
+
// This handles the case where environment variables were set in a way
|
|
41
|
+
// that the current process doesn't see (e.g., exported in a subshell)
|
|
42
|
+
const cliEnvVars = {};
|
|
43
|
+
for (const envVar of options.env || []) {
|
|
44
|
+
const eqIndex = envVar.indexOf('=');
|
|
45
|
+
if (eqIndex > 0) {
|
|
46
|
+
const key = envVar.slice(0, eqIndex);
|
|
47
|
+
const value = envVar.slice(eqIndex + 1);
|
|
48
|
+
cliEnvVars[key] = value;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
38
51
|
// Check if using template
|
|
39
52
|
if (options.template) {
|
|
40
53
|
const template = getTemplate(name);
|
|
@@ -54,27 +67,49 @@ export function createMCPCommand() {
|
|
|
54
67
|
console.log(chalk.gray(template.description));
|
|
55
68
|
console.log();
|
|
56
69
|
// Check required environment variables
|
|
70
|
+
// BUG FIX: Check both process.env AND command-line --env options
|
|
57
71
|
const envVars = {};
|
|
58
|
-
|
|
72
|
+
const missingEnvVarsList = [];
|
|
59
73
|
for (const envVar of template.requiredEnv) {
|
|
60
|
-
|
|
74
|
+
// Priority: CLI --env flag > process.env
|
|
75
|
+
const value = cliEnvVars[envVar.name] || process.env[envVar.name];
|
|
61
76
|
if (!value) {
|
|
62
|
-
|
|
63
|
-
console.log(chalk.gray(` ${envVar.description}`));
|
|
64
|
-
if (envVar.url) {
|
|
65
|
-
console.log(chalk.gray(` More info: ${envVar.url}`));
|
|
66
|
-
}
|
|
67
|
-
console.log();
|
|
68
|
-
missingEnvVars = true;
|
|
77
|
+
missingEnvVarsList.push(envVar);
|
|
69
78
|
}
|
|
70
79
|
else {
|
|
71
80
|
envVars[envVar.name] = value;
|
|
72
81
|
}
|
|
73
82
|
}
|
|
74
|
-
if (
|
|
75
|
-
console.log(chalk.
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
if (missingEnvVarsList.length > 0) {
|
|
84
|
+
console.log(chalk.yellow('ā ļø Missing required environment variables:\n'));
|
|
85
|
+
for (const envVar of missingEnvVarsList) {
|
|
86
|
+
console.log(chalk.yellow(` ⢠${chalk.bold(envVar.name)}`));
|
|
87
|
+
console.log(chalk.gray(` ${envVar.description}`));
|
|
88
|
+
if (envVar.url) {
|
|
89
|
+
console.log(chalk.gray(` Documentation: ${envVar.url}`));
|
|
90
|
+
}
|
|
91
|
+
console.log();
|
|
92
|
+
}
|
|
93
|
+
console.log(chalk.red('ā Setup cannot continue without required environment variables.\n'));
|
|
94
|
+
// BUG FIX: Provide multiple options for setting environment variables
|
|
95
|
+
console.log(chalk.blue('Options to provide the missing variables:\n'));
|
|
96
|
+
// Option 1: Pass directly via --env flag
|
|
97
|
+
const envFlags = missingEnvVarsList.map(e => `--env ${e.name}=YOUR_VALUE`).join(' ');
|
|
98
|
+
console.log(chalk.white(' Option 1: Pass directly with --env flag (recommended):'));
|
|
99
|
+
console.log(chalk.cyan(` ax-cli mcp add ${name} --template ${envFlags}\n`));
|
|
100
|
+
// Option 2: Export in current shell
|
|
101
|
+
console.log(chalk.white(' Option 2: Export in current shell:'));
|
|
102
|
+
for (const envVar of missingEnvVarsList) {
|
|
103
|
+
console.log(chalk.cyan(` export ${envVar.name}="your_value"`));
|
|
104
|
+
}
|
|
105
|
+
console.log(chalk.cyan(` ax-cli mcp add ${name} --template\n`));
|
|
106
|
+
// Option 3: Add to shell profile
|
|
107
|
+
console.log(chalk.white(' Option 3: Add to shell profile (~/.bashrc or ~/.zshrc):'));
|
|
108
|
+
for (const envVar of missingEnvVarsList) {
|
|
109
|
+
console.log(chalk.cyan(` export ${envVar.name}="your_value"`));
|
|
110
|
+
}
|
|
111
|
+
console.log(chalk.gray(' Then restart your terminal or run: source ~/.zshrc\n'));
|
|
112
|
+
console.log(chalk.blue('Full setup instructions:'));
|
|
78
113
|
console.log(template.setupInstructions);
|
|
79
114
|
process.exit(1);
|
|
80
115
|
}
|
|
@@ -554,50 +589,59 @@ export function createMCPCommand() {
|
|
|
554
589
|
const { MCPHealthMonitor } = await import('../mcp/health.js');
|
|
555
590
|
const manager = getMCPManager();
|
|
556
591
|
const healthMonitor = new MCPHealthMonitor(manager);
|
|
592
|
+
// JSON mode - plain output
|
|
593
|
+
if (options.json) {
|
|
594
|
+
const health = serverName
|
|
595
|
+
? filterValidHealth([await healthMonitor.getServerStatus(serverName)])
|
|
596
|
+
: await healthMonitor.getHealthReport();
|
|
597
|
+
console.log(JSON.stringify(health, null, 2));
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
557
600
|
if (options.watch) {
|
|
558
601
|
// Continuous monitoring mode
|
|
559
|
-
|
|
560
|
-
|
|
602
|
+
prompts.intro(chalk.cyan('MCP Server Health Monitoring'));
|
|
603
|
+
prompts.log.info('Press Ctrl+C to stop');
|
|
561
604
|
// Start monitoring (uses configured health check interval)
|
|
562
605
|
healthMonitor.start(MCP_CONFIG.HEALTH_CHECK_INTERVAL);
|
|
563
606
|
// Display initial report
|
|
564
607
|
const displayHealth = async () => {
|
|
565
608
|
console.clear();
|
|
566
|
-
|
|
567
|
-
|
|
609
|
+
prompts.intro(chalk.cyan('MCP Server Health Report'));
|
|
610
|
+
prompts.log.message(`Last updated: ${new Date().toLocaleTimeString()}`);
|
|
568
611
|
const health = serverName
|
|
569
612
|
? filterValidHealth([await healthMonitor.getServerStatus(serverName)])
|
|
570
613
|
: await healthMonitor.getHealthReport();
|
|
571
614
|
if (health.length === 0) {
|
|
572
|
-
|
|
615
|
+
prompts.log.warn('No servers connected');
|
|
573
616
|
return;
|
|
574
617
|
}
|
|
575
618
|
for (const server of health) {
|
|
576
619
|
const statusIcon = server.connected ? 'ā' : 'ā';
|
|
577
|
-
const statusColor = server.connected ? chalk.green : chalk.red;
|
|
578
620
|
const statusText = server.connected ? 'Connected' : 'Disconnected';
|
|
579
|
-
|
|
580
|
-
|
|
621
|
+
// Build server info
|
|
622
|
+
const serverInfo = [];
|
|
623
|
+
serverInfo.push(`Transport: MCP`);
|
|
581
624
|
if (server.uptime) {
|
|
582
|
-
|
|
625
|
+
serverInfo.push(`Uptime: ${MCPHealthMonitor.formatUptime(server.uptime)}`);
|
|
583
626
|
}
|
|
584
|
-
|
|
627
|
+
serverInfo.push(`Tools: ${server.toolCount} available`);
|
|
585
628
|
if (server.avgLatency) {
|
|
586
|
-
|
|
629
|
+
serverInfo.push(`Latency: avg ${MCPHealthMonitor.formatLatency(server.avgLatency)}, p95 ${MCPHealthMonitor.formatLatency(server.p95Latency || 0)}`);
|
|
587
630
|
}
|
|
588
631
|
const successRateColor = server.successRate >= 95 ? chalk.green :
|
|
589
632
|
server.successRate >= 80 ? chalk.yellow : chalk.red;
|
|
590
|
-
|
|
633
|
+
serverInfo.push(`Success Rate: ${successRateColor(`${server.successRate.toFixed(1)}%`)} (${server.successCount}/${server.successCount + server.failureCount} calls)`);
|
|
591
634
|
if (server.lastError) {
|
|
592
|
-
|
|
635
|
+
serverInfo.push(chalk.red(`Last Error: ${server.lastError}`));
|
|
593
636
|
if (server.lastErrorAt) {
|
|
594
637
|
const timeSinceError = Date.now() - server.lastErrorAt;
|
|
595
|
-
|
|
638
|
+
serverInfo.push(` ${MCPHealthMonitor.formatUptime(timeSinceError)} ago`);
|
|
596
639
|
}
|
|
597
640
|
}
|
|
598
|
-
|
|
641
|
+
const titleColor = server.connected ? chalk.green : chalk.red;
|
|
642
|
+
prompts.note(serverInfo.join('\n'), titleColor(`${statusIcon} ${server.serverName} (${statusText})`));
|
|
599
643
|
}
|
|
600
|
-
|
|
644
|
+
prompts.log.message(chalk.dim('Next update in 60 seconds...'));
|
|
601
645
|
};
|
|
602
646
|
// Display immediately
|
|
603
647
|
await displayHealth();
|
|
@@ -607,67 +651,74 @@ export function createMCPCommand() {
|
|
|
607
651
|
process.once('SIGINT', () => {
|
|
608
652
|
clearInterval(watchInterval);
|
|
609
653
|
healthMonitor.stop();
|
|
610
|
-
|
|
654
|
+
prompts.outro(chalk.yellow('Stopped health monitoring'));
|
|
611
655
|
process.exit(0);
|
|
612
656
|
});
|
|
613
657
|
}
|
|
614
658
|
else {
|
|
615
|
-
// One-time health check
|
|
659
|
+
// One-time health check with @clack/prompts
|
|
660
|
+
prompts.intro(chalk.cyan('MCP Server Health'));
|
|
661
|
+
const spinner = prompts.spinner();
|
|
662
|
+
spinner.start('Checking server health...');
|
|
616
663
|
const health = serverName
|
|
617
664
|
? filterValidHealth([await healthMonitor.getServerStatus(serverName)])
|
|
618
665
|
: await healthMonitor.getHealthReport();
|
|
619
|
-
|
|
620
|
-
console.log(JSON.stringify(health, null, 2));
|
|
621
|
-
return;
|
|
622
|
-
}
|
|
666
|
+
spinner.stop('Health check complete');
|
|
623
667
|
if (health.length === 0) {
|
|
624
668
|
if (serverName) {
|
|
625
|
-
|
|
669
|
+
prompts.log.warn(`Server "${serverName}" not found`);
|
|
626
670
|
}
|
|
627
671
|
else {
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
console.log(chalk.cyan(' ax-cli mcp add figma --template'));
|
|
631
|
-
console.log();
|
|
672
|
+
prompts.log.warn('No MCP servers connected');
|
|
673
|
+
prompts.log.info('To add a server: ax-cli mcp add figma --template');
|
|
632
674
|
}
|
|
675
|
+
prompts.outro('');
|
|
633
676
|
return;
|
|
634
677
|
}
|
|
635
|
-
|
|
678
|
+
// Display each server's health
|
|
636
679
|
for (const server of health) {
|
|
637
680
|
const statusIcon = server.connected ? 'ā' : 'ā';
|
|
638
|
-
const statusColor = server.connected ? chalk.green : chalk.red;
|
|
639
681
|
const statusText = server.connected ? 'Connected' : 'Disconnected';
|
|
640
|
-
|
|
641
|
-
|
|
682
|
+
// Build server info
|
|
683
|
+
const serverInfo = [];
|
|
684
|
+
serverInfo.push(`Transport: MCP`);
|
|
642
685
|
if (server.uptime) {
|
|
643
|
-
|
|
686
|
+
serverInfo.push(`Uptime: ${MCPHealthMonitor.formatUptime(server.uptime)}`);
|
|
644
687
|
}
|
|
645
|
-
|
|
688
|
+
serverInfo.push(`Tools: ${server.toolCount} available`);
|
|
646
689
|
if (server.avgLatency) {
|
|
647
|
-
|
|
690
|
+
serverInfo.push(`Latency: avg ${MCPHealthMonitor.formatLatency(server.avgLatency)}, p95 ${MCPHealthMonitor.formatLatency(server.p95Latency || 0)}`);
|
|
648
691
|
}
|
|
649
692
|
const successRateColor = server.successRate >= 95 ? chalk.green :
|
|
650
693
|
server.successRate >= 80 ? chalk.yellow : chalk.red;
|
|
651
|
-
|
|
694
|
+
serverInfo.push(`Success Rate: ${successRateColor(`${server.successRate.toFixed(1)}%`)} (${server.successCount}/${server.successCount + server.failureCount} calls)`);
|
|
652
695
|
if (server.lastError) {
|
|
653
|
-
|
|
696
|
+
serverInfo.push(chalk.red(`Last Error: ${server.lastError}`));
|
|
654
697
|
if (server.lastErrorAt) {
|
|
655
698
|
const timeSinceError = Date.now() - server.lastErrorAt;
|
|
656
|
-
|
|
699
|
+
serverInfo.push(` ${MCPHealthMonitor.formatUptime(timeSinceError)} ago`);
|
|
657
700
|
}
|
|
658
701
|
}
|
|
659
702
|
if (server.lastSuccess) {
|
|
660
703
|
const timeSinceSuccess = Date.now() - server.lastSuccess;
|
|
661
|
-
|
|
704
|
+
serverInfo.push(`Last Successful Call: ${MCPHealthMonitor.formatUptime(timeSinceSuccess)} ago`);
|
|
662
705
|
}
|
|
663
|
-
|
|
706
|
+
const titleColor = server.connected ? chalk.green : chalk.red;
|
|
707
|
+
prompts.note(serverInfo.join('\n'), titleColor(`${statusIcon} ${server.serverName} (${statusText})`));
|
|
708
|
+
}
|
|
709
|
+
// Summary
|
|
710
|
+
const connectedCount = health.filter(s => s.connected).length;
|
|
711
|
+
const totalCount = health.length;
|
|
712
|
+
if (connectedCount === totalCount) {
|
|
713
|
+
prompts.outro(chalk.green(`All ${totalCount} server(s) healthy. Use --watch to monitor.`));
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
prompts.outro(chalk.yellow(`${connectedCount}/${totalCount} server(s) connected. Use --watch to monitor.`));
|
|
664
717
|
}
|
|
665
|
-
console.log(chalk.gray('š” Tip: Use --watch to continuously monitor server health'));
|
|
666
|
-
console.log();
|
|
667
718
|
}
|
|
668
719
|
}
|
|
669
720
|
catch (error) {
|
|
670
|
-
|
|
721
|
+
prompts.log.error(`Error: ${extractErrorMessage(error)}`);
|
|
671
722
|
process.exit(1);
|
|
672
723
|
}
|
|
673
724
|
});
|