cntx-ui 3.0.7 → 3.0.9

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.
Files changed (36) hide show
  1. package/dist/bin/cntx-ui.js +70 -0
  2. package/dist/lib/agent-runtime.js +269 -0
  3. package/dist/lib/agent-tools.js +162 -0
  4. package/dist/lib/api-router.js +387 -0
  5. package/dist/lib/bundle-manager.js +236 -0
  6. package/dist/lib/configuration-manager.js +230 -0
  7. package/dist/lib/database-manager.js +277 -0
  8. package/dist/lib/file-system-manager.js +305 -0
  9. package/dist/lib/function-level-chunker.js +144 -0
  10. package/dist/lib/heuristics-manager.js +491 -0
  11. package/dist/lib/mcp-server.js +159 -0
  12. package/dist/lib/mcp-transport.js +10 -0
  13. package/dist/lib/semantic-splitter.js +335 -0
  14. package/dist/lib/simple-vector-store.js +98 -0
  15. package/dist/lib/treesitter-semantic-chunker.js +277 -0
  16. package/dist/lib/websocket-manager.js +268 -0
  17. package/dist/server.js +225 -0
  18. package/package.json +18 -8
  19. package/bin/cntx-ui-mcp.sh +0 -3
  20. package/bin/cntx-ui.js +0 -123
  21. package/lib/agent-runtime.js +0 -371
  22. package/lib/agent-tools.js +0 -370
  23. package/lib/api-router.js +0 -1026
  24. package/lib/bundle-manager.js +0 -326
  25. package/lib/configuration-manager.js +0 -760
  26. package/lib/database-manager.js +0 -397
  27. package/lib/file-system-manager.js +0 -489
  28. package/lib/function-level-chunker.js +0 -406
  29. package/lib/heuristics-manager.js +0 -529
  30. package/lib/mcp-server.js +0 -1380
  31. package/lib/mcp-transport.js +0 -97
  32. package/lib/semantic-splitter.js +0 -304
  33. package/lib/simple-vector-store.js +0 -108
  34. package/lib/treesitter-semantic-chunker.js +0 -1485
  35. package/lib/websocket-manager.js +0 -470
  36. package/server.js +0 -687
package/dist/server.js ADDED
@@ -0,0 +1,225 @@
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 } from 'fs';
9
+ // Import our modular components
10
+ import ConfigurationManager from './lib/configuration-manager.js';
11
+ import FileSystemManager from './lib/file-system-manager.js';
12
+ import BundleManager from './lib/bundle-manager.js';
13
+ import APIRouter from './lib/api-router.js';
14
+ import WebSocketManager from './lib/websocket-manager.js';
15
+ // Import existing lib modules
16
+ import SemanticSplitter from './lib/semantic-splitter.js';
17
+ import SimpleVectorStore from './lib/simple-vector-store.js';
18
+ import { MCPServer } from './lib/mcp-server.js';
19
+ import AgentRuntime from './lib/agent-runtime.js';
20
+ const __dirname = dirname(fileURLToPath(import.meta.url));
21
+ export class CntxServer {
22
+ CWD;
23
+ CNTX_DIR;
24
+ verbose;
25
+ mcpServerStarted;
26
+ mcpServer;
27
+ initMessages;
28
+ configManager;
29
+ databaseManager;
30
+ fileSystemManager;
31
+ bundleManager;
32
+ webSocketManager;
33
+ apiRouter;
34
+ semanticSplitter;
35
+ vectorStore;
36
+ agentRuntime;
37
+ semanticCache;
38
+ lastSemanticAnalysis;
39
+ vectorStoreInitialized;
40
+ semanticAnalysisManager;
41
+ activityManager;
42
+ constructor(cwd = process.cwd(), options = {}) {
43
+ this.CWD = cwd;
44
+ this.CNTX_DIR = join(cwd, '.cntx');
45
+ this.verbose = options.verbose || false;
46
+ this.mcpServerStarted = false;
47
+ this.mcpServer = null;
48
+ this.initMessages = [];
49
+ // Ensure directory exists
50
+ if (!existsSync(this.CNTX_DIR))
51
+ mkdirSync(this.CNTX_DIR, { recursive: true });
52
+ // Initialize modular components
53
+ this.configManager = new ConfigurationManager(cwd, { verbose: this.verbose });
54
+ this.databaseManager = this.configManager.dbManager;
55
+ this.fileSystemManager = new FileSystemManager(cwd, { verbose: this.verbose });
56
+ this.bundleManager = new BundleManager(this.configManager, this.fileSystemManager, this.verbose);
57
+ this.webSocketManager = new WebSocketManager(this.bundleManager, this.configManager, { verbose: this.verbose });
58
+ // AI Components
59
+ this.semanticSplitter = new SemanticSplitter({
60
+ maxChunkSize: 2000,
61
+ includeContext: true,
62
+ minFunctionSize: 50
63
+ });
64
+ this.vectorStore = new SimpleVectorStore(this.databaseManager, {
65
+ modelName: 'Xenova/all-MiniLM-L6-v2'
66
+ });
67
+ this.semanticCache = null;
68
+ this.lastSemanticAnalysis = null;
69
+ this.vectorStoreInitialized = false;
70
+ // Initialize Agent Runtime
71
+ this.agentRuntime = new AgentRuntime(this);
72
+ this.semanticAnalysisManager = this; // Self as manager
73
+ this.activityManager = this; // Simple mock for now
74
+ // Initialize API router
75
+ this.apiRouter = new APIRouter(this, this.configManager, this.bundleManager, this.fileSystemManager, this.semanticAnalysisManager, this.vectorStore, this.activityManager);
76
+ // Cross-module linkage
77
+ this.bundleManager.fileSystemManager = this.fileSystemManager;
78
+ this.bundleManager.webSocketManager = this.webSocketManager;
79
+ }
80
+ async init(options = {}) {
81
+ const { skipFileWatcher = false, skipBundleGeneration = false } = options;
82
+ // Load configs
83
+ this.configManager.loadConfig();
84
+ this.configManager.loadHiddenFilesConfig();
85
+ this.configManager.loadIgnorePatterns();
86
+ this.configManager.loadBundleStates();
87
+ if (!skipFileWatcher) {
88
+ this.startWatching();
89
+ // Trigger semantic analysis
90
+ if (!this.semanticCache) {
91
+ this.getSemanticAnalysis().catch(err => console.error('Initial semantic analysis failed:', err.message));
92
+ }
93
+ if (!skipBundleGeneration) {
94
+ await this.bundleManager.generateAllBundles();
95
+ }
96
+ }
97
+ // Load reasoning/manifest
98
+ await this.agentRuntime.generateAgentManifest();
99
+ }
100
+ startWatching() {
101
+ this.fileSystemManager.startWatching((eventType, filename) => {
102
+ this.bundleManager.markBundlesChanged(filename);
103
+ this.webSocketManager.onFileChanged(filename, eventType);
104
+ });
105
+ }
106
+ async getSemanticAnalysis() {
107
+ // Try SQLite first
108
+ try {
109
+ const dbChunks = this.databaseManager.db.prepare('SELECT * FROM semantic_chunks').all();
110
+ if (dbChunks.length > 0) {
111
+ if (!this.semanticCache) {
112
+ this.semanticCache = {
113
+ chunks: dbChunks.map(row => this.databaseManager.mapChunkRow(row)),
114
+ summary: { totalChunks: dbChunks.length }
115
+ };
116
+ }
117
+ return this.semanticCache;
118
+ }
119
+ }
120
+ catch (e) { }
121
+ // Fresh analysis
122
+ const files = this.fileSystemManager.getAllFiles().map(f => this.fileSystemManager.relativePath(f))
123
+ .filter(f => ['.js', '.jsx', '.ts', '.tsx', '.rs'].includes(extname(f).toLowerCase()));
124
+ let bundleConfig = null;
125
+ if (existsSync(this.configManager.CONFIG_FILE)) {
126
+ bundleConfig = JSON.parse(readFileSync(this.configManager.CONFIG_FILE, 'utf8'));
127
+ }
128
+ this.semanticCache = await this.semanticSplitter.extractSemanticChunks(this.CWD, files, bundleConfig);
129
+ this.lastSemanticAnalysis = Date.now();
130
+ if (this.semanticCache.chunks.length > 0) {
131
+ this.databaseManager.saveChunks(this.semanticCache.chunks);
132
+ }
133
+ this.enhanceSemanticChunksIfNeeded(this.semanticCache);
134
+ return this.semanticCache;
135
+ }
136
+ async enhanceSemanticChunksIfNeeded(analysis) {
137
+ if (!analysis || !analysis.chunks)
138
+ return;
139
+ if (!this.vectorStoreInitialized) {
140
+ await this.vectorStore.init();
141
+ this.vectorStoreInitialized = true;
142
+ }
143
+ for (const chunk of analysis.chunks) {
144
+ if (!this.databaseManager.getEmbedding(chunk.id)) {
145
+ await this.vectorStore.upsertChunk(chunk);
146
+ }
147
+ }
148
+ }
149
+ async refreshSemanticAnalysis() {
150
+ this.databaseManager.db.prepare('DELETE FROM semantic_chunks').run();
151
+ this.databaseManager.db.prepare('DELETE FROM vector_embeddings').run();
152
+ this.semanticCache = null;
153
+ return this.getSemanticAnalysis();
154
+ }
155
+ startMCPServer() {
156
+ if (!this.mcpServer) {
157
+ this.mcpServer = new MCPServer(this);
158
+ this.mcpServerStarted = true;
159
+ }
160
+ }
161
+ async listen(port = 3333, host = 'localhost') {
162
+ const server = createServer((req, res) => {
163
+ const url = parse(req.url || '/', true);
164
+ // Serve static files from web/dist
165
+ if (!url.pathname?.startsWith('/api/')) {
166
+ return this.handleStaticFile(req, res, url);
167
+ }
168
+ // Route API requests
169
+ this.apiRouter.handleRequest(req, res, url);
170
+ });
171
+ this.webSocketManager.initialize(server);
172
+ return new Promise((resolve) => {
173
+ server.listen(port, host, () => {
174
+ console.log(`🚀 cntx-ui server running at http://${host}:${port}`);
175
+ resolve(server);
176
+ });
177
+ });
178
+ }
179
+ handleStaticFile(req, res, url) {
180
+ const webDir = join(__dirname, 'web/dist');
181
+ let filePath = join(webDir, url.pathname === '/' ? 'index.html' : url.pathname);
182
+ if (!existsSync(filePath)) {
183
+ filePath = join(webDir, 'index.html');
184
+ }
185
+ try {
186
+ const content = readFileSync(filePath);
187
+ const ext = extname(filePath).toLowerCase();
188
+ const contentType = this.getContentType(ext);
189
+ res.writeHead(200, { 'Content-Type': contentType });
190
+ res.end(content);
191
+ }
192
+ catch (e) {
193
+ res.writeHead(404);
194
+ res.end('Not Found');
195
+ }
196
+ }
197
+ getContentType(ext) {
198
+ const types = {
199
+ '.html': 'text/html',
200
+ '.js': 'application/javascript',
201
+ '.css': 'text/css',
202
+ '.json': 'application/json',
203
+ '.png': 'image/png',
204
+ '.jpg': 'image/jpeg',
205
+ '.svg': 'image/svg+xml'
206
+ };
207
+ return types[ext] || 'text/plain';
208
+ }
209
+ // Activity Manager Mock
210
+ async loadActivities() {
211
+ return [];
212
+ }
213
+ }
214
+ export async function startServer(options = {}) {
215
+ const server = new CntxServer(options.cwd, options);
216
+ await server.init(options);
217
+ if (options.withMcp !== false)
218
+ server.startMCPServer();
219
+ return await server.listen(options.port, options.host);
220
+ }
221
+ export async function initConfig(cwd = process.cwd()) {
222
+ const server = new CntxServer(cwd);
223
+ // Implementation matches previous init logic
224
+ return [];
225
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cntx-ui",
3
3
  "type": "module",
4
- "version": "3.0.7",
4
+ "version": "3.0.9",
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
- "bin/",
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 server.js",
40
- "build": "cd web && npm install && npm run 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.0.0.tgz"
45
+ "test:local": "npm pack && npm install -g ./cntx-ui-3.0.8.tgz"
45
46
  },
46
47
  "dependencies": {
47
48
  "@xenova/transformers": "^2.17.2",
@@ -49,7 +50,16 @@
49
50
  "glob": "^9.0.0",
50
51
  "tree-sitter": "^0.21.1",
51
52
  "tree-sitter-javascript": "^0.23.1",
53
+ "tree-sitter-rust": "^0.21.0",
52
54
  "tree-sitter-typescript": "^0.23.2",
53
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"
54
64
  }
55
65
  }
@@ -1,3 +0,0 @@
1
- #!/bin/bash
2
- # Wrapper script to run cntx-ui MCP server in current directory
3
- cd "$(pwd)" && npx cntx-ui mcp
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);