vibecodingmachine-cli 2026.2.26-1739 ā 2026.3.9-1621
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/bin/auth/auth-compliance.js +7 -1
- package/bin/commands/agent-commands.js +150 -228
- package/bin/commands/command-aliases.js +68 -0
- package/bin/vibecodingmachine.js +1 -2
- package/package.json +2 -2
- package/src/commands/agents/list.js +71 -115
- package/src/commands/agents-check.js +16 -4
- package/src/commands/analyze-file-sizes.js +1 -1
- package/src/commands/auto-direct/auto-provider-manager.js +290 -0
- package/src/commands/auto-direct/auto-status-display.js +331 -0
- package/src/commands/auto-direct/auto-utils.js +439 -0
- package/src/commands/auto-direct/file-operations.js +110 -0
- package/src/commands/auto-direct/provider-config.js +1 -1
- package/src/commands/auto-direct/provider-manager.js +1 -1
- package/src/commands/auto-direct/status-display.js +1 -1
- package/src/commands/auto-direct/utils.js +24 -18
- package/src/commands/auto-direct-refactored.js +413 -0
- package/src/commands/auto-direct.js +594 -188
- package/src/commands/requirements/commands.js +353 -0
- package/src/commands/requirements/default-handlers.js +272 -0
- package/src/commands/requirements/disable.js +97 -0
- package/src/commands/requirements/enable.js +97 -0
- package/src/commands/requirements/utils.js +194 -0
- package/src/commands/requirements-refactored.js +60 -0
- package/src/commands/requirements.js +38 -771
- package/src/commands/specs/disable.js +96 -0
- package/src/commands/specs/enable.js +96 -0
- package/src/trui/TruiInterface.js +5 -11
- package/src/trui/agents/AgentInterface.js +24 -396
- package/src/trui/agents/handlers/CommandHandler.js +93 -0
- package/src/trui/agents/handlers/ContextManager.js +117 -0
- package/src/trui/agents/handlers/DisplayHandler.js +243 -0
- package/src/trui/agents/handlers/HelpHandler.js +51 -0
- package/src/utils/auth.js +13 -111
- package/src/utils/config.js +5 -1
- package/src/utils/interactive/requirements-navigation.js +17 -15
- package/src/utils/interactive-broken.js +2 -2
- package/src/utils/provider-checker/agent-runner.js +15 -1
- package/src/utils/provider-checker/cli-installer.js +149 -7
- package/src/utils/provider-checker/opencode-checker.js +588 -0
- package/src/utils/provider-checker/provider-validator.js +88 -3
- package/src/utils/provider-checker/time-formatter.js +3 -2
- package/src/utils/provider-manager.js +28 -20
- package/src/utils/provider-registry.js +35 -3
- package/src/utils/requirements-navigator/index.js +94 -0
- package/src/utils/requirements-navigator/input-handler.js +217 -0
- package/src/utils/requirements-navigator/section-loader.js +188 -0
- package/src/utils/requirements-navigator/tree-builder.js +105 -0
- package/src/utils/requirements-navigator/tree-renderer.js +50 -0
- package/src/utils/requirements-navigator.js +2 -583
- package/src/utils/trui-clarifications.js +188 -0
- package/src/utils/trui-feedback.js +54 -1
- package/src/utils/trui-kiro-integration.js +398 -0
- package/src/utils/trui-main-handlers.js +194 -0
- package/src/utils/trui-main-menu.js +235 -0
- package/src/utils/trui-nav-agents.js +178 -25
- package/src/utils/trui-nav-requirements.js +203 -27
- package/src/utils/trui-nav-settings.js +114 -1
- package/src/utils/trui-nav-specifications.js +44 -3
- package/src/utils/trui-navigation-backup.js +603 -0
- package/src/utils/trui-navigation.js +70 -228
- package/src/utils/trui-provider-health.js +274 -0
- package/src/utils/trui-provider-manager.js +376 -0
- package/src/utils/trui-quick-menu.js +25 -1
- package/src/utils/trui-req-actions-backup.js +507 -0
- package/src/utils/trui-req-actions.js +148 -216
- package/src/utils/trui-req-editor.js +170 -0
- package/src/utils/trui-req-file-ops.js +278 -0
- package/src/utils/trui-req-tree-old.js +719 -0
- package/src/utils/trui-req-tree.js +348 -627
- package/src/utils/trui-specifications.js +25 -7
- package/src/utils/trui-windsurf.js +231 -10
- package/src/utils/welcome-screen-extracted.js +2 -2
- package/src/utils/welcome-screen.js +2 -2
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TRUI Clarification Response Editing
|
|
3
|
+
*
|
|
4
|
+
* Handles editing clarification responses for requirements with multi-line support.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
const inquirer = require('inquirer');
|
|
9
|
+
const { debugLogger } = require('./trui-debug');
|
|
10
|
+
const { editMultiLineText } = require('./trui-req-editor');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Edit clarification response for a requirement
|
|
14
|
+
* @param {Object} requirement - The requirement object with clarification
|
|
15
|
+
* @param {Function} saveCallback - Function to save the updated requirement
|
|
16
|
+
*/
|
|
17
|
+
async function editClarificationResponse(requirement, saveCallback) {
|
|
18
|
+
debugLogger.info('Opening clarification editor', { requirementId: requirement.id });
|
|
19
|
+
|
|
20
|
+
console.clear();
|
|
21
|
+
console.log(chalk.cyan('\nš Edit Clarification Response\n'));
|
|
22
|
+
console.log(chalk.gray(`Requirement: ${requirement.title}\n`));
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
// Extract current clarification response
|
|
26
|
+
const currentResponse = extractClarificationResponse(requirement);
|
|
27
|
+
|
|
28
|
+
if (!currentResponse) {
|
|
29
|
+
console.log(chalk.yellow('No clarification response found for this requirement.'));
|
|
30
|
+
await inquirer.prompt([{ type: 'input', name: 'c', message: chalk.gray('Press Enter to continue...') }]);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Show current response
|
|
35
|
+
console.log(chalk.bold('Current response:'));
|
|
36
|
+
console.log(chalk.white(currentResponse));
|
|
37
|
+
console.log();
|
|
38
|
+
|
|
39
|
+
// Edit response
|
|
40
|
+
const { action } = await inquirer.prompt([
|
|
41
|
+
{
|
|
42
|
+
type: 'list',
|
|
43
|
+
name: 'action',
|
|
44
|
+
message: 'What would you like to do?',
|
|
45
|
+
choices: [
|
|
46
|
+
{ name: 'āļø Edit response', value: 'edit' },
|
|
47
|
+
{ name: 'šļø Preview formatted', value: 'preview' },
|
|
48
|
+
{ name: 'ā Cancel', value: 'cancel' }
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
if (action === 'cancel') {
|
|
54
|
+
console.log(chalk.yellow('\nā Edit cancelled.'));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (action === 'preview') {
|
|
59
|
+
await showFormattedPreview(currentResponse);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (action === 'edit') {
|
|
64
|
+
const editedResponse = await editMultiLineText(
|
|
65
|
+
currentResponse,
|
|
66
|
+
'Edit clarification response:',
|
|
67
|
+
'clarification-response'
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
if (!editedResponse || editedResponse.trim() === currentResponse.trim()) {
|
|
71
|
+
console.log(chalk.yellow('\nā No changes made.'));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Show diff and confirm
|
|
76
|
+
const { confirmed } = await inquirer.prompt([
|
|
77
|
+
{
|
|
78
|
+
type: 'confirm',
|
|
79
|
+
name: 'confirmed',
|
|
80
|
+
message: 'Save these changes?',
|
|
81
|
+
default: true
|
|
82
|
+
}
|
|
83
|
+
]);
|
|
84
|
+
|
|
85
|
+
if (confirmed) {
|
|
86
|
+
// Update the requirement with the new response
|
|
87
|
+
const updatedRequirement = updateClarificationResponse(requirement, editedResponse);
|
|
88
|
+
await saveCallback(updatedRequirement);
|
|
89
|
+
|
|
90
|
+
console.log(chalk.green('\nā Clarification response updated successfully.'));
|
|
91
|
+
debugLogger.info('Clarification response updated', { requirementId: requirement.id });
|
|
92
|
+
} else {
|
|
93
|
+
console.log(chalk.yellow('\nā Changes discarded.'));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
} catch (error) {
|
|
98
|
+
debugLogger.error('Error editing clarification response', { error: error.message });
|
|
99
|
+
console.log(chalk.red('\nā Error editing clarification response: ' + error.message));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Extract clarification response from requirement content
|
|
105
|
+
*/
|
|
106
|
+
function extractClarificationResponse(requirement) {
|
|
107
|
+
const content = requirement.content || requirement.description || '';
|
|
108
|
+
|
|
109
|
+
// Look for clarification response section
|
|
110
|
+
const clarificationMatch = content.match(/##\s*Clarification\s*Response\s*\n([\s\S]*?)(?=\n##|\n---|$)/i);
|
|
111
|
+
if (clarificationMatch) {
|
|
112
|
+
return clarificationMatch[1].trim();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Look for response section
|
|
116
|
+
const responseMatch = content.match(/###\s*Response\s*\n([\s\S]*?)(?=\n###|\n##|\n---|$)/i);
|
|
117
|
+
if (responseMatch) {
|
|
118
|
+
return responseMatch[1].trim();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Update clarification response in requirement content
|
|
126
|
+
*/
|
|
127
|
+
function updateClarificationResponse(requirement, newResponse) {
|
|
128
|
+
const content = requirement.content || requirement.description || '';
|
|
129
|
+
|
|
130
|
+
// Update existing clarification response section
|
|
131
|
+
if (content.match(/##\s*Clarification\s*Response\s*\n/i)) {
|
|
132
|
+
const updatedContent = content.replace(
|
|
133
|
+
/##\s*Clarification\s*Response\s*\n[\s\S]*?(?=\n##|\n---|$)/i,
|
|
134
|
+
`## Clarification Response\n${newResponse}`
|
|
135
|
+
);
|
|
136
|
+
return { ...requirement, content: updatedContent };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Update existing response section
|
|
140
|
+
if (content.match(/###\s*Response\s*\n/i)) {
|
|
141
|
+
const updatedContent = content.replace(
|
|
142
|
+
/###\s*Response\s*\n[\s\S]*?(?=\n###|\n##|\n---|$)/i,
|
|
143
|
+
`### Response\n${newResponse}`
|
|
144
|
+
);
|
|
145
|
+
return { ...requirement, content: updatedContent };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Add new clarification response section at the end
|
|
149
|
+
const updatedContent = content + `\n\n## Clarification Response\n${newResponse}`;
|
|
150
|
+
return { ...requirement, content: updatedContent };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Show formatted preview of the response
|
|
155
|
+
*/
|
|
156
|
+
async function showFormattedPreview(response) {
|
|
157
|
+
console.clear();
|
|
158
|
+
console.log(chalk.bold.cyan('\nš Formatted Preview\n'));
|
|
159
|
+
console.log(chalk.gray('This is how the response will appear when rendered:\n'));
|
|
160
|
+
|
|
161
|
+
// Simple markdown-like formatting for preview
|
|
162
|
+
const formatted = response
|
|
163
|
+
.replace(/\*\*(.*?)\*\*/g, chalk.bold('$1'))
|
|
164
|
+
.replace(/\*(.*?)\*/g, chalk.italic('$1'))
|
|
165
|
+
.replace(/`(.*?)`/g, chalk.cyan('$1'))
|
|
166
|
+
.replace(/^### (.*?)$/gm, chalk.bold.underline('$1'))
|
|
167
|
+
.replace(/^## (.*?)$/gm, chalk.bold.cyan.underline('$1'))
|
|
168
|
+
.replace(/^# (.*?)$/gm, chalk.bold.white.underline('$1'));
|
|
169
|
+
|
|
170
|
+
console.log(formatted);
|
|
171
|
+
|
|
172
|
+
await inquirer.prompt([{ type: 'input', name: 'c', message: chalk.gray('Press Enter to continue...') }]);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Check if a requirement has a clarification response
|
|
177
|
+
*/
|
|
178
|
+
function hasClarificationResponse(requirement) {
|
|
179
|
+
return extractClarificationResponse(requirement) !== null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
module.exports = {
|
|
183
|
+
editClarificationResponse,
|
|
184
|
+
extractClarificationResponse,
|
|
185
|
+
updateClarificationResponse,
|
|
186
|
+
hasClarificationResponse,
|
|
187
|
+
showFormattedPreview
|
|
188
|
+
};
|
|
@@ -65,6 +65,45 @@ async function showFeedbackSubmission() {
|
|
|
65
65
|
}
|
|
66
66
|
]);
|
|
67
67
|
|
|
68
|
+
// Screenshot attachment (optional)
|
|
69
|
+
const { includeScreenshot } = await inquirer.prompt([
|
|
70
|
+
{
|
|
71
|
+
type: 'confirm',
|
|
72
|
+
name: 'includeScreenshot',
|
|
73
|
+
message: 'Include screenshot attachment?',
|
|
74
|
+
default: false
|
|
75
|
+
}
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
let screenshotPath = null;
|
|
79
|
+
if (includeScreenshot) {
|
|
80
|
+
const { screenshot } = await inquirer.prompt([
|
|
81
|
+
{
|
|
82
|
+
type: 'input',
|
|
83
|
+
name: 'screenshot',
|
|
84
|
+
message: 'Screenshot file path (or drag & drop):',
|
|
85
|
+
validate: (input) => {
|
|
86
|
+
if (!input) return 'Screenshot path is required when including screenshot';
|
|
87
|
+
const fs = require('fs');
|
|
88
|
+
const path = require('path');
|
|
89
|
+
|
|
90
|
+
if (!fs.existsSync(input.trim())) {
|
|
91
|
+
return `File not found: ${input}`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const ext = path.extname(input.trim()).toLowerCase();
|
|
95
|
+
const validExts = ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp'];
|
|
96
|
+
if (!validExts.includes(ext)) {
|
|
97
|
+
return `Invalid image format. Supported: ${validExts.join(', ')}`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
]);
|
|
104
|
+
screenshotPath = screenshot.trim();
|
|
105
|
+
}
|
|
106
|
+
|
|
68
107
|
// Confirmation
|
|
69
108
|
const { confirmed } = await inquirer.prompt([
|
|
70
109
|
{
|
|
@@ -81,7 +120,7 @@ async function showFeedbackSubmission() {
|
|
|
81
120
|
}
|
|
82
121
|
|
|
83
122
|
// Submit feedback
|
|
84
|
-
await submitFeedback({ category, feedback, email });
|
|
123
|
+
await submitFeedback({ category, feedback, email, screenshotPath });
|
|
85
124
|
|
|
86
125
|
console.log(chalk.green('\nā Thank you! Your feedback has been submitted.\n'));
|
|
87
126
|
|
|
@@ -114,6 +153,20 @@ async function submitFeedback(feedbackData) {
|
|
|
114
153
|
version: require('../../../package.json').version || 'unknown'
|
|
115
154
|
};
|
|
116
155
|
|
|
156
|
+
// Handle screenshot attachment
|
|
157
|
+
if (feedbackData.screenshotPath) {
|
|
158
|
+
const screenshotFileName = `screenshot-${Date.now()}${path.extname(feedbackData.screenshotPath)}`;
|
|
159
|
+
const screenshotDestPath = path.join(feedbackDir, screenshotFileName);
|
|
160
|
+
|
|
161
|
+
// Copy screenshot to feedback directory
|
|
162
|
+
fs.copyFileSync(feedbackData.screenshotPath, screenshotDestPath);
|
|
163
|
+
feedbackWithMeta.screenshotFile = screenshotFileName;
|
|
164
|
+
debugLogger.info('Screenshot attached', {
|
|
165
|
+
source: feedbackData.screenshotPath,
|
|
166
|
+
dest: screenshotDestPath
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
117
170
|
fs.writeFileSync(feedbackFile, JSON.stringify(feedbackWithMeta, null, 2));
|
|
118
171
|
debugLogger.info('Feedback saved locally', { file: feedbackFile });
|
|
119
172
|
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TRUI Kiro Integration Module
|
|
3
|
+
*
|
|
4
|
+
* Handles Kiro integration and installation prompts.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
const inquirer = require('inquirer');
|
|
9
|
+
const { debugLogger } = require('./trui-debug');
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Check if Kiro is installed
|
|
16
|
+
*/
|
|
17
|
+
async function isKiroInstalled() {
|
|
18
|
+
try {
|
|
19
|
+
execSync('kiro --version', { stdio: 'ignore' });
|
|
20
|
+
return true;
|
|
21
|
+
} catch (error) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Get Kiro version if installed
|
|
28
|
+
*/
|
|
29
|
+
async function getKiroVersion() {
|
|
30
|
+
try {
|
|
31
|
+
const version = execSync('kiro --version', { encoding: 'utf8' }).trim();
|
|
32
|
+
return version;
|
|
33
|
+
} catch (error) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Check if Kiro is properly configured
|
|
40
|
+
*/
|
|
41
|
+
async function isKiroConfigured() {
|
|
42
|
+
try {
|
|
43
|
+
const configPath = path.join(process.cwd(), '.kiro', 'config.json');
|
|
44
|
+
return fs.existsSync(configPath);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get Kiro configuration
|
|
52
|
+
*/
|
|
53
|
+
async function getKiroConfig() {
|
|
54
|
+
try {
|
|
55
|
+
const configPath = path.join(process.cwd(), '.kiro', 'config.json');
|
|
56
|
+
if (fs.existsSync(configPath)) {
|
|
57
|
+
const config = fs.readFileSync(configPath, 'utf8');
|
|
58
|
+
return JSON.parse(config);
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
debugLogger.error('Error reading Kiro config', { error: error.message });
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Install Kiro
|
|
69
|
+
*/
|
|
70
|
+
async function installKiro() {
|
|
71
|
+
console.log(chalk.bold.cyan('\nš Installing Kiro...\n'));
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
// Check if npm is available
|
|
75
|
+
execSync('npm --version', { stdio: 'ignore' });
|
|
76
|
+
|
|
77
|
+
console.log(chalk.gray('Installing Kiro via npm...'));
|
|
78
|
+
execSync('npm install -g kiro', { stdio: 'inherit' });
|
|
79
|
+
|
|
80
|
+
console.log(chalk.green('\nā
Kiro installed successfully!'));
|
|
81
|
+
return true;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.log(chalk.red('\nā Failed to install Kiro: ' + error.message));
|
|
84
|
+
|
|
85
|
+
// Try alternative installation methods
|
|
86
|
+
const { tryAlternative } = await inquirer.prompt([
|
|
87
|
+
{
|
|
88
|
+
type: 'confirm',
|
|
89
|
+
name: 'tryAlternative',
|
|
90
|
+
message: 'Try alternative installation methods?',
|
|
91
|
+
default: true
|
|
92
|
+
}
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
if (tryAlternative) {
|
|
96
|
+
return await tryAlternativeInstallation();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Try alternative installation methods
|
|
105
|
+
*/
|
|
106
|
+
async function tryAlternativeInstallation() {
|
|
107
|
+
console.log(chalk.yellow('\nš¦ Alternative installation options:\n'));
|
|
108
|
+
|
|
109
|
+
const { method } = await inquirer.prompt([
|
|
110
|
+
{
|
|
111
|
+
type: 'list',
|
|
112
|
+
name: 'method',
|
|
113
|
+
message: 'Choose installation method:',
|
|
114
|
+
choices: [
|
|
115
|
+
{ name: 'Download from GitHub releases', value: 'github' },
|
|
116
|
+
{ name: 'Build from source', value: 'source' },
|
|
117
|
+
{ name: 'Use package manager (yarn/pnpm)', value: 'package-manager' },
|
|
118
|
+
{ name: 'Cancel', value: 'cancel' }
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
]);
|
|
122
|
+
|
|
123
|
+
switch (method) {
|
|
124
|
+
case 'github':
|
|
125
|
+
return await installFromGitHub();
|
|
126
|
+
case 'source':
|
|
127
|
+
return await installFromSource();
|
|
128
|
+
case 'package-manager':
|
|
129
|
+
return await installWithPackageManager();
|
|
130
|
+
case 'cancel':
|
|
131
|
+
return false;
|
|
132
|
+
default:
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Install Kiro from GitHub releases
|
|
139
|
+
*/
|
|
140
|
+
async function installFromGitHub() {
|
|
141
|
+
console.log(chalk.gray('\nOpening GitHub releases page...'));
|
|
142
|
+
console.log(chalk.white('Please download the appropriate binary for your system.'));
|
|
143
|
+
console.log(chalk.cyan('https://github.com/kiro-dev/kiro/releases\n'));
|
|
144
|
+
|
|
145
|
+
const { downloaded } = await inquirer.prompt([
|
|
146
|
+
{
|
|
147
|
+
type: 'confirm',
|
|
148
|
+
name: 'downloaded',
|
|
149
|
+
message: 'Have you downloaded and installed Kiro?',
|
|
150
|
+
default: false
|
|
151
|
+
}
|
|
152
|
+
]);
|
|
153
|
+
|
|
154
|
+
if (downloaded) {
|
|
155
|
+
const verified = await verifyKiroInstallation();
|
|
156
|
+
return verified;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Install Kiro from source
|
|
164
|
+
*/
|
|
165
|
+
async function installFromSource() {
|
|
166
|
+
console.log(chalk.gray('\nCloning and building from source...'));
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
execSync('git clone https://github.com/kiro-dev/kiro.git /tmp/kiro-build', { stdio: 'inherit' });
|
|
170
|
+
process.chdir('/tmp/kiro-build');
|
|
171
|
+
execSync('npm install', { stdio: 'inherit' });
|
|
172
|
+
execSync('npm run build', { stdio: 'inherit' });
|
|
173
|
+
execSync('npm install -g .', { stdio: 'inherit' });
|
|
174
|
+
|
|
175
|
+
console.log(chalk.green('\nā
Kiro built and installed successfully!'));
|
|
176
|
+
return true;
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.log(chalk.red('\nā Failed to build from source: ' + error.message));
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Install Kiro with alternative package manager
|
|
185
|
+
*/
|
|
186
|
+
async function installWithPackageManager() {
|
|
187
|
+
const { packageManager } = await inquirer.prompt([
|
|
188
|
+
{
|
|
189
|
+
type: 'list',
|
|
190
|
+
name: 'packageManager',
|
|
191
|
+
message: 'Choose package manager:',
|
|
192
|
+
choices: [
|
|
193
|
+
{ name: 'Yarn', value: 'yarn' },
|
|
194
|
+
{ name: 'PNPM', value: 'pnpm' },
|
|
195
|
+
{ name: 'Cancel', value: 'cancel' }
|
|
196
|
+
]
|
|
197
|
+
}
|
|
198
|
+
]);
|
|
199
|
+
|
|
200
|
+
if (packageManager === 'cancel') return false;
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
console.log(chalk.gray(`Installing Kiro with ${packageManager}...`));
|
|
204
|
+
execSync(`${packageManager} global add kiro`, { stdio: 'inherit' });
|
|
205
|
+
console.log(chalk.green('\nā
Kiro installed successfully!'));
|
|
206
|
+
return true;
|
|
207
|
+
} catch (error) {
|
|
208
|
+
console.log(chalk.red(`\nā Failed to install with ${packageManager}: ` + error.message));
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Verify Kiro installation
|
|
215
|
+
*/
|
|
216
|
+
async function verifyKiroInstallation() {
|
|
217
|
+
const isInstalled = await isKiroInstalled();
|
|
218
|
+
if (isInstalled) {
|
|
219
|
+
const version = await getKiroVersion();
|
|
220
|
+
console.log(chalk.green(`ā
Kiro ${version} is installed!`));
|
|
221
|
+
return true;
|
|
222
|
+
} else {
|
|
223
|
+
console.log(chalk.red('ā Kiro installation not found.'));
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Configure Kiro for current project
|
|
230
|
+
*/
|
|
231
|
+
async function configureKiro() {
|
|
232
|
+
console.log(chalk.bold.cyan('\nāļø Configuring Kiro...\n'));
|
|
233
|
+
|
|
234
|
+
const { projectName } = await inquirer.prompt([
|
|
235
|
+
{
|
|
236
|
+
type: 'input',
|
|
237
|
+
name: 'projectName',
|
|
238
|
+
message: 'Project name:',
|
|
239
|
+
default: path.basename(process.cwd())
|
|
240
|
+
}
|
|
241
|
+
]);
|
|
242
|
+
|
|
243
|
+
const { provider } = await inquirer.prompt([
|
|
244
|
+
{
|
|
245
|
+
type: 'list',
|
|
246
|
+
name: 'provider',
|
|
247
|
+
message: 'Primary AI provider:',
|
|
248
|
+
choices: [
|
|
249
|
+
{ name: 'Claude (Anthropic)', value: 'claude' },
|
|
250
|
+
{ name: 'GPT (OpenAI)', value: 'gpt' },
|
|
251
|
+
{ name: 'Custom', value: 'custom' }
|
|
252
|
+
]
|
|
253
|
+
}
|
|
254
|
+
]);
|
|
255
|
+
|
|
256
|
+
const { autoMode } = await inquirer.prompt([
|
|
257
|
+
{
|
|
258
|
+
type: 'confirm',
|
|
259
|
+
name: 'autoMode',
|
|
260
|
+
message: 'Enable auto-mode?',
|
|
261
|
+
default: true
|
|
262
|
+
}
|
|
263
|
+
]);
|
|
264
|
+
|
|
265
|
+
// Create .kiro directory and config
|
|
266
|
+
const kiroDir = path.join(process.cwd(), '.kiro');
|
|
267
|
+
if (!fs.existsSync(kiroDir)) {
|
|
268
|
+
fs.mkdirSync(kiroDir, { recursive: true });
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const config = {
|
|
272
|
+
project: projectName,
|
|
273
|
+
provider,
|
|
274
|
+
autoMode,
|
|
275
|
+
version: '1.0.0',
|
|
276
|
+
createdAt: new Date().toISOString()
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
fs.writeFileSync(
|
|
280
|
+
path.join(kiroDir, 'config.json'),
|
|
281
|
+
JSON.stringify(config, null, 2)
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
console.log(chalk.green('\nā
Kiro configured successfully!'));
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Show Kiro status
|
|
290
|
+
*/
|
|
291
|
+
async function showKiroStatus() {
|
|
292
|
+
const isInstalled = await isKiroInstalled();
|
|
293
|
+
const version = await getKiroVersion();
|
|
294
|
+
const isConfigured = await isKiroConfigured();
|
|
295
|
+
const config = await getKiroConfig();
|
|
296
|
+
|
|
297
|
+
console.log(chalk.bold.cyan('\nš Kiro Status\n'));
|
|
298
|
+
|
|
299
|
+
console.log(`Status: ${isInstalled ? chalk.green('Installed') : chalk.red('Not Installed')}`);
|
|
300
|
+
if (version) {
|
|
301
|
+
console.log(`Version: ${chalk.white(version)}`);
|
|
302
|
+
}
|
|
303
|
+
console.log(`Configured: ${isConfigured ? chalk.green('Yes') : chalk.yellow('No')}`);
|
|
304
|
+
|
|
305
|
+
if (config) {
|
|
306
|
+
console.log(`Project: ${chalk.white(config.project)}`);
|
|
307
|
+
console.log(`Provider: ${chalk.white(config.provider)}`);
|
|
308
|
+
console.log(`Auto-mode: ${config.autoMode ? chalk.green('Enabled') : chalk.red('Disabled')}`);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
console.log();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Prompt for Kiro installation if not installed
|
|
316
|
+
*/
|
|
317
|
+
async function promptKiroInstallation() {
|
|
318
|
+
const isInstalled = await isKiroInstalled();
|
|
319
|
+
|
|
320
|
+
if (isInstalled) {
|
|
321
|
+
console.log(chalk.green('ā
Kiro is already installed.'));
|
|
322
|
+
const isConfigured = await isKiroConfigured();
|
|
323
|
+
if (!isConfigured) {
|
|
324
|
+
const { shouldConfigure } = await inquirer.prompt([
|
|
325
|
+
{
|
|
326
|
+
type: 'confirm',
|
|
327
|
+
name: 'shouldConfigure',
|
|
328
|
+
message: 'Kiro is installed but not configured. Configure it now?',
|
|
329
|
+
default: true
|
|
330
|
+
}
|
|
331
|
+
]);
|
|
332
|
+
|
|
333
|
+
if (shouldConfigure) {
|
|
334
|
+
return await configureKiro();
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
console.log(chalk.yellow('ā ļø Kiro is not installed.'));
|
|
341
|
+
|
|
342
|
+
const { shouldInstall } = await inquirer.prompt([
|
|
343
|
+
{
|
|
344
|
+
type: 'confirm',
|
|
345
|
+
name: 'shouldInstall',
|
|
346
|
+
message: 'Would you like to install Kiro now?',
|
|
347
|
+
default: true
|
|
348
|
+
}
|
|
349
|
+
]);
|
|
350
|
+
|
|
351
|
+
if (shouldInstall) {
|
|
352
|
+
const installed = await installKiro();
|
|
353
|
+
if (installed) {
|
|
354
|
+
const { shouldConfigure } = await inquirer.prompt([
|
|
355
|
+
{
|
|
356
|
+
type: 'confirm',
|
|
357
|
+
name: 'shouldConfigure',
|
|
358
|
+
message: 'Kiro installed! Configure it for this project?',
|
|
359
|
+
default: true
|
|
360
|
+
}
|
|
361
|
+
]);
|
|
362
|
+
|
|
363
|
+
if (shouldConfigure) {
|
|
364
|
+
return await configureKiro();
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Get Kiro integration status for display
|
|
374
|
+
*/
|
|
375
|
+
async function getKiroIntegrationStatus() {
|
|
376
|
+
const isInstalled = await isKiroInstalled();
|
|
377
|
+
const isConfigured = await isKiroConfigured();
|
|
378
|
+
|
|
379
|
+
return {
|
|
380
|
+
installed: isInstalled,
|
|
381
|
+
configured: isConfigured,
|
|
382
|
+
version: await getKiroVersion(),
|
|
383
|
+
config: await getKiroConfig()
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
module.exports = {
|
|
388
|
+
isKiroInstalled,
|
|
389
|
+
getKiroVersion,
|
|
390
|
+
isKiroConfigured,
|
|
391
|
+
getKiroConfig,
|
|
392
|
+
installKiro,
|
|
393
|
+
configureKiro,
|
|
394
|
+
showKiroStatus,
|
|
395
|
+
promptKiroInstallation,
|
|
396
|
+
getKiroIntegrationStatus,
|
|
397
|
+
verifyKiroInstallation
|
|
398
|
+
};
|