cntx-ui 3.0.8 → 3.1.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/dist/bin/cntx-ui.js +89 -0
- package/dist/lib/agent-runtime.js +269 -0
- package/dist/lib/agent-tools.js +162 -0
- package/dist/lib/api-router.js +387 -0
- package/dist/lib/bundle-manager.js +236 -0
- package/dist/lib/configuration-manager.js +230 -0
- package/dist/lib/database-manager.js +277 -0
- package/dist/lib/file-system-manager.js +305 -0
- package/dist/lib/function-level-chunker.js +144 -0
- package/dist/lib/heuristics-manager.js +491 -0
- package/dist/lib/mcp-server.js +159 -0
- package/dist/lib/mcp-transport.js +10 -0
- package/dist/lib/semantic-splitter.js +335 -0
- package/dist/lib/simple-vector-store.js +98 -0
- package/dist/lib/treesitter-semantic-chunker.js +277 -0
- package/dist/lib/websocket-manager.js +268 -0
- package/dist/server.js +413 -0
- package/package.json +17 -8
- package/bin/cntx-ui-mcp.sh +0 -3
- package/bin/cntx-ui.js +0 -123
- package/lib/agent-runtime.js +0 -371
- package/lib/agent-tools.js +0 -370
- package/lib/api-router.js +0 -1026
- package/lib/bundle-manager.js +0 -326
- package/lib/configuration-manager.js +0 -760
- package/lib/database-manager.js +0 -397
- package/lib/file-system-manager.js +0 -489
- package/lib/function-level-chunker.js +0 -406
- package/lib/heuristics-manager.js +0 -529
- package/lib/mcp-server.js +0 -1380
- package/lib/mcp-transport.js +0 -97
- package/lib/semantic-splitter.js +0 -347
- package/lib/simple-vector-store.js +0 -108
- package/lib/treesitter-semantic-chunker.js +0 -1557
- package/lib/websocket-manager.js +0 -470
- package/server.js +0 -687
package/dist/server.js
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refactored cntx-ui Server
|
|
3
|
+
* Lean orchestration layer using modular architecture
|
|
4
|
+
*/
|
|
5
|
+
import { createServer } from 'http';
|
|
6
|
+
import { join, dirname, extname } from 'path';
|
|
7
|
+
import { fileURLToPath, parse } from 'url';
|
|
8
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync, cpSync } from 'fs';
|
|
9
|
+
import { homedir } from 'os';
|
|
10
|
+
// Import our modular components
|
|
11
|
+
import ConfigurationManager from './lib/configuration-manager.js';
|
|
12
|
+
import FileSystemManager from './lib/file-system-manager.js';
|
|
13
|
+
import BundleManager from './lib/bundle-manager.js';
|
|
14
|
+
import APIRouter from './lib/api-router.js';
|
|
15
|
+
import WebSocketManager from './lib/websocket-manager.js';
|
|
16
|
+
// Import existing lib modules
|
|
17
|
+
import SemanticSplitter from './lib/semantic-splitter.js';
|
|
18
|
+
import SimpleVectorStore from './lib/simple-vector-store.js';
|
|
19
|
+
import { MCPServer } from './lib/mcp-server.js';
|
|
20
|
+
import AgentRuntime from './lib/agent-runtime.js';
|
|
21
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
22
|
+
export class CntxServer {
|
|
23
|
+
CWD;
|
|
24
|
+
CNTX_DIR;
|
|
25
|
+
verbose;
|
|
26
|
+
mcpServerStarted;
|
|
27
|
+
mcpServer;
|
|
28
|
+
initMessages;
|
|
29
|
+
configManager;
|
|
30
|
+
databaseManager;
|
|
31
|
+
fileSystemManager;
|
|
32
|
+
bundleManager;
|
|
33
|
+
webSocketManager;
|
|
34
|
+
apiRouter;
|
|
35
|
+
semanticSplitter;
|
|
36
|
+
vectorStore;
|
|
37
|
+
agentRuntime;
|
|
38
|
+
semanticCache;
|
|
39
|
+
lastSemanticAnalysis;
|
|
40
|
+
vectorStoreInitialized;
|
|
41
|
+
semanticAnalysisManager;
|
|
42
|
+
activityManager;
|
|
43
|
+
constructor(cwd = process.cwd(), options = {}) {
|
|
44
|
+
this.CWD = cwd;
|
|
45
|
+
this.CNTX_DIR = join(cwd, '.cntx');
|
|
46
|
+
this.verbose = options.verbose || false;
|
|
47
|
+
this.mcpServerStarted = false;
|
|
48
|
+
this.mcpServer = null;
|
|
49
|
+
this.initMessages = [];
|
|
50
|
+
// Ensure directory exists
|
|
51
|
+
if (!existsSync(this.CNTX_DIR))
|
|
52
|
+
mkdirSync(this.CNTX_DIR, { recursive: true });
|
|
53
|
+
// Initialize modular components
|
|
54
|
+
this.configManager = new ConfigurationManager(cwd, { verbose: this.verbose });
|
|
55
|
+
this.databaseManager = this.configManager.dbManager;
|
|
56
|
+
this.fileSystemManager = new FileSystemManager(cwd, { verbose: this.verbose });
|
|
57
|
+
this.bundleManager = new BundleManager(this.configManager, this.fileSystemManager, this.verbose);
|
|
58
|
+
this.webSocketManager = new WebSocketManager(this.bundleManager, this.configManager, { verbose: this.verbose });
|
|
59
|
+
// AI Components
|
|
60
|
+
this.semanticSplitter = new SemanticSplitter({
|
|
61
|
+
maxChunkSize: 2000,
|
|
62
|
+
includeContext: true,
|
|
63
|
+
minFunctionSize: 50
|
|
64
|
+
});
|
|
65
|
+
this.vectorStore = new SimpleVectorStore(this.databaseManager, {
|
|
66
|
+
modelName: 'Xenova/all-MiniLM-L6-v2'
|
|
67
|
+
});
|
|
68
|
+
this.semanticCache = null;
|
|
69
|
+
this.lastSemanticAnalysis = null;
|
|
70
|
+
this.vectorStoreInitialized = false;
|
|
71
|
+
// Initialize Agent Runtime
|
|
72
|
+
this.agentRuntime = new AgentRuntime(this);
|
|
73
|
+
this.semanticAnalysisManager = this; // Self as manager
|
|
74
|
+
this.activityManager = this; // Simple mock for now
|
|
75
|
+
// Initialize API router
|
|
76
|
+
this.apiRouter = new APIRouter(this, this.configManager, this.bundleManager, this.fileSystemManager, this.semanticAnalysisManager, this.vectorStore, this.activityManager);
|
|
77
|
+
// Cross-module linkage
|
|
78
|
+
this.bundleManager.fileSystemManager = this.fileSystemManager;
|
|
79
|
+
this.bundleManager.webSocketManager = this.webSocketManager;
|
|
80
|
+
}
|
|
81
|
+
async init(options = {}) {
|
|
82
|
+
const { skipFileWatcher = false, skipBundleGeneration = false } = options;
|
|
83
|
+
// Load configs
|
|
84
|
+
this.configManager.loadConfig();
|
|
85
|
+
this.configManager.loadHiddenFilesConfig();
|
|
86
|
+
this.configManager.loadIgnorePatterns();
|
|
87
|
+
this.configManager.loadBundleStates();
|
|
88
|
+
if (!skipFileWatcher) {
|
|
89
|
+
this.startWatching();
|
|
90
|
+
// Trigger semantic analysis
|
|
91
|
+
if (!this.semanticCache) {
|
|
92
|
+
this.getSemanticAnalysis().catch(err => console.error('Initial semantic analysis failed:', err.message));
|
|
93
|
+
}
|
|
94
|
+
if (!skipBundleGeneration) {
|
|
95
|
+
await this.bundleManager.generateAllBundles();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Load reasoning/manifest
|
|
99
|
+
await this.agentRuntime.generateAgentManifest();
|
|
100
|
+
}
|
|
101
|
+
startWatching() {
|
|
102
|
+
this.fileSystemManager.startWatching((eventType, filename) => {
|
|
103
|
+
this.bundleManager.markBundlesChanged(filename);
|
|
104
|
+
this.webSocketManager.onFileChanged(filename, eventType);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
async getSemanticAnalysis() {
|
|
108
|
+
// Try SQLite first
|
|
109
|
+
try {
|
|
110
|
+
const dbChunks = this.databaseManager.db.prepare('SELECT * FROM semantic_chunks').all();
|
|
111
|
+
if (dbChunks.length > 0) {
|
|
112
|
+
if (!this.semanticCache) {
|
|
113
|
+
this.semanticCache = {
|
|
114
|
+
chunks: dbChunks.map(row => this.databaseManager.mapChunkRow(row)),
|
|
115
|
+
summary: { totalChunks: dbChunks.length }
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return this.semanticCache;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch (e) { }
|
|
122
|
+
// Fresh analysis
|
|
123
|
+
const files = this.fileSystemManager.getAllFiles().map(f => this.fileSystemManager.relativePath(f))
|
|
124
|
+
.filter(f => ['.js', '.jsx', '.ts', '.tsx', '.rs'].includes(extname(f).toLowerCase()));
|
|
125
|
+
let bundleConfig = null;
|
|
126
|
+
if (existsSync(this.configManager.CONFIG_FILE)) {
|
|
127
|
+
bundleConfig = JSON.parse(readFileSync(this.configManager.CONFIG_FILE, 'utf8'));
|
|
128
|
+
}
|
|
129
|
+
this.semanticCache = await this.semanticSplitter.extractSemanticChunks(this.CWD, files, bundleConfig);
|
|
130
|
+
this.lastSemanticAnalysis = Date.now();
|
|
131
|
+
if (this.semanticCache.chunks.length > 0) {
|
|
132
|
+
this.databaseManager.saveChunks(this.semanticCache.chunks);
|
|
133
|
+
}
|
|
134
|
+
this.enhanceSemanticChunksIfNeeded(this.semanticCache);
|
|
135
|
+
return this.semanticCache;
|
|
136
|
+
}
|
|
137
|
+
async enhanceSemanticChunksIfNeeded(analysis) {
|
|
138
|
+
if (!analysis || !analysis.chunks)
|
|
139
|
+
return;
|
|
140
|
+
if (!this.vectorStoreInitialized) {
|
|
141
|
+
await this.vectorStore.init();
|
|
142
|
+
this.vectorStoreInitialized = true;
|
|
143
|
+
}
|
|
144
|
+
for (const chunk of analysis.chunks) {
|
|
145
|
+
if (!this.databaseManager.getEmbedding(chunk.id)) {
|
|
146
|
+
await this.vectorStore.upsertChunk(chunk);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async refreshSemanticAnalysis() {
|
|
151
|
+
this.databaseManager.db.prepare('DELETE FROM semantic_chunks').run();
|
|
152
|
+
this.databaseManager.db.prepare('DELETE FROM vector_embeddings').run();
|
|
153
|
+
this.semanticCache = null;
|
|
154
|
+
return this.getSemanticAnalysis();
|
|
155
|
+
}
|
|
156
|
+
startMCPServer() {
|
|
157
|
+
if (!this.mcpServer) {
|
|
158
|
+
this.mcpServer = new MCPServer(this);
|
|
159
|
+
this.mcpServerStarted = true;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async listen(port = 3333, host = 'localhost') {
|
|
163
|
+
const server = createServer((req, res) => {
|
|
164
|
+
const url = parse(req.url || '/', true);
|
|
165
|
+
// Serve static files from web/dist
|
|
166
|
+
if (!url.pathname?.startsWith('/api/')) {
|
|
167
|
+
return this.handleStaticFile(req, res, url);
|
|
168
|
+
}
|
|
169
|
+
// Route API requests
|
|
170
|
+
this.apiRouter.handleRequest(req, res, url);
|
|
171
|
+
});
|
|
172
|
+
this.webSocketManager.initialize(server);
|
|
173
|
+
return new Promise((resolve) => {
|
|
174
|
+
server.listen(port, host, () => {
|
|
175
|
+
console.log(`🚀 cntx-ui server running at http://${host}:${port}`);
|
|
176
|
+
resolve(server);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
handleStaticFile(req, res, url) {
|
|
181
|
+
const webDir = join(__dirname, 'web/dist');
|
|
182
|
+
let filePath = join(webDir, url.pathname === '/' ? 'index.html' : url.pathname);
|
|
183
|
+
if (!existsSync(filePath)) {
|
|
184
|
+
filePath = join(webDir, 'index.html');
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
const content = readFileSync(filePath);
|
|
188
|
+
const ext = extname(filePath).toLowerCase();
|
|
189
|
+
const contentType = this.getContentType(ext);
|
|
190
|
+
res.writeHead(200, { 'Content-Type': contentType });
|
|
191
|
+
res.end(content);
|
|
192
|
+
}
|
|
193
|
+
catch (e) {
|
|
194
|
+
res.writeHead(404);
|
|
195
|
+
res.end('Not Found');
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
getContentType(ext) {
|
|
199
|
+
const types = {
|
|
200
|
+
'.html': 'text/html',
|
|
201
|
+
'.js': 'application/javascript',
|
|
202
|
+
'.css': 'text/css',
|
|
203
|
+
'.json': 'application/json',
|
|
204
|
+
'.png': 'image/png',
|
|
205
|
+
'.jpg': 'image/jpeg',
|
|
206
|
+
'.svg': 'image/svg+xml'
|
|
207
|
+
};
|
|
208
|
+
return types[ext] || 'text/plain';
|
|
209
|
+
}
|
|
210
|
+
// Activity Manager Mock
|
|
211
|
+
async loadActivities() {
|
|
212
|
+
return [];
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
export async function startServer(options = {}) {
|
|
216
|
+
const server = new CntxServer(options.cwd, options);
|
|
217
|
+
await server.init(options);
|
|
218
|
+
if (options.withMcp !== false)
|
|
219
|
+
server.startMCPServer();
|
|
220
|
+
return await server.listen(options.port, options.host);
|
|
221
|
+
}
|
|
222
|
+
// Initialize project configuration
|
|
223
|
+
export async function initConfig(cwd = process.cwd()) {
|
|
224
|
+
const server = new CntxServer(cwd);
|
|
225
|
+
// 1. Initialize directory structure
|
|
226
|
+
if (!existsSync(server.CNTX_DIR)) {
|
|
227
|
+
mkdirSync(server.CNTX_DIR, { recursive: true });
|
|
228
|
+
console.log('📁 Created .cntx directory');
|
|
229
|
+
}
|
|
230
|
+
// 2. Create .mcp.json for Claude Code discovery
|
|
231
|
+
const mcpConfigPath = join(cwd, '.mcp.json');
|
|
232
|
+
const mcpConfig = {
|
|
233
|
+
mcpServers: {
|
|
234
|
+
"cntx-ui": {
|
|
235
|
+
command: "cntx-ui",
|
|
236
|
+
args: ["mcp"],
|
|
237
|
+
cwd: "."
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), 'utf8');
|
|
242
|
+
console.log('📄 Created .mcp.json for agent auto-discovery');
|
|
243
|
+
// 3. Initialize basic configuration with better defaults and auto-suggestions
|
|
244
|
+
server.configManager.loadConfig();
|
|
245
|
+
const suggestedBundles = {
|
|
246
|
+
master: ['**/*']
|
|
247
|
+
};
|
|
248
|
+
// Directory-based auto-suggestions
|
|
249
|
+
const commonDirs = [
|
|
250
|
+
{ dir: 'src/components', name: 'ui-components' },
|
|
251
|
+
{ dir: 'src/services', name: 'services' },
|
|
252
|
+
{ dir: 'src/lib', name: 'libraries' },
|
|
253
|
+
{ dir: 'src/hooks', name: 'react-hooks' },
|
|
254
|
+
{ dir: 'server', name: 'backend-api' },
|
|
255
|
+
{ dir: 'tests', name: 'test-suite' }
|
|
256
|
+
];
|
|
257
|
+
commonDirs.forEach(d => {
|
|
258
|
+
if (existsSync(join(cwd, d.dir))) {
|
|
259
|
+
suggestedBundles[d.name] = [`${d.dir}/**`];
|
|
260
|
+
console.log(`💡 Suggested bundle: ${d.name} (${d.dir}/**)`);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
server.configManager.saveConfig({
|
|
264
|
+
bundles: suggestedBundles
|
|
265
|
+
});
|
|
266
|
+
// 4. Create robust default .cntxignore
|
|
267
|
+
const ignorePath = join(cwd, '.cntxignore');
|
|
268
|
+
if (!existsSync(ignorePath)) {
|
|
269
|
+
const defaultIgnore = `# Binary files
|
|
270
|
+
*.db
|
|
271
|
+
*.db-journal
|
|
272
|
+
*.png
|
|
273
|
+
*.jpg
|
|
274
|
+
*.jpeg
|
|
275
|
+
*.ico
|
|
276
|
+
*.icns
|
|
277
|
+
*.gif
|
|
278
|
+
*.zip
|
|
279
|
+
*.tar.gz
|
|
280
|
+
|
|
281
|
+
# Generated files
|
|
282
|
+
**/gen/**
|
|
283
|
+
**/dist/**
|
|
284
|
+
**/build/**
|
|
285
|
+
**/node_modules/**
|
|
286
|
+
**/.next/**
|
|
287
|
+
**/.cache/**
|
|
288
|
+
|
|
289
|
+
# cntx-ui internals
|
|
290
|
+
.cntx/**
|
|
291
|
+
.mcp.json
|
|
292
|
+
`;
|
|
293
|
+
writeFileSync(ignorePath, defaultIgnore, 'utf8');
|
|
294
|
+
console.log('📄 Created .cntxignore with smart defaults');
|
|
295
|
+
}
|
|
296
|
+
console.log('⚙️ Basic configuration initialized');
|
|
297
|
+
const templateDir = join(__dirname, 'templates');
|
|
298
|
+
// Copy agent configuration files
|
|
299
|
+
const agentFiles = [
|
|
300
|
+
'agent-config.yaml',
|
|
301
|
+
'agent-instructions.md'
|
|
302
|
+
];
|
|
303
|
+
for (const file of agentFiles) {
|
|
304
|
+
const sourcePath = join(templateDir, file);
|
|
305
|
+
const destPath = join(server.CNTX_DIR, file);
|
|
306
|
+
if (existsSync(sourcePath) && !existsSync(destPath)) {
|
|
307
|
+
copyFileSync(sourcePath, destPath);
|
|
308
|
+
console.log(`📄 Created ${file}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// Copy agent-rules directory structure
|
|
312
|
+
const agentRulesSource = join(templateDir, 'agent-rules');
|
|
313
|
+
const agentRulesDest = join(server.CNTX_DIR, 'agent-rules');
|
|
314
|
+
if (existsSync(agentRulesSource) && !existsSync(agentRulesDest)) {
|
|
315
|
+
cpSync(agentRulesSource, agentRulesDest, { recursive: true });
|
|
316
|
+
console.log('📁 Created agent-rules directory with templates');
|
|
317
|
+
}
|
|
318
|
+
// Copy activities framework
|
|
319
|
+
const activitiesDir = join(server.CNTX_DIR, 'activities');
|
|
320
|
+
if (!existsSync(activitiesDir)) {
|
|
321
|
+
mkdirSync(activitiesDir, { recursive: true });
|
|
322
|
+
}
|
|
323
|
+
// Copy activities README
|
|
324
|
+
const activitiesReadmeSource = join(templateDir, 'activities', 'README.md');
|
|
325
|
+
const activitiesReadmeDest = join(activitiesDir, 'README.md');
|
|
326
|
+
if (existsSync(activitiesReadmeSource) && !existsSync(activitiesReadmeDest)) {
|
|
327
|
+
copyFileSync(activitiesReadmeSource, activitiesReadmeDest);
|
|
328
|
+
console.log('📄 Created activities/README.md');
|
|
329
|
+
}
|
|
330
|
+
// Copy activities lib directory (MDC templates)
|
|
331
|
+
const activitiesLibSource = join(templateDir, 'activities', 'lib');
|
|
332
|
+
const activitiesLibDest = join(activitiesDir, 'lib');
|
|
333
|
+
if (existsSync(activitiesLibSource) && !existsSync(activitiesLibDest)) {
|
|
334
|
+
cpSync(activitiesLibSource, activitiesLibDest, { recursive: true });
|
|
335
|
+
console.log('📁 Created activities/lib with MDC templates');
|
|
336
|
+
}
|
|
337
|
+
// Copy activities.json from templates
|
|
338
|
+
const activitiesJsonPath = join(activitiesDir, 'activities.json');
|
|
339
|
+
const templateActivitiesJsonPath = join(templateDir, 'activities', 'activities.json');
|
|
340
|
+
if (!existsSync(activitiesJsonPath) && existsSync(templateActivitiesJsonPath)) {
|
|
341
|
+
copyFileSync(templateActivitiesJsonPath, activitiesJsonPath);
|
|
342
|
+
console.log('📄 Created activities.json with bundle example activity');
|
|
343
|
+
}
|
|
344
|
+
// Copy example activity from templates
|
|
345
|
+
const activitiesDestDir = join(activitiesDir, 'activities');
|
|
346
|
+
const templateActivitiesDir = join(templateDir, 'activities', 'activities');
|
|
347
|
+
if (!existsSync(activitiesDestDir) && existsSync(templateActivitiesDir)) {
|
|
348
|
+
cpSync(templateActivitiesDir, activitiesDestDir, { recursive: true });
|
|
349
|
+
console.log('📁 Created example activity with templates');
|
|
350
|
+
}
|
|
351
|
+
return server.initMessages;
|
|
352
|
+
}
|
|
353
|
+
export async function generateBundle(name) {
|
|
354
|
+
const server = new CntxServer(process.cwd());
|
|
355
|
+
await server.init({ skipFileWatcher: true });
|
|
356
|
+
return await server.bundleManager.regenerateBundle(name);
|
|
357
|
+
}
|
|
358
|
+
export async function getStatus() {
|
|
359
|
+
const server = new CntxServer(process.cwd());
|
|
360
|
+
await server.init({ skipFileWatcher: true });
|
|
361
|
+
const bundles = server.bundleManager.getAllBundleInfo();
|
|
362
|
+
const totalFiles = server.fileSystemManager.getAllFiles().length;
|
|
363
|
+
console.log('📊 cntx-ui Status');
|
|
364
|
+
console.log('================');
|
|
365
|
+
console.log(`Total files: ${totalFiles}`);
|
|
366
|
+
console.log(`Bundles: ${bundles.length}`);
|
|
367
|
+
bundles.forEach(bundle => {
|
|
368
|
+
console.log(` • ${bundle.name}: ${bundle.fileCount} files (${Math.round(bundle.size / 1024)}KB)`);
|
|
369
|
+
});
|
|
370
|
+
return {
|
|
371
|
+
totalFiles,
|
|
372
|
+
bundles: bundles.length,
|
|
373
|
+
bundleDetails: bundles
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
export function setupMCP() {
|
|
377
|
+
const configPath = join(homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
378
|
+
const projectPath = process.cwd();
|
|
379
|
+
console.log('🔧 Setting up MCP integration...');
|
|
380
|
+
console.log(`Project: ${projectPath}`);
|
|
381
|
+
console.log(`Claude config: ${configPath}`);
|
|
382
|
+
try {
|
|
383
|
+
let config = {};
|
|
384
|
+
if (existsSync(configPath)) {
|
|
385
|
+
config = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
386
|
+
}
|
|
387
|
+
if (!config.mcpServers) {
|
|
388
|
+
config.mcpServers = {};
|
|
389
|
+
}
|
|
390
|
+
config.mcpServers['cntx-ui'] = {
|
|
391
|
+
command: 'npx',
|
|
392
|
+
args: ['cntx-ui', 'mcp'],
|
|
393
|
+
cwd: projectPath
|
|
394
|
+
};
|
|
395
|
+
// Ensure directory exists
|
|
396
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
397
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
398
|
+
console.log('✅ MCP integration configured');
|
|
399
|
+
console.log('💡 Restart Claude Desktop to apply changes');
|
|
400
|
+
}
|
|
401
|
+
catch (error) {
|
|
402
|
+
console.error('❌ Failed to setup MCP:', error.message);
|
|
403
|
+
console.log('💡 You may need to manually add the configuration to Claude Desktop');
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
// Auto-start server when run directly
|
|
407
|
+
const isMainModule = import.meta.url === `file://${process.argv[1]}`;
|
|
408
|
+
if (isMainModule) {
|
|
409
|
+
console.log('🚀 Starting cntx-ui server...');
|
|
410
|
+
const server = new CntxServer();
|
|
411
|
+
server.init();
|
|
412
|
+
server.listen(3333, 'localhost');
|
|
413
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cntx-ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.0
|
|
4
|
+
"version": "3.1.0",
|
|
5
5
|
"description": "Autonomous Repository Intelligence engine with web UI and MCP server. Unified semantic code understanding, local RAG, and agent working memory.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"repository-intelligence",
|
|
@@ -20,13 +20,12 @@
|
|
|
20
20
|
},
|
|
21
21
|
"author": "whaleen",
|
|
22
22
|
"license": "MIT",
|
|
23
|
+
"main": "dist/server.js",
|
|
23
24
|
"bin": {
|
|
24
|
-
"cntx-ui": "./bin/cntx-ui.js"
|
|
25
|
+
"cntx-ui": "./dist/bin/cntx-ui.js"
|
|
25
26
|
},
|
|
26
27
|
"files": [
|
|
27
|
-
"
|
|
28
|
-
"server.js",
|
|
29
|
-
"lib/",
|
|
28
|
+
"dist/",
|
|
30
29
|
"templates/",
|
|
31
30
|
"web/dist/",
|
|
32
31
|
"README.md",
|
|
@@ -36,12 +35,14 @@
|
|
|
36
35
|
"node": ">=18.0.0"
|
|
37
36
|
},
|
|
38
37
|
"scripts": {
|
|
39
|
-
"dev": "node
|
|
40
|
-
"build": "
|
|
38
|
+
"dev": "ts-node --esm bin/cntx-ui.ts",
|
|
39
|
+
"build:backend": "tsc && chmod +x dist/bin/cntx-ui.js",
|
|
40
|
+
"build:web": "cd web && npm install && npm run build",
|
|
41
|
+
"build": "npm run build:backend && npm run build:web",
|
|
41
42
|
"check:version-sync": "node scripts/check-version-sync.mjs",
|
|
42
43
|
"release:ci": "node scripts/release-from-package.mjs",
|
|
43
44
|
"prepublishOnly": "npm run build",
|
|
44
|
-
"test:local": "npm pack && npm install -g ./cntx-ui-3.
|
|
45
|
+
"test:local": "npm pack && npm install -g ./cntx-ui-3.1.0.tgz"
|
|
45
46
|
},
|
|
46
47
|
"dependencies": {
|
|
47
48
|
"@xenova/transformers": "^2.17.2",
|
|
@@ -52,5 +53,13 @@
|
|
|
52
53
|
"tree-sitter-rust": "^0.21.0",
|
|
53
54
|
"tree-sitter-typescript": "^0.23.2",
|
|
54
55
|
"ws": "^8.13.0"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
59
|
+
"@types/glob": "^8.1.0",
|
|
60
|
+
"@types/node": "^25.3.2",
|
|
61
|
+
"@types/ws": "^8.18.1",
|
|
62
|
+
"ts-node": "^10.9.2",
|
|
63
|
+
"typescript": "^5.9.3"
|
|
55
64
|
}
|
|
56
65
|
}
|
package/bin/cntx-ui-mcp.sh
DELETED
package/bin/cntx-ui.js
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { readFileSync } from 'fs';
|
|
4
|
-
import { dirname, join } from 'path';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
6
|
-
import { autoInitAndStart, startMCPServer, generateBundle, initConfig, getStatus } from '../server.js';
|
|
7
|
-
|
|
8
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
-
const packagePath = join(__dirname, '..', 'package.json');
|
|
10
|
-
const packageJson = JSON.parse(readFileSync(packagePath, 'utf8'));
|
|
11
|
-
|
|
12
|
-
const args = process.argv.slice(2);
|
|
13
|
-
const command = args[0] || 'start';
|
|
14
|
-
const isVerbose = args.includes('--verbose');
|
|
15
|
-
|
|
16
|
-
// Graceful shutdown
|
|
17
|
-
process.on('SIGINT', () => {
|
|
18
|
-
console.log('\n Shutting down cntx-ui...');
|
|
19
|
-
process.exit(0);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
function showHelp() {
|
|
23
|
-
console.log(`cntx-ui v${packageJson.version}
|
|
24
|
-
|
|
25
|
-
${packageJson.description}
|
|
26
|
-
|
|
27
|
-
Usage:
|
|
28
|
-
cntx-ui [command] [options]
|
|
29
|
-
|
|
30
|
-
Commands:
|
|
31
|
-
(default) Auto-init if needed, then start web server
|
|
32
|
-
init Initialize configuration in current directory
|
|
33
|
-
mcp Start MCP server (stdio transport)
|
|
34
|
-
bundle [name] Generate specific bundle (default: master)
|
|
35
|
-
status Show current project status
|
|
36
|
-
|
|
37
|
-
Options:
|
|
38
|
-
--verbose Enable detailed logging
|
|
39
|
-
--version, -v Show version number
|
|
40
|
-
--help, -h Show this help message
|
|
41
|
-
|
|
42
|
-
Examples:
|
|
43
|
-
cntx-ui Start server (auto-inits if needed)
|
|
44
|
-
cntx-ui init Initialize a new project
|
|
45
|
-
cntx-ui mcp Start MCP server on stdio
|
|
46
|
-
cntx-ui bundle api Generate 'api' bundle
|
|
47
|
-
cntx-ui status Show project status
|
|
48
|
-
|
|
49
|
-
MCP Integration:
|
|
50
|
-
Running 'cntx-ui init' creates a .mcp.json file so Claude Code
|
|
51
|
-
can auto-discover the MCP server. Run 'cntx-ui mcp' for stdio mode.
|
|
52
|
-
|
|
53
|
-
Repository: ${packageJson.repository.url}
|
|
54
|
-
Author: ${packageJson.author}
|
|
55
|
-
License: ${packageJson.license}`);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function showVersion() {
|
|
59
|
-
console.log(`cntx-ui v${packageJson.version}`);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async function main() {
|
|
63
|
-
// Handle version flags
|
|
64
|
-
if (args.includes('--version') || args.includes('-v')) {
|
|
65
|
-
return showVersion();
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Handle help flags
|
|
69
|
-
if (args.includes('--help') || args.includes('-h') || command === 'help') {
|
|
70
|
-
return showHelp();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
switch (command) {
|
|
75
|
-
case 'start':
|
|
76
|
-
case 'watch':
|
|
77
|
-
case 'w':
|
|
78
|
-
const port = parseInt(args[1]) || 3333;
|
|
79
|
-
await autoInitAndStart({ port, verbose: isVerbose });
|
|
80
|
-
break;
|
|
81
|
-
|
|
82
|
-
case 'mcp':
|
|
83
|
-
// MCP server mode - runs on stdio
|
|
84
|
-
await startMCPServer({ cwd: process.cwd(), verbose: isVerbose });
|
|
85
|
-
break;
|
|
86
|
-
|
|
87
|
-
case 'bundle':
|
|
88
|
-
case 'b':
|
|
89
|
-
const bundleName = args[1] || 'master';
|
|
90
|
-
try {
|
|
91
|
-
await generateBundle(bundleName);
|
|
92
|
-
console.log(`Bundle '${bundleName}' generated successfully`);
|
|
93
|
-
} catch (error) {
|
|
94
|
-
console.error(`Failed to generate bundle '${bundleName}': ${error.message}`);
|
|
95
|
-
process.exit(1);
|
|
96
|
-
}
|
|
97
|
-
break;
|
|
98
|
-
|
|
99
|
-
case 'init':
|
|
100
|
-
case 'i':
|
|
101
|
-
await initConfig();
|
|
102
|
-
break;
|
|
103
|
-
|
|
104
|
-
case 'status':
|
|
105
|
-
case 's':
|
|
106
|
-
await getStatus();
|
|
107
|
-
break;
|
|
108
|
-
|
|
109
|
-
default:
|
|
110
|
-
console.error(`Unknown command: ${command}`);
|
|
111
|
-
console.log('Run "cntx-ui --help" for usage information.');
|
|
112
|
-
process.exit(1);
|
|
113
|
-
}
|
|
114
|
-
} catch (error) {
|
|
115
|
-
console.error(`Error: ${error.message}`);
|
|
116
|
-
if (isVerbose) {
|
|
117
|
-
console.error(error.stack);
|
|
118
|
-
}
|
|
119
|
-
process.exit(1);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
main().catch(console.error);
|