@nolrm/contextkit 0.7.3
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 +216 -0
- package/bin/contextkit.js +324 -0
- package/bin/vibe-kit.js +3 -0
- package/install-fallback.sh +59 -0
- package/lib/commands/ai.js +147 -0
- package/lib/commands/analyze.js +544 -0
- package/lib/commands/check.js +290 -0
- package/lib/commands/dashboard.js +383 -0
- package/lib/commands/install.js +1454 -0
- package/lib/commands/note.js +120 -0
- package/lib/commands/publish.js +184 -0
- package/lib/commands/pull.js +191 -0
- package/lib/commands/run.js +232 -0
- package/lib/commands/status.js +253 -0
- package/lib/commands/update.js +376 -0
- package/lib/index.js +9 -0
- package/lib/integrations/aider-integration.js +93 -0
- package/lib/integrations/base-integration.js +123 -0
- package/lib/integrations/claude-integration.js +141 -0
- package/lib/integrations/codex-integration.js +45 -0
- package/lib/integrations/continue-integration.js +99 -0
- package/lib/integrations/copilot-integration.js +73 -0
- package/lib/integrations/cursor-integration.js +162 -0
- package/lib/integrations/gemini-integration.js +62 -0
- package/lib/integrations/index.js +33 -0
- package/lib/integrations/windsurf-integration.js +88 -0
- package/lib/utils/download.js +50 -0
- package/lib/utils/git-hooks.js +228 -0
- package/lib/utils/project-detector.js +110 -0
- package/lib/utils/status-manager.js +107 -0
- package/lib/utils/tool-detector.js +137 -0
- package/package.json +85 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const ora = require('ora');
|
|
5
|
+
|
|
6
|
+
class RunCommand {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.workflowPath = null;
|
|
9
|
+
this.workflowContent = null;
|
|
10
|
+
this.currentStep = 0;
|
|
11
|
+
this.steps = [];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async run(workflowName, options = {}) {
|
|
15
|
+
console.log(chalk.magenta(`š Running workflow: ${workflowName}\n`));
|
|
16
|
+
|
|
17
|
+
// Find workflow file
|
|
18
|
+
const possiblePaths = [
|
|
19
|
+
`.contextkit/instructions/core/${workflowName}.md`,
|
|
20
|
+
`.contextkit/instructions/${workflowName}.md`,
|
|
21
|
+
`.contextkit/commands/${workflowName}.md`
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
let workflowPath = null;
|
|
25
|
+
for (const possiblePath of possiblePaths) {
|
|
26
|
+
if (await fs.pathExists(possiblePath)) {
|
|
27
|
+
workflowPath = possiblePath;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!workflowPath) {
|
|
33
|
+
console.log(chalk.red(`ā Workflow not found: ${workflowName}`));
|
|
34
|
+
console.log(chalk.yellow(' Searched in:'));
|
|
35
|
+
possiblePaths.forEach(p => console.log(chalk.dim(` - ${p}`)));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
this.workflowPath = workflowPath;
|
|
40
|
+
this.workflowContent = await fs.readFile(workflowPath, 'utf-8');
|
|
41
|
+
|
|
42
|
+
// Parse workflow
|
|
43
|
+
const parsed = this.parseWorkflow(this.workflowContent);
|
|
44
|
+
|
|
45
|
+
if (!parsed) {
|
|
46
|
+
console.log(chalk.red('ā Failed to parse workflow'));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Execute pre-flight checks
|
|
51
|
+
if (parsed.preFlight) {
|
|
52
|
+
await this.executePreFlight(parsed.preFlight);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Execute workflow steps
|
|
56
|
+
if (parsed.steps && parsed.steps.length > 0) {
|
|
57
|
+
console.log(chalk.blue(`\nš Executing ${parsed.steps.length} step(s)...\n`));
|
|
58
|
+
|
|
59
|
+
for (let i = 0; i < parsed.steps.length; i++) {
|
|
60
|
+
const step = parsed.steps[i];
|
|
61
|
+
this.currentStep = i + 1;
|
|
62
|
+
|
|
63
|
+
console.log(chalk.cyan(`\n${'ā'.repeat(60)}`));
|
|
64
|
+
console.log(chalk.bold(`Step ${step.number}: ${step.name || 'Unnamed Step'}`));
|
|
65
|
+
console.log(chalk.cyan(`${'ā'.repeat(60)}\n`));
|
|
66
|
+
|
|
67
|
+
await this.executeStep(step, options);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Execute post-flight checks
|
|
72
|
+
if (parsed.postFlight) {
|
|
73
|
+
await this.executePostFlight(parsed.postFlight);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.log(chalk.green('\nā
Workflow completed successfully!\n'));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
parseWorkflow(content) {
|
|
80
|
+
const result = {
|
|
81
|
+
preFlight: null,
|
|
82
|
+
steps: [],
|
|
83
|
+
postFlight: null
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Extract pre-flight
|
|
87
|
+
const preFlightMatch = content.match(/<pre_flight_check>([\s\S]*?)<\/pre_flight_check>/);
|
|
88
|
+
if (preFlightMatch) {
|
|
89
|
+
result.preFlight = preFlightMatch[1].trim();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Extract process_flow and steps
|
|
93
|
+
const processFlowMatch = content.match(/<process_flow>([\s\S]*?)<\/process_flow>/);
|
|
94
|
+
if (processFlowMatch) {
|
|
95
|
+
const processFlow = processFlowMatch[1];
|
|
96
|
+
|
|
97
|
+
// Extract all steps
|
|
98
|
+
const stepRegex = /<step\s+number="(\d+)"(?:\s+subagent="([^"]+)")?(?:\s+name="([^"]+)")?>([\s\S]*?)<\/step>/g;
|
|
99
|
+
let stepMatch;
|
|
100
|
+
|
|
101
|
+
while ((stepMatch = stepRegex.exec(processFlow)) !== null) {
|
|
102
|
+
result.steps.push({
|
|
103
|
+
number: parseInt(stepMatch[1]),
|
|
104
|
+
subagent: stepMatch[2] || null,
|
|
105
|
+
name: stepMatch[3] || null,
|
|
106
|
+
content: stepMatch[4].trim()
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Extract post-flight
|
|
112
|
+
const postFlightMatch = content.match(/<post_flight_check>([\s\S]*?)<\/post_flight_check>/);
|
|
113
|
+
if (postFlightMatch) {
|
|
114
|
+
result.postFlight = postFlightMatch[1].trim();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async executePreFlight(preFlightContent) {
|
|
121
|
+
console.log(chalk.blue('š Pre-flight checks...\n'));
|
|
122
|
+
|
|
123
|
+
// Check for EXECUTE directive
|
|
124
|
+
const executeMatch = preFlightContent.match(/EXECUTE:\s*(.+)/);
|
|
125
|
+
if (executeMatch) {
|
|
126
|
+
const filePath = executeMatch[1].trim().replace('@.contextkit/', '.contextkit/');
|
|
127
|
+
|
|
128
|
+
if (await fs.pathExists(filePath)) {
|
|
129
|
+
const preFlightFile = await fs.readFile(filePath, 'utf-8');
|
|
130
|
+
console.log(chalk.dim(preFlightFile));
|
|
131
|
+
console.log('');
|
|
132
|
+
} else {
|
|
133
|
+
console.log(chalk.yellow(`ā ļø Pre-flight file not found: ${filePath}`));
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
console.log(chalk.dim(preFlightContent));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async executeStep(step, options) {
|
|
141
|
+
// Display step content
|
|
142
|
+
console.log(chalk.dim(step.content));
|
|
143
|
+
console.log('');
|
|
144
|
+
|
|
145
|
+
// Handle subagent (for now, just note it)
|
|
146
|
+
if (step.subagent) {
|
|
147
|
+
console.log(chalk.yellow(`š Subagent: ${step.subagent}`));
|
|
148
|
+
console.log(chalk.dim(' (Subagent delegation would happen here in full implementation)'));
|
|
149
|
+
console.log('');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Extract instructions from step content
|
|
153
|
+
const instructions = this.extractInstructions(step.content);
|
|
154
|
+
|
|
155
|
+
// For now, display instructions and wait for user/AI to execute
|
|
156
|
+
if (instructions.length > 0) {
|
|
157
|
+
console.log(chalk.blue('š Instructions to execute:'));
|
|
158
|
+
instructions.forEach((inst, idx) => {
|
|
159
|
+
console.log(chalk.cyan(` ${idx + 1}. ${inst}`));
|
|
160
|
+
});
|
|
161
|
+
console.log('');
|
|
162
|
+
console.log(chalk.yellow('š” Use your AI assistant to execute these instructions'));
|
|
163
|
+
console.log(chalk.yellow(' Or continue manually following the workflow steps\n'));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// In interactive mode, wait for confirmation
|
|
167
|
+
if (options.interactive) {
|
|
168
|
+
const readline = require('readline').createInterface({
|
|
169
|
+
input: process.stdin,
|
|
170
|
+
output: process.stdout
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
return new Promise((resolve) => {
|
|
174
|
+
readline.question(chalk.yellow('Press Enter to continue to next step...'), () => {
|
|
175
|
+
readline.close();
|
|
176
|
+
resolve();
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
extractInstructions(content) {
|
|
183
|
+
const instructions = [];
|
|
184
|
+
|
|
185
|
+
// Extract ACTION directives
|
|
186
|
+
const actionMatches = content.matchAll(/ACTION:\s*(.+)/gi);
|
|
187
|
+
for (const match of actionMatches) {
|
|
188
|
+
instructions.push(match[1].trim());
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Extract numbered steps
|
|
192
|
+
const stepMatches = content.matchAll(/^\d+\.\s+(.+)$/gm);
|
|
193
|
+
for (const match of stepMatches) {
|
|
194
|
+
instructions.push(match[1].trim());
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return instructions;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async executePostFlight(postFlightContent) {
|
|
201
|
+
console.log(chalk.blue('\nš Post-flight checks...\n'));
|
|
202
|
+
|
|
203
|
+
// Check for EXECUTE directive
|
|
204
|
+
const executeMatch = postFlightContent.match(/EXECUTE:\s*(.+)/);
|
|
205
|
+
if (executeMatch) {
|
|
206
|
+
const filePath = executeMatch[1].trim().replace('@.contextkit/', '.contextkit/');
|
|
207
|
+
|
|
208
|
+
if (await fs.pathExists(filePath)) {
|
|
209
|
+
const postFlightFile = await fs.readFile(filePath, 'utf-8');
|
|
210
|
+
console.log(chalk.dim(postFlightFile));
|
|
211
|
+
console.log('');
|
|
212
|
+
|
|
213
|
+
// Check for corrections log update instructions
|
|
214
|
+
if (postFlightFile.includes('corrections log')) {
|
|
215
|
+
console.log(chalk.yellow('š” Remember to update corrections.md if any issues occurred'));
|
|
216
|
+
}
|
|
217
|
+
} else {
|
|
218
|
+
console.log(chalk.yellow(`ā ļø Post-flight file not found: ${filePath}`));
|
|
219
|
+
}
|
|
220
|
+
} else {
|
|
221
|
+
console.log(chalk.dim(postFlightContent));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async function run(workflowName, options) {
|
|
227
|
+
const cmd = new RunCommand();
|
|
228
|
+
await cmd.run(workflowName, options);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
module.exports = run;
|
|
232
|
+
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const ora = require('ora');
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const StatusManager = require('../utils/status-manager');
|
|
6
|
+
|
|
7
|
+
class StatusCommand {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.configPath = '.contextkit/config.yml';
|
|
10
|
+
this.statusManager = new StatusManager();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async status() {
|
|
14
|
+
if (!await fs.pathExists(this.configPath)) {
|
|
15
|
+
console.log(chalk.red('ā ContextKit is not installed in this project'));
|
|
16
|
+
console.log(chalk.yellow('š” Run: contextkit install'));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const config = await this.parseConfig();
|
|
22
|
+
const projectType = await this.detectProjectType();
|
|
23
|
+
const packageManager = await this.detectPackageManager();
|
|
24
|
+
const status = await this.statusManager.getStatus();
|
|
25
|
+
const analyzeInfo = await this.statusManager.getAnalyzeInfo();
|
|
26
|
+
|
|
27
|
+
console.log(chalk.green('šµ ContextKit Status'));
|
|
28
|
+
console.log('');
|
|
29
|
+
|
|
30
|
+
console.log(chalk.blue('š¦ Installation:'));
|
|
31
|
+
console.log(` Version: ${status.version}`);
|
|
32
|
+
console.log(` Installed: ${new Date(status.installed_at).toLocaleDateString()}`);
|
|
33
|
+
console.log(` Last Updated: ${new Date(status.last_updated).toLocaleDateString()}`);
|
|
34
|
+
console.log('');
|
|
35
|
+
|
|
36
|
+
console.log(chalk.blue('š Analysis:'));
|
|
37
|
+
if (analyzeInfo.isFirstTime) {
|
|
38
|
+
console.log(chalk.yellow(' Status: Not analyzed'));
|
|
39
|
+
console.log(chalk.blue(' Recommendation: Run @.contextkit/commands/analyze.md to customize standards'));
|
|
40
|
+
} else {
|
|
41
|
+
console.log(chalk.green(` Status: Completed (${new Date(analyzeInfo.lastRun).toLocaleDateString()})`));
|
|
42
|
+
console.log(chalk.blue(` Project: ${analyzeInfo.projectType || 'Unknown'}`));
|
|
43
|
+
console.log(chalk.blue(` Package Manager: ${analyzeInfo.packageManager || 'Unknown'}`));
|
|
44
|
+
if (analyzeInfo.customizations.length > 0) {
|
|
45
|
+
console.log(chalk.blue(` Customizations: ${analyzeInfo.customizations.length} applied`));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
console.log('');
|
|
49
|
+
|
|
50
|
+
console.log(chalk.blue('ā
Features:'));
|
|
51
|
+
console.log(` Git Hooks: ${status.features.git_hooks ? 'ā
' : 'ā'}`);
|
|
52
|
+
console.log(` Standards: ${status.features.standards ? 'ā
' : 'ā'}`);
|
|
53
|
+
console.log(` Templates: ${status.features.templates ? 'ā
' : 'ā'}`);
|
|
54
|
+
console.log('');
|
|
55
|
+
|
|
56
|
+
// Check context files
|
|
57
|
+
console.log(chalk.blue('š Context Files (Loaded with ck "prompt"):'));
|
|
58
|
+
const contextFiles = await this.checkContextFiles();
|
|
59
|
+
console.log(` context.md: ${contextFiles.context ? 'ā
' : 'ā'}`);
|
|
60
|
+
console.log(` code-style.md: ${contextFiles.codeStyle ? 'ā
' : 'ā'}`);
|
|
61
|
+
console.log(` testing.md: ${contextFiles.testing ? 'ā
' : 'ā'}`);
|
|
62
|
+
console.log(` architecture.md: ${contextFiles.architecture ? 'ā
' : 'ā'}`);
|
|
63
|
+
console.log(` ai-guidelines.md: ${contextFiles.guidelines ? 'ā
' : 'ā'}`);
|
|
64
|
+
console.log(` glossary.md: ${contextFiles.glossary ? 'ā
' : 'ā'}`);
|
|
65
|
+
|
|
66
|
+
if (contextFiles.allPresent) {
|
|
67
|
+
console.log(chalk.green('\nā
All context files ready for AI prompts!'));
|
|
68
|
+
} else {
|
|
69
|
+
console.log(chalk.yellow('\nā ļø Some context files are missing. Run: contextkit update'));
|
|
70
|
+
}
|
|
71
|
+
console.log('');
|
|
72
|
+
|
|
73
|
+
// Platform Integrations
|
|
74
|
+
console.log(chalk.blue('š Platform Integrations:'));
|
|
75
|
+
await this.checkPlatformIntegrations();
|
|
76
|
+
console.log('');
|
|
77
|
+
|
|
78
|
+
// Check for updates
|
|
79
|
+
const updateInfo = await this.checkForUpdates(status.version);
|
|
80
|
+
if (updateInfo.hasUpdate) {
|
|
81
|
+
console.log(chalk.yellow('š Update Available!'));
|
|
82
|
+
console.log(` Current: ${updateInfo.currentVersion}`);
|
|
83
|
+
console.log(` Latest: ${updateInfo.latestVersion}`);
|
|
84
|
+
console.log(chalk.yellow('š” Run: contextkit update'));
|
|
85
|
+
} else {
|
|
86
|
+
console.log(chalk.green('ā
ContextKit is up to date'));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.log(chalk.red('ā Error reading ContextKit configuration:'), error.message);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async parseConfig() {
|
|
95
|
+
const configContent = await fs.readFile(this.configPath, 'utf8');
|
|
96
|
+
const config = {};
|
|
97
|
+
|
|
98
|
+
// Simple YAML parsing for our config format
|
|
99
|
+
const lines = configContent.split('\n');
|
|
100
|
+
for (const line of lines) {
|
|
101
|
+
const trimmed = line.trim();
|
|
102
|
+
if (trimmed.startsWith('version:')) {
|
|
103
|
+
config.version = trimmed.split('version:')[1].trim().replace(/"/g, '');
|
|
104
|
+
} else if (trimmed.startsWith('project_name:')) {
|
|
105
|
+
config.project_name = trimmed.split('project_name:')[1].trim().replace(/"/g, '');
|
|
106
|
+
} else if (trimmed.startsWith('project_type:')) {
|
|
107
|
+
config.project_type = trimmed.split('project_type:')[1].trim().replace(/"/g, '');
|
|
108
|
+
} else if (trimmed.startsWith('testing:')) {
|
|
109
|
+
config.features = config.features || {};
|
|
110
|
+
config.features.testing = trimmed.split('testing:')[1].trim() === 'true';
|
|
111
|
+
} else if (trimmed.startsWith('documentation:')) {
|
|
112
|
+
config.features = config.features || {};
|
|
113
|
+
config.features.documentation = trimmed.split('documentation:')[1].trim() === 'true';
|
|
114
|
+
} else if (trimmed.startsWith('code_review:')) {
|
|
115
|
+
config.features = config.features || {};
|
|
116
|
+
config.features.code_review = trimmed.split('code_review:')[1].trim() === 'true';
|
|
117
|
+
} else if (trimmed.startsWith('linting:')) {
|
|
118
|
+
config.features = config.features || {};
|
|
119
|
+
config.features.linting = trimmed.split('linting:')[1].trim() === 'true';
|
|
120
|
+
} else if (trimmed.startsWith('type_safety:')) {
|
|
121
|
+
config.features = config.features || {};
|
|
122
|
+
config.features.type_safety = trimmed.split('type_safety:')[1].trim() === 'true';
|
|
123
|
+
} else if (trimmed.startsWith('git_hooks:')) {
|
|
124
|
+
config.features = config.features || {};
|
|
125
|
+
config.features.git_hooks = trimmed.split('git_hooks:')[1].trim() === 'true';
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return config;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async detectProjectType() {
|
|
133
|
+
if (await fs.pathExists('package.json')) {
|
|
134
|
+
const packageJson = require(path.join(process.cwd(), 'package.json'));
|
|
135
|
+
if (packageJson.dependencies?.react || packageJson.devDependencies?.react) {
|
|
136
|
+
return 'react';
|
|
137
|
+
} else if (packageJson.dependencies?.vue || packageJson.devDependencies?.vue) {
|
|
138
|
+
return 'vue';
|
|
139
|
+
} else if (packageJson.dependencies?.['@angular/core'] || packageJson.devDependencies?.['@angular/core']) {
|
|
140
|
+
return 'angular';
|
|
141
|
+
} else if (packageJson.dependencies?.next || packageJson.devDependencies?.next) {
|
|
142
|
+
return 'nextjs';
|
|
143
|
+
} else if (packageJson.dependencies?.nuxt || packageJson.devDependencies?.nuxt) {
|
|
144
|
+
return 'nuxt';
|
|
145
|
+
} else if (packageJson.dependencies?.svelte || packageJson.devDependencies?.svelte) {
|
|
146
|
+
return 'svelte';
|
|
147
|
+
}
|
|
148
|
+
return 'node';
|
|
149
|
+
} else if (await fs.pathExists('requirements.txt') || await fs.pathExists('pyproject.toml')) {
|
|
150
|
+
return 'python';
|
|
151
|
+
} else if (await fs.pathExists('Cargo.toml')) {
|
|
152
|
+
return 'rust';
|
|
153
|
+
} else if (await fs.pathExists('go.mod')) {
|
|
154
|
+
return 'go';
|
|
155
|
+
}
|
|
156
|
+
return 'generic';
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async detectPackageManager() {
|
|
160
|
+
if (await fs.pathExists('yarn.lock')) {
|
|
161
|
+
return 'yarn';
|
|
162
|
+
} else if (await fs.pathExists('pnpm-lock.yaml')) {
|
|
163
|
+
return 'pnpm';
|
|
164
|
+
} else if (await fs.pathExists('package-lock.json')) {
|
|
165
|
+
return 'npm';
|
|
166
|
+
} else if (await fs.pathExists('package.json')) {
|
|
167
|
+
return 'npm';
|
|
168
|
+
}
|
|
169
|
+
return 'none';
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async checkForUpdates(currentVersion) {
|
|
173
|
+
try {
|
|
174
|
+
const axios = require('axios');
|
|
175
|
+
const response = await axios.get('https://api.github.com/repos/nolrm/contextkit/releases/latest', {
|
|
176
|
+
timeout: 5000
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
const latestVersion = response.data.tag_name.replace('v', '');
|
|
180
|
+
const hasUpdate = this.isNewerVersion(latestVersion, currentVersion);
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
hasUpdate,
|
|
184
|
+
currentVersion,
|
|
185
|
+
latestVersion
|
|
186
|
+
};
|
|
187
|
+
} catch (error) {
|
|
188
|
+
return {
|
|
189
|
+
hasUpdate: false,
|
|
190
|
+
currentVersion,
|
|
191
|
+
latestVersion: 'unknown',
|
|
192
|
+
error: error.message
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
isNewerVersion(latest, current) {
|
|
198
|
+
const latestParts = latest.split('.').map(Number);
|
|
199
|
+
const currentParts = current.split('.').map(Number);
|
|
200
|
+
|
|
201
|
+
for (let i = 0; i < Math.max(latestParts.length, currentParts.length); i++) {
|
|
202
|
+
const latestPart = latestParts[i] || 0;
|
|
203
|
+
const currentPart = currentParts[i] || 0;
|
|
204
|
+
|
|
205
|
+
if (latestPart > currentPart) return true;
|
|
206
|
+
if (latestPart < currentPart) return false;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async checkPlatformIntegrations() {
|
|
213
|
+
const { getAllIntegrationNames, getIntegration } = require('../integrations');
|
|
214
|
+
|
|
215
|
+
for (const name of getAllIntegrationNames()) {
|
|
216
|
+
const integration = getIntegration(name);
|
|
217
|
+
const result = await integration.validate();
|
|
218
|
+
const allFiles = [...integration.bridgeFiles, ...integration.generatedFiles];
|
|
219
|
+
|
|
220
|
+
if (allFiles.length === 0) continue;
|
|
221
|
+
|
|
222
|
+
if (result.valid) {
|
|
223
|
+
console.log(` ${integration.displayName}: ${chalk.green('ā
')} (${result.present.length} files)`);
|
|
224
|
+
} else if (result.present.length > 0) {
|
|
225
|
+
console.log(` ${integration.displayName}: ${chalk.yellow('ā ļø')} (${result.present.length}/${allFiles.length} files)`);
|
|
226
|
+
} else {
|
|
227
|
+
console.log(` ${integration.displayName}: ${chalk.dim('not installed')} ā run: ck ${name}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async checkContextFiles() {
|
|
233
|
+
const checks = {
|
|
234
|
+
context: await fs.pathExists('.contextkit/context.md'),
|
|
235
|
+
codeStyle: await fs.pathExists('.contextkit/standards/code-style.md'),
|
|
236
|
+
testing: await fs.pathExists('.contextkit/standards/testing.md'),
|
|
237
|
+
architecture: await fs.pathExists('.contextkit/standards/architecture.md'),
|
|
238
|
+
guidelines: await fs.pathExists('.contextkit/standards/ai-guidelines.md'),
|
|
239
|
+
glossary: await fs.pathExists('.contextkit/standards/glossary.md')
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
checks.allPresent = checks.context && checks.codeStyle && checks.testing && checks.architecture && checks.guidelines && checks.glossary;
|
|
243
|
+
|
|
244
|
+
return checks;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async function status() {
|
|
249
|
+
const statusChecker = new StatusCommand();
|
|
250
|
+
await statusChecker.status();
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
module.exports = status;
|