k0ntext 3.0.0
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 +623 -0
- package/bin/k0ntext.js +12 -0
- package/dist/agents/cleanup-agent.d.ts +39 -0
- package/dist/agents/cleanup-agent.d.ts.map +1 -0
- package/dist/agents/cleanup-agent.js +56 -0
- package/dist/agents/cleanup-agent.js.map +1 -0
- package/dist/agents/performance-agent.d.ts +37 -0
- package/dist/agents/performance-agent.d.ts.map +1 -0
- package/dist/agents/performance-agent.js +91 -0
- package/dist/agents/performance-agent.js.map +1 -0
- package/dist/analyzer/index.d.ts +5 -0
- package/dist/analyzer/index.d.ts.map +1 -0
- package/dist/analyzer/index.js +5 -0
- package/dist/analyzer/index.js.map +1 -0
- package/dist/analyzer/intelligent-analyzer.d.ts +111 -0
- package/dist/analyzer/intelligent-analyzer.d.ts.map +1 -0
- package/dist/analyzer/intelligent-analyzer.js +537 -0
- package/dist/analyzer/intelligent-analyzer.js.map +1 -0
- package/dist/cli/commands/cleanup.d.ts +3 -0
- package/dist/cli/commands/cleanup.d.ts.map +1 -0
- package/dist/cli/commands/cleanup.js +24 -0
- package/dist/cli/commands/cleanup.js.map +1 -0
- package/dist/cli/commands/export.d.ts +9 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +72 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/import.d.ts +9 -0
- package/dist/cli/commands/import.d.ts.map +1 -0
- package/dist/cli/commands/import.js +62 -0
- package/dist/cli/commands/import.js.map +1 -0
- package/dist/cli/commands/performance.d.ts +9 -0
- package/dist/cli/commands/performance.d.ts.map +1 -0
- package/dist/cli/commands/performance.js +36 -0
- package/dist/cli/commands/performance.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +9 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +82 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/commands/watch.d.ts +9 -0
- package/dist/cli/commands/watch.d.ts.map +1 -0
- package/dist/cli/commands/watch.js +72 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/generate.d.ts +3 -0
- package/dist/cli/generate.d.ts.map +1 -0
- package/dist/cli/generate.js +194 -0
- package/dist/cli/generate.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +448 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/sync.d.ts +26 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +163 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/config/cleanup-config.d.ts +26 -0
- package/dist/config/cleanup-config.d.ts.map +1 -0
- package/dist/config/cleanup-config.js +21 -0
- package/dist/config/cleanup-config.js.map +1 -0
- package/dist/db/client.d.ts +284 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +688 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/index.d.ts +6 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +6 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.d.ts +41 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +226 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/embeddings/index.d.ts +5 -0
- package/dist/embeddings/index.d.ts.map +1 -0
- package/dist/embeddings/index.js +5 -0
- package/dist/embeddings/index.js.map +1 -0
- package/dist/embeddings/openrouter.d.ts +133 -0
- package/dist/embeddings/openrouter.d.ts.map +1 -0
- package/dist/embeddings/openrouter.js +455 -0
- package/dist/embeddings/openrouter.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp.d.ts +29 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +257 -0
- package/dist/mcp.js.map +1 -0
- package/docs/ARCHIVE/MIGRATE_TO_NEW_REPO.md +222 -0
- package/docs/ARCHIVE/MIGRATE_TO_UNIFIED.md +220 -0
- package/docs/CLEANUP.md +76 -0
- package/docs/MCP_QUICKSTART.md +219 -0
- package/docs/QUICKSTART.md +119 -0
- package/docs/TROUBLESHOOTING.md +611 -0
- package/package.json +100 -0
- package/skills/context-optimize/SKILL.md +86 -0
- package/skills/implement/SKILL.md +150 -0
- package/skills/plan/SKILL.md +143 -0
- package/skills/research/SKILL.md +103 -0
- package/skills/validate/SKILL.md +62 -0
- package/skills/verify-docs/SKILL.md +77 -0
- package/src/agents/cleanup-agent.ts +96 -0
- package/src/agents/performance-agent.ts +117 -0
- package/src/analyzer/index.ts +10 -0
- package/src/analyzer/intelligent-analyzer.ts +640 -0
- package/src/cli/commands/cleanup.ts +26 -0
- package/src/cli/commands/export.ts +82 -0
- package/src/cli/commands/import.ts +73 -0
- package/src/cli/commands/performance.ts +40 -0
- package/src/cli/commands/validate.ts +98 -0
- package/src/cli/commands/watch.ts +83 -0
- package/src/cli/generate.ts +219 -0
- package/src/cli/index.ts +510 -0
- package/src/cli/sync.ts +194 -0
- package/src/config/cleanup-config.ts +42 -0
- package/src/db/client.ts +949 -0
- package/src/db/index.ts +19 -0
- package/src/db/schema.ts +241 -0
- package/src/embeddings/index.ts +11 -0
- package/src/embeddings/openrouter.ts +592 -0
- package/src/index.ts +57 -0
- package/src/mcp.ts +354 -0
- package/templates/AI_CONTEXT.md.template +245 -0
- package/templates/base/README.md +260 -0
- package/templates/base/RPI_WORKFLOW_PLAN.md +325 -0
- package/templates/base/agents/api-developer.md +76 -0
- package/templates/base/agents/context-engineer.md +525 -0
- package/templates/base/agents/core-architect.md +76 -0
- package/templates/base/agents/database-ops.md +76 -0
- package/templates/base/agents/deployment-ops.md +76 -0
- package/templates/base/agents/integration-hub.md +76 -0
- package/templates/base/analytics/README.md +114 -0
- package/templates/base/automation/config.json +58 -0
- package/templates/base/automation/generators/code-mapper.js +308 -0
- package/templates/base/automation/generators/index-builder.js +321 -0
- package/templates/base/automation/hooks/post-commit.sh +83 -0
- package/templates/base/automation/hooks/pre-commit.sh +103 -0
- package/templates/base/ci-templates/README.md +108 -0
- package/templates/base/ci-templates/github-actions/context-check.yml +144 -0
- package/templates/base/ci-templates/github-actions/validate-docs.yml +105 -0
- package/templates/base/commands/analytics.md +238 -0
- package/templates/base/commands/auto-sync.md +172 -0
- package/templates/base/commands/collab.md +194 -0
- package/templates/base/commands/context-optimize.md +226 -0
- package/templates/base/commands/help.md +485 -0
- package/templates/base/commands/rpi-implement.md +164 -0
- package/templates/base/commands/rpi-plan.md +147 -0
- package/templates/base/commands/rpi-research.md +145 -0
- package/templates/base/commands/session-resume.md +144 -0
- package/templates/base/commands/session-save.md +112 -0
- package/templates/base/commands/validate-all.md +77 -0
- package/templates/base/commands/verify-docs-current.md +86 -0
- package/templates/base/config/base.json +57 -0
- package/templates/base/config/environments/development.json +13 -0
- package/templates/base/config/environments/production.json +17 -0
- package/templates/base/config/environments/staging.json +13 -0
- package/templates/base/config/local.json.example +21 -0
- package/templates/base/context/.meta/generated-at.json +18 -0
- package/templates/base/context/ARCHITECTURE_SNAPSHOT.md +156 -0
- package/templates/base/context/CODE_TO_WORKFLOW_MAP.md +94 -0
- package/templates/base/context/FILE_OWNERSHIP.md +57 -0
- package/templates/base/context/INTEGRATION_POINTS.md +92 -0
- package/templates/base/context/KNOWN_GOTCHAS.md +195 -0
- package/templates/base/context/TESTING_MAP.md +95 -0
- package/templates/base/context/WORKFLOW_INDEX.md +129 -0
- package/templates/base/context/workflows/WORKFLOW_TEMPLATE.md +294 -0
- package/templates/base/indexes/agents/CAPABILITY_MATRIX.md +255 -0
- package/templates/base/indexes/agents/CATEGORY_INDEX.md +44 -0
- package/templates/base/indexes/code/CATEGORY_INDEX.md +38 -0
- package/templates/base/indexes/routing/CATEGORY_INDEX.md +39 -0
- package/templates/base/indexes/search/CATEGORY_INDEX.md +39 -0
- package/templates/base/indexes/workflows/CATEGORY_INDEX.md +38 -0
- package/templates/base/knowledge/README.md +98 -0
- package/templates/base/knowledge/sessions/README.md +88 -0
- package/templates/base/knowledge/sessions/TEMPLATE.md +150 -0
- package/templates/base/knowledge/shared/decisions/0001-adopt-context-engineering.md +144 -0
- package/templates/base/knowledge/shared/decisions/README.md +49 -0
- package/templates/base/knowledge/shared/decisions/TEMPLATE.md +123 -0
- package/templates/base/knowledge/shared/patterns/README.md +62 -0
- package/templates/base/knowledge/shared/patterns/TEMPLATE.md +120 -0
- package/templates/base/plans/PLAN_TEMPLATE.md +316 -0
- package/templates/base/plans/active/.gitkeep +0 -0
- package/templates/base/plans/completed/.gitkeep +0 -0
- package/templates/base/research/RESEARCH_TEMPLATE.md +245 -0
- package/templates/base/research/active/.gitkeep +0 -0
- package/templates/base/research/completed/.gitkeep +0 -0
- package/templates/base/schemas/agent.schema.json +141 -0
- package/templates/base/schemas/anchors.schema.json +54 -0
- package/templates/base/schemas/automation.schema.json +93 -0
- package/templates/base/schemas/command.schema.json +134 -0
- package/templates/base/schemas/hashes.schema.json +40 -0
- package/templates/base/schemas/manifest.schema.json +117 -0
- package/templates/base/schemas/plan.schema.json +136 -0
- package/templates/base/schemas/research.schema.json +115 -0
- package/templates/base/schemas/roles.schema.json +34 -0
- package/templates/base/schemas/session.schema.json +77 -0
- package/templates/base/schemas/settings.schema.json +244 -0
- package/templates/base/schemas/staleness.schema.json +53 -0
- package/templates/base/schemas/team-config.schema.json +42 -0
- package/templates/base/schemas/workflow.schema.json +126 -0
- package/templates/base/session/checkpoints/.gitkeep +2 -0
- package/templates/base/session/current/state.json +20 -0
- package/templates/base/session/history/.gitkeep +2 -0
- package/templates/base/settings.json +3 -0
- package/templates/base/standards/COMPATIBILITY.md +219 -0
- package/templates/base/standards/EXTENSION_GUIDELINES.md +280 -0
- package/templates/base/standards/QUALITY_CHECKLIST.md +211 -0
- package/templates/base/standards/README.md +66 -0
- package/templates/base/sync/anchors.json +6 -0
- package/templates/base/sync/hashes.json +6 -0
- package/templates/base/sync/staleness.json +10 -0
- package/templates/base/team/README.md +168 -0
- package/templates/base/team/config.json +79 -0
- package/templates/base/team/roles.json +145 -0
- package/templates/base/tools/bin/claude-context.js +151 -0
- package/templates/base/tools/lib/anchor-resolver.js +276 -0
- package/templates/base/tools/lib/config-loader.js +363 -0
- package/templates/base/tools/lib/detector.js +350 -0
- package/templates/base/tools/lib/diagnose.js +206 -0
- package/templates/base/tools/lib/drift-detector.js +373 -0
- package/templates/base/tools/lib/errors.js +199 -0
- package/templates/base/tools/lib/index.js +36 -0
- package/templates/base/tools/lib/init.js +192 -0
- package/templates/base/tools/lib/logger.js +230 -0
- package/templates/base/tools/lib/placeholder.js +201 -0
- package/templates/base/tools/lib/session-manager.js +354 -0
- package/templates/base/tools/lib/validate.js +521 -0
- package/templates/base/tools/package.json +49 -0
- package/templates/handlebars/aider-config.hbs +146 -0
- package/templates/handlebars/antigravity.hbs +377 -0
- package/templates/handlebars/claude.hbs +183 -0
- package/templates/handlebars/cline.hbs +62 -0
- package/templates/handlebars/continue-config.hbs +116 -0
- package/templates/handlebars/copilot.hbs +130 -0
- package/templates/handlebars/partials/gotcha-list.hbs +11 -0
- package/templates/handlebars/partials/header.hbs +3 -0
- package/templates/handlebars/partials/workflow-summary.hbs +16 -0
- package/templates/handlebars/windsurf-rules.hbs +69 -0
- package/templates/hooks/post-commit.hbs +28 -0
- package/templates/hooks/pre-commit.hbs +46 -0
package/src/cli/index.ts
ADDED
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AI Context CLI
|
|
5
|
+
*
|
|
6
|
+
* Unified CLI for AI Context Engineering.
|
|
7
|
+
* Supports initialization, MCP server, context generation, and cross-tool sync.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { Command } from 'commander';
|
|
11
|
+
import chalk from 'chalk';
|
|
12
|
+
import ora from 'ora';
|
|
13
|
+
import fs from 'fs';
|
|
14
|
+
import path from 'path';
|
|
15
|
+
import { fileURLToPath } from 'url';
|
|
16
|
+
|
|
17
|
+
import { createIntelligentAnalyzer } from '../analyzer/intelligent-analyzer.js';
|
|
18
|
+
import { hasOpenRouterKey } from '../embeddings/openrouter.js';
|
|
19
|
+
import { generateCommand } from './generate.js';
|
|
20
|
+
import { syncCommand } from './sync.js';
|
|
21
|
+
import { cleanupCommand } from './commands/cleanup.js';
|
|
22
|
+
import { validateCommand } from './commands/validate.js';
|
|
23
|
+
import { exportCommand } from './commands/export.js';
|
|
24
|
+
import { importCommand } from './commands/import.js';
|
|
25
|
+
import { performanceCommand } from './commands/performance.js';
|
|
26
|
+
import { watchCommand } from './commands/watch.js';
|
|
27
|
+
|
|
28
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
29
|
+
const __dirname = path.dirname(__filename);
|
|
30
|
+
|
|
31
|
+
// Read package.json for version
|
|
32
|
+
const packageJsonPath = path.join(__dirname, '../../package.json');
|
|
33
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
34
|
+
|
|
35
|
+
// Supported AI tools
|
|
36
|
+
const AI_TOOLS = ['claude', 'copilot', 'cline', 'antigravity', 'windsurf', 'aider', 'continue', 'cursor', 'gemini', 'all'];
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* ASCII Banner
|
|
40
|
+
*/
|
|
41
|
+
function showBanner(): void {
|
|
42
|
+
console.log(`
|
|
43
|
+
${chalk.cyan('╔═══════════════════════════════════════════════════════════════╗')}
|
|
44
|
+
${chalk.cyan('║')} ${chalk.bold.white('K0ntext')} ${chalk.gray('v' + packageJson.version)} ${chalk.cyan('║')}
|
|
45
|
+
${chalk.cyan('║')} ${chalk.gray('Unified context engineering for all AI coding assistants')} ${chalk.cyan('║')}
|
|
46
|
+
${chalk.cyan('╚═══════════════════════════════════════════════════════════════╝')}
|
|
47
|
+
`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Parse AI tools from comma-separated string
|
|
52
|
+
*/
|
|
53
|
+
function _parseAiTools(toolsString: string): string[] {
|
|
54
|
+
const tools = toolsString.split(',').map(t => t.trim().toLowerCase());
|
|
55
|
+
const invalid = tools.filter(t => !AI_TOOLS.includes(t));
|
|
56
|
+
|
|
57
|
+
if (invalid.length > 0) {
|
|
58
|
+
console.error(chalk.red(`\n✖ Error: Invalid AI tools: ${invalid.join(', ')}`));
|
|
59
|
+
console.error(chalk.gray(` Valid options: ${AI_TOOLS.join(', ')}`));
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const allTools = AI_TOOLS.filter(t => t !== 'all');
|
|
64
|
+
return tools.includes('all') ? allTools : tools;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Create the CLI program
|
|
69
|
+
*/
|
|
70
|
+
function createProgram(): Command {
|
|
71
|
+
const program = new Command();
|
|
72
|
+
|
|
73
|
+
program
|
|
74
|
+
.name('k0ntext')
|
|
75
|
+
.description('Unified AI Context Engineering - Intelligent context for all AI coding assistants')
|
|
76
|
+
.version(packageJson.version);
|
|
77
|
+
|
|
78
|
+
// ==================== Init Command ====================
|
|
79
|
+
program
|
|
80
|
+
.command('init')
|
|
81
|
+
.description('Initialize AI context for a project with intelligent analysis')
|
|
82
|
+
.argument('[project-name]', 'Name of the project (defaults to current directory)')
|
|
83
|
+
.option('--no-intelligent', 'Skip OpenRouter-powered intelligent analysis')
|
|
84
|
+
.action(async (projectName, options) => {
|
|
85
|
+
showBanner();
|
|
86
|
+
|
|
87
|
+
const targetDir = projectName
|
|
88
|
+
? path.resolve(process.cwd(), projectName)
|
|
89
|
+
: process.cwd();
|
|
90
|
+
|
|
91
|
+
const spinner = ora();
|
|
92
|
+
|
|
93
|
+
// Check for OpenRouter API key
|
|
94
|
+
const hasApiKey = hasOpenRouterKey();
|
|
95
|
+
if (!hasApiKey && options.intelligent !== false) {
|
|
96
|
+
console.log(chalk.yellow('\n⚠ OPENROUTER_API_KEY not found'));
|
|
97
|
+
console.log(chalk.gray(' Set OPENROUTER_API_KEY for intelligent analysis'));
|
|
98
|
+
console.log(chalk.gray(' Get your key at: https://openrouter.ai/keys\n'));
|
|
99
|
+
console.log(chalk.gray(' Continuing with basic analysis...\n'));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
// Create analyzer
|
|
104
|
+
spinner.start('Analyzing project...');
|
|
105
|
+
const analyzer = createIntelligentAnalyzer(targetDir);
|
|
106
|
+
|
|
107
|
+
// Run analysis
|
|
108
|
+
const analysis = await analyzer.analyze();
|
|
109
|
+
spinner.succeed('Analysis complete');
|
|
110
|
+
|
|
111
|
+
// Display results
|
|
112
|
+
console.log(`\n${chalk.bold('Analysis Results:')}`);
|
|
113
|
+
console.log(` ${chalk.cyan('•')} Documents: ${analysis.existingContext.files.filter(f => f.type === 'doc').length} found`);
|
|
114
|
+
console.log(` ${chalk.cyan('•')} Tool Configs: ${analysis.existingContext.tools.length} configured (${analysis.existingContext.tools.join(', ') || 'none'})`);
|
|
115
|
+
console.log(` ${chalk.cyan('•')} Tech Stack: ${analysis.techStack.languages.join(', ') || 'Unknown'}`);
|
|
116
|
+
|
|
117
|
+
if (analyzer.isIntelligentModeAvailable()) {
|
|
118
|
+
console.log(` ${chalk.green('✓')} Intelligent Analysis: Enabled`);
|
|
119
|
+
if (analysis.workflows.length > 0) {
|
|
120
|
+
console.log(` ${chalk.cyan('•')} Workflows Discovered: ${analysis.workflows.length}`);
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
console.log(` ${chalk.yellow('○')} Intelligent Analysis: Disabled (no API key)`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
console.log(`\n${chalk.bold('Summary:')}`);
|
|
127
|
+
console.log(analysis.summary);
|
|
128
|
+
|
|
129
|
+
if (analysis.suggestions.workflows.length > 0) {
|
|
130
|
+
console.log(`\n${chalk.bold('Suggested Workflows to Document:')}`);
|
|
131
|
+
for (const workflow of analysis.suggestions.workflows.slice(0, 5)) {
|
|
132
|
+
console.log(` ${chalk.cyan('•')} ${workflow}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
console.log(`\n${chalk.green('✓')} AI Context initialized successfully!`);
|
|
137
|
+
console.log(`\n${chalk.bold('Next Steps:')}`);
|
|
138
|
+
console.log(` ${chalk.cyan('1.')} Run ${chalk.white('k0ntext stats')} to view database statistics`);
|
|
139
|
+
console.log(` ${chalk.cyan('2.')} Run ${chalk.white('k0ntext mcp')} to start the MCP server`);
|
|
140
|
+
console.log(` ${chalk.cyan('3.')} Run ${chalk.white('k0ntext --help')} to explore all available commands`);
|
|
141
|
+
|
|
142
|
+
} catch (error) {
|
|
143
|
+
spinner.fail('Analysis failed');
|
|
144
|
+
console.error(chalk.red(`\nError: ${error instanceof Error ? error.message : error}`));
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// ==================== Generate Command ====================
|
|
150
|
+
program.addCommand(generateCommand);
|
|
151
|
+
|
|
152
|
+
// ==================== MCP Command ====================
|
|
153
|
+
program
|
|
154
|
+
.command('mcp')
|
|
155
|
+
.description('Start the MCP server for AI tools to connect')
|
|
156
|
+
.option('--db <path>', 'Database file path', '.ai-context.db')
|
|
157
|
+
.action(async (options) => {
|
|
158
|
+
const projectRoot = process.cwd();
|
|
159
|
+
|
|
160
|
+
console.error(chalk.cyan('AI Context MCP Server starting...'));
|
|
161
|
+
console.error(chalk.gray(`Project root: ${projectRoot}`));
|
|
162
|
+
console.error(chalk.gray(`Database: ${options.db}`));
|
|
163
|
+
|
|
164
|
+
// Dynamic import of server module
|
|
165
|
+
try {
|
|
166
|
+
const { startServer } = await import('../mcp.js');
|
|
167
|
+
await startServer({
|
|
168
|
+
projectRoot,
|
|
169
|
+
dbPath: options.db
|
|
170
|
+
});
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.error(chalk.red(`\nError starting MCP server: ${error instanceof Error ? error.message : error}`));
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// ==================== Sync Command ====================
|
|
178
|
+
program.addCommand(syncCommand);
|
|
179
|
+
|
|
180
|
+
// ==================== Cleanup Command ====================
|
|
181
|
+
program.addCommand(cleanupCommand);
|
|
182
|
+
|
|
183
|
+
// ==================== Validate Command ====================
|
|
184
|
+
program.addCommand(validateCommand);
|
|
185
|
+
|
|
186
|
+
// ==================== Export Command ====================
|
|
187
|
+
program.addCommand(exportCommand);
|
|
188
|
+
|
|
189
|
+
// ==================== Import Command ====================
|
|
190
|
+
program.addCommand(importCommand);
|
|
191
|
+
|
|
192
|
+
// ==================== Performance Command ====================
|
|
193
|
+
program.addCommand(performanceCommand);
|
|
194
|
+
|
|
195
|
+
// ==================== Watch Command ====================
|
|
196
|
+
program.addCommand(watchCommand);
|
|
197
|
+
|
|
198
|
+
// ==================== Index Command ====================
|
|
199
|
+
program
|
|
200
|
+
.command('index')
|
|
201
|
+
.description('Index codebase content into the database')
|
|
202
|
+
.option('--docs', 'Index documentation files only')
|
|
203
|
+
.option('--code', 'Index source code only')
|
|
204
|
+
.option('--tools', 'Index AI tool configurations only')
|
|
205
|
+
.option('--all', 'Index everything (default)')
|
|
206
|
+
.option('-v, --verbose', 'Show detailed output')
|
|
207
|
+
.action(async (options) => {
|
|
208
|
+
showBanner();
|
|
209
|
+
|
|
210
|
+
const spinner = ora();
|
|
211
|
+
let db: any;
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
spinner.start('Discovering content...');
|
|
215
|
+
|
|
216
|
+
const analyzer = createIntelligentAnalyzer(process.cwd());
|
|
217
|
+
const { DatabaseClient } = await import('../db/client.js');
|
|
218
|
+
db = new DatabaseClient(process.cwd());
|
|
219
|
+
|
|
220
|
+
let discoveredCount = 0;
|
|
221
|
+
let indexedCount = 0;
|
|
222
|
+
const allIndexedFiles: string[] = []; // Track all indexed files for embeddings
|
|
223
|
+
|
|
224
|
+
if (options.all || (!options.docs && !options.code && !options.tools)) {
|
|
225
|
+
// Discover everything
|
|
226
|
+
const [docs, code, tools] = await Promise.all([
|
|
227
|
+
analyzer.discoverDocs(),
|
|
228
|
+
analyzer.discoverCode(),
|
|
229
|
+
analyzer.discoverToolConfigs()
|
|
230
|
+
]);
|
|
231
|
+
discoveredCount = docs.length + code.length + tools.length;
|
|
232
|
+
|
|
233
|
+
spinner.text = `Indexing ${discoveredCount} files...`;
|
|
234
|
+
|
|
235
|
+
// Store docs in database
|
|
236
|
+
for (const doc of docs) {
|
|
237
|
+
const content = fs.existsSync(doc.path) ? fs.readFileSync(doc.path, 'utf-8').slice(0, 50000) : '';
|
|
238
|
+
db.upsertItem({
|
|
239
|
+
type: 'doc',
|
|
240
|
+
name: path.basename(doc.relativePath),
|
|
241
|
+
content,
|
|
242
|
+
filePath: doc.relativePath,
|
|
243
|
+
metadata: { size: doc.size }
|
|
244
|
+
});
|
|
245
|
+
indexedCount++;
|
|
246
|
+
allIndexedFiles.push(doc.relativePath);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Store tool configs in database
|
|
250
|
+
for (const config of tools) {
|
|
251
|
+
const content = fs.existsSync(config.path) ? fs.readFileSync(config.path, 'utf-8').slice(0, 50000) : '';
|
|
252
|
+
db.upsertItem({
|
|
253
|
+
type: 'tool_config',
|
|
254
|
+
name: `${config.tool}:${path.basename(config.relativePath)}`,
|
|
255
|
+
content,
|
|
256
|
+
filePath: config.relativePath,
|
|
257
|
+
metadata: { tool: config.tool, size: config.size }
|
|
258
|
+
});
|
|
259
|
+
indexedCount++;
|
|
260
|
+
allIndexedFiles.push(config.relativePath);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Store code in database (first N files to avoid overwhelming the db)
|
|
264
|
+
const maxCodeFiles = 100;
|
|
265
|
+
for (const codeFile of code.slice(0, maxCodeFiles)) {
|
|
266
|
+
const content = fs.existsSync(codeFile.path) ? fs.readFileSync(codeFile.path, 'utf-8').slice(0, 20000) : '';
|
|
267
|
+
db.upsertItem({
|
|
268
|
+
type: 'code',
|
|
269
|
+
name: path.basename(codeFile.relativePath),
|
|
270
|
+
content,
|
|
271
|
+
filePath: codeFile.relativePath,
|
|
272
|
+
metadata: { size: codeFile.size }
|
|
273
|
+
});
|
|
274
|
+
indexedCount++;
|
|
275
|
+
allIndexedFiles.push(codeFile.relativePath);
|
|
276
|
+
}
|
|
277
|
+
if (code.length > maxCodeFiles) {
|
|
278
|
+
console.log(chalk.gray(`\nNote: Indexed first ${maxCodeFiles} of ${code.length} code files.`));
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
if (options.docs) {
|
|
282
|
+
const docs = await analyzer.discoverDocs();
|
|
283
|
+
discoveredCount += docs.length;
|
|
284
|
+
spinner.text = `Indexing ${docs.length} docs...`;
|
|
285
|
+
for (const doc of docs) {
|
|
286
|
+
const content = fs.existsSync(doc.path) ? fs.readFileSync(doc.path, 'utf-8').slice(0, 50000) : '';
|
|
287
|
+
db.upsertItem({
|
|
288
|
+
type: 'doc',
|
|
289
|
+
name: path.basename(doc.relativePath),
|
|
290
|
+
content,
|
|
291
|
+
filePath: doc.relativePath,
|
|
292
|
+
metadata: { size: doc.size }
|
|
293
|
+
});
|
|
294
|
+
indexedCount++;
|
|
295
|
+
allIndexedFiles.push(doc.relativePath);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (options.code) {
|
|
299
|
+
const code = await analyzer.discoverCode();
|
|
300
|
+
discoveredCount += code.length;
|
|
301
|
+
const maxCodeFiles = 100;
|
|
302
|
+
spinner.text = `Indexing code files...`;
|
|
303
|
+
for (const codeFile of code.slice(0, maxCodeFiles)) {
|
|
304
|
+
const content = fs.existsSync(codeFile.path) ? fs.readFileSync(codeFile.path, 'utf-8').slice(0, 20000) : '';
|
|
305
|
+
db.upsertItem({
|
|
306
|
+
type: 'code',
|
|
307
|
+
name: path.basename(codeFile.relativePath),
|
|
308
|
+
content,
|
|
309
|
+
filePath: codeFile.relativePath,
|
|
310
|
+
metadata: { size: codeFile.size }
|
|
311
|
+
});
|
|
312
|
+
indexedCount++;
|
|
313
|
+
allIndexedFiles.push(codeFile.relativePath);
|
|
314
|
+
}
|
|
315
|
+
if (code.length > maxCodeFiles) {
|
|
316
|
+
console.log(chalk.gray(`\nNote: Indexed first ${maxCodeFiles} of ${code.length} code files.`));
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (options.tools) {
|
|
320
|
+
const tools = await analyzer.discoverToolConfigs();
|
|
321
|
+
discoveredCount += tools.length;
|
|
322
|
+
spinner.text = `Indexing ${tools.length} tool configs...`;
|
|
323
|
+
for (const config of tools) {
|
|
324
|
+
const content = fs.existsSync(config.path) ? fs.readFileSync(config.path, 'utf-8').slice(0, 50000) : '';
|
|
325
|
+
db.upsertItem({
|
|
326
|
+
type: 'tool_config',
|
|
327
|
+
name: `${config.tool}:${path.basename(config.relativePath)}`,
|
|
328
|
+
content,
|
|
329
|
+
filePath: config.relativePath,
|
|
330
|
+
metadata: { tool: config.tool, size: config.size }
|
|
331
|
+
});
|
|
332
|
+
indexedCount++;
|
|
333
|
+
allIndexedFiles.push(config.relativePath);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Generate embeddings if OpenRouter is available
|
|
339
|
+
let embeddingsCount = 0;
|
|
340
|
+
if (hasOpenRouterKey() && indexedCount > 0) {
|
|
341
|
+
spinner.text = `Generating embeddings for ${indexedCount} files...`;
|
|
342
|
+
|
|
343
|
+
try {
|
|
344
|
+
const embeddings = await analyzer.generateEmbeddings(
|
|
345
|
+
allIndexedFiles.map(fp => ({
|
|
346
|
+
path: path.resolve(process.cwd(), fp),
|
|
347
|
+
relativePath: fp,
|
|
348
|
+
type: 'code' as const,
|
|
349
|
+
size: 0
|
|
350
|
+
}))
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
spinner.text = `Storing ${embeddings.size} embeddings...`;
|
|
354
|
+
for (const [filePath, embedding] of embeddings.entries()) {
|
|
355
|
+
db.insertEmbedding(filePath, embedding);
|
|
356
|
+
embeddingsCount++;
|
|
357
|
+
}
|
|
358
|
+
} catch (error) {
|
|
359
|
+
spinner.warn(`Indexed ${indexedCount} files (embeddings failed: ${error instanceof Error ? error.message : error})`);
|
|
360
|
+
embeddingsCount = 0;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (embeddingsCount > 0) {
|
|
365
|
+
spinner.succeed(`Discovered ${discoveredCount} files, indexed ${indexedCount} into database, generated ${embeddingsCount} embeddings`);
|
|
366
|
+
} else {
|
|
367
|
+
spinner.succeed(`Discovered ${discoveredCount} files, indexed ${indexedCount} into database`);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
} catch (error) {
|
|
371
|
+
spinner.fail('Indexing failed');
|
|
372
|
+
console.error(chalk.red(`\nError: ${error instanceof Error ? error.message : error}`));
|
|
373
|
+
process.exit(1);
|
|
374
|
+
} finally {
|
|
375
|
+
if (db && typeof db.close === 'function') {
|
|
376
|
+
try {
|
|
377
|
+
db.close();
|
|
378
|
+
} catch {
|
|
379
|
+
// Ignore close errors
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// ==================== Search Command ====================
|
|
386
|
+
program
|
|
387
|
+
.command('search <query>')
|
|
388
|
+
.description('Search across indexed content')
|
|
389
|
+
.option('-t, --type <type>', 'Filter by type (workflow, agent, command, code, doc)')
|
|
390
|
+
.option('-l, --limit <n>', 'Maximum results', '10')
|
|
391
|
+
.option('-m, --mode <mode>', 'Search mode: text, semantic, hybrid (default: hybrid)', 'hybrid')
|
|
392
|
+
.action(async (query, options) => {
|
|
393
|
+
const spinner = ora();
|
|
394
|
+
let db: any;
|
|
395
|
+
|
|
396
|
+
try {
|
|
397
|
+
const limit =
|
|
398
|
+
typeof options.limit === 'string'
|
|
399
|
+
? Number.parseInt(options.limit, 10) || 10
|
|
400
|
+
: 10;
|
|
401
|
+
|
|
402
|
+
const mode = options.mode || 'hybrid';
|
|
403
|
+
|
|
404
|
+
spinner.start('Searching...');
|
|
405
|
+
|
|
406
|
+
const { DatabaseClient } = await import('../db/client.js');
|
|
407
|
+
db = new DatabaseClient(process.cwd());
|
|
408
|
+
|
|
409
|
+
let items: Array<{ type: string; name?: string; id?: string; filePath?: string }>;
|
|
410
|
+
|
|
411
|
+
if (mode === 'semantic') {
|
|
412
|
+
// Semantic search requires query embedding
|
|
413
|
+
const { createIntelligentAnalyzer } = await import('../analyzer/intelligent-analyzer.js');
|
|
414
|
+
const analyzer = createIntelligentAnalyzer(process.cwd());
|
|
415
|
+
|
|
416
|
+
if (!analyzer.isIntelligentModeAvailable()) {
|
|
417
|
+
spinner.fail('Semantic search requires OPENROUTER_API_KEY');
|
|
418
|
+
process.exit(1);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const queryEmbedding = await analyzer.embedText(query);
|
|
422
|
+
const results = db.searchByEmbedding(queryEmbedding, limit);
|
|
423
|
+
items = results.map((r: { item: { type: string; name?: string; id?: string; filePath?: string } }) => r.item);
|
|
424
|
+
} else if (mode === 'text') {
|
|
425
|
+
// Pure text search
|
|
426
|
+
const results = db.searchText(query, options.type);
|
|
427
|
+
items = Array.isArray(results) ? results.slice(0, limit) : [];
|
|
428
|
+
} else {
|
|
429
|
+
// Hybrid search (default)
|
|
430
|
+
const { createIntelligentAnalyzer } = await import('../analyzer/intelligent-analyzer.js');
|
|
431
|
+
const analyzer = createIntelligentAnalyzer(process.cwd());
|
|
432
|
+
|
|
433
|
+
let queryEmbedding: number[] | null = null;
|
|
434
|
+
if (analyzer.isIntelligentModeAvailable()) {
|
|
435
|
+
queryEmbedding = await analyzer.embedText(query);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
const results = db.hybridSearch(query, queryEmbedding, { limit, type: options.type });
|
|
439
|
+
// Unwrap items from { item, similarity } structure
|
|
440
|
+
items = Array.isArray(results) ? results.slice(0, limit).map((r: { item: { type: string; name?: string; id?: string; filePath?: string } }) => r.item) : [];
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
spinner.stop();
|
|
444
|
+
|
|
445
|
+
if (items.length === 0) {
|
|
446
|
+
console.log(chalk.yellow('\nNo matching results found.'));
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
console.log(chalk.bold(`\nSearch results for "${query}":`));
|
|
451
|
+
|
|
452
|
+
for (const [index, item] of items.entries()) {
|
|
453
|
+
const idx = chalk.cyan(`#${index + 1}`);
|
|
454
|
+
const title = item.name || item.id || '(untitled)';
|
|
455
|
+
const typeLabel = item.type ? String(item.type) : 'item';
|
|
456
|
+
const pathInfo = item.filePath ? chalk.gray(` (${item.filePath})`) : '';
|
|
457
|
+
|
|
458
|
+
console.log(` ${idx} ${chalk.bold(String(title))} [${typeLabel}]${pathInfo}`);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
} catch (error) {
|
|
462
|
+
spinner.fail('Search failed');
|
|
463
|
+
console.error(chalk.red(`\nError: ${error instanceof Error ? error.message : error}`));
|
|
464
|
+
process.exit(1);
|
|
465
|
+
} finally {
|
|
466
|
+
if (db && typeof db.close === 'function') {
|
|
467
|
+
try {
|
|
468
|
+
db.close();
|
|
469
|
+
} catch {
|
|
470
|
+
// Ignore close errors
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
// ==================== Stats Command ====================
|
|
477
|
+
program
|
|
478
|
+
.command('stats')
|
|
479
|
+
.description('Show database and indexing statistics')
|
|
480
|
+
.action(async () => {
|
|
481
|
+
showBanner();
|
|
482
|
+
|
|
483
|
+
try {
|
|
484
|
+
const { DatabaseClient } = await import('../db/client.js');
|
|
485
|
+
const db = new DatabaseClient(process.cwd());
|
|
486
|
+
|
|
487
|
+
const stats = db.getStats();
|
|
488
|
+
|
|
489
|
+
console.log(`${chalk.bold('Database Statistics:')}`);
|
|
490
|
+
console.log(` ${chalk.cyan('•')} Context Items: ${stats.items}`);
|
|
491
|
+
console.log(` ${chalk.cyan('•')} Relations: ${stats.relations}`);
|
|
492
|
+
console.log(` ${chalk.cyan('•')} Git Commits: ${stats.commits}`);
|
|
493
|
+
console.log(` ${chalk.cyan('•')} Embeddings: ${stats.embeddings}`);
|
|
494
|
+
console.log(` ${chalk.cyan('•')} Tool Configs: ${stats.toolConfigs}`);
|
|
495
|
+
console.log(` ${chalk.cyan('•')} Database Path: ${db.getPath()}`);
|
|
496
|
+
|
|
497
|
+
db.close();
|
|
498
|
+
|
|
499
|
+
} catch (error) {
|
|
500
|
+
console.error(chalk.red(`\nError: ${error instanceof Error ? error.message : error}`));
|
|
501
|
+
process.exit(1);
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
return program;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Main entry point
|
|
509
|
+
const program = createProgram();
|
|
510
|
+
program.parse();
|