cntx-ui 2.0.13 ā 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/README.md +51 -339
- package/VISION.md +110 -0
- package/bin/cntx-ui-mcp.sh +3 -0
- package/bin/cntx-ui.js +138 -55
- package/lib/agent-runtime.js +301 -0
- package/lib/agent-tools.js +370 -0
- package/lib/api-router.js +1161 -0
- package/lib/bundle-manager.js +236 -0
- package/lib/configuration-manager.js +760 -0
- package/lib/database-manager.js +397 -0
- package/lib/file-system-manager.js +489 -0
- package/lib/heuristics-manager.js +527 -0
- package/lib/mcp-server.js +1125 -2
- package/lib/semantic-splitter.js +225 -491
- package/lib/simple-vector-store.js +98 -0
- package/lib/websocket-manager.js +470 -0
- package/package.json +19 -25
- package/server.js +742 -1935
- package/templates/TOOLS.md +41 -0
- package/templates/activities/README.md +67 -0
- package/templates/activities/activities/create-project-bundles/README.md +84 -0
- package/templates/activities/activities/create-project-bundles/notes.md +98 -0
- package/templates/activities/activities/create-project-bundles/progress.md +63 -0
- package/templates/activities/activities/create-project-bundles/tasks.md +39 -0
- package/templates/activities/activities.json +219 -0
- package/templates/activities/lib/.markdownlint.jsonc +18 -0
- package/templates/activities/lib/create-activity.mdc +63 -0
- package/templates/activities/lib/generate-tasks.mdc +64 -0
- package/templates/activities/lib/process-task-list.mdc +52 -0
- package/templates/agent-config.yaml +65 -0
- package/templates/agent-instructions.md +234 -0
- package/templates/agent-rules/capabilities/activities-system.md +147 -0
- package/templates/agent-rules/capabilities/bundle-system.md +131 -0
- package/templates/agent-rules/capabilities/vector-search.md +135 -0
- package/templates/agent-rules/core/codebase-navigation.md +91 -0
- package/templates/agent-rules/core/performance-hierarchy.md +48 -0
- package/templates/agent-rules/core/response-formatting.md +120 -0
- package/templates/agent-rules/project-specific/architecture.md +145 -0
- package/templates/config.json +76 -0
- package/templates/hidden-files.json +14 -0
- package/web/dist/assets/index-B2OdTzzI.css +1 -0
- package/web/dist/assets/index-D0tBsKiR.js +2016 -0
- package/web/dist/cntx-ui.svg +18 -0
- package/web/dist/index.html +25 -8
- package/lib/semantic-integration.js +0 -441
- package/mcp-config-example.json +0 -9
- package/web/dist/assets/index-Ci1Q-YrQ.js +0 -611
- package/web/dist/assets/index-IUp4q_fr.css +0 -1
- package/web/dist/vite.svg +0 -21
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!-- Generated by Pixelmator Pro 3.4.3 -->
|
|
3
|
+
<svg width="31" height="32" viewBox="0 0 31 32" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
+
<g id="Group-copy">
|
|
5
|
+
<path id="Path" fill="none" stroke="#828080" stroke-linecap="round" stroke-linejoin="round" d="M 2.431387 18.088001 C 1.545252 18.620388 1.002266 19.57761 1 20.611374 L 1 25.392504 C 1.002266 26.426268 1.545252 27.383492 2.431387 27.915876 L 6.858358 30.572058 C 7.793726 31.134027 8.962845 31.134027 9.898211 30.572058 L 15.756571 27.059996 L 15.756571 18.943882 L 8.378285 14.516911 L 2.431387 18.088001 Z"/>
|
|
6
|
+
<path id="path1" fill="none" stroke="#828080" stroke-linecap="round" stroke-linejoin="round" d="M 8.378285 23.370853 L 1.383671 19.16523"/>
|
|
7
|
+
<path id="path2" fill="none" stroke="#828080" stroke-linecap="round" stroke-linejoin="round" d="M 8.378285 23.370853 L 15.756571 18.943882"/>
|
|
8
|
+
<path id="path3" fill="none" stroke="#828080" stroke-linecap="round" stroke-linejoin="round" d="M 8.378285 23.370853 L 8.378285 31"/>
|
|
9
|
+
<path id="path4" fill="none" stroke="#828080" stroke-linecap="round" stroke-linejoin="round" d="M 15.756571 18.943882 L 15.756571 27.059996 L 21.614929 30.572058 C 22.550297 31.134027 23.719416 31.134027 24.654783 30.572058 L 29.081755 27.915876 C 29.96789 27.383492 30.510876 26.426268 30.513142 25.392504 L 30.513142 20.611374 C 30.510876 19.57761 29.96789 18.620388 29.081755 18.088001 L 23.134855 14.516911 L 15.756571 18.943882 Z"/>
|
|
10
|
+
<path id="path5" fill="none" stroke="#828080" stroke-linecap="round" stroke-linejoin="round" d="M 23.134855 23.370853 L 15.756571 18.943882"/>
|
|
11
|
+
<path id="path6" fill="none" stroke="#828080" stroke-linecap="round" stroke-linejoin="round" d="M 23.134855 23.370853 L 30.129469 19.16523"/>
|
|
12
|
+
<path id="path7" fill="none" stroke="#828080" stroke-linecap="round" stroke-linejoin="round" d="M 23.134855 23.370853 L 23.134855 31"/>
|
|
13
|
+
<path id="path8" fill="none" stroke="#828080" stroke-linecap="round" stroke-linejoin="round" d="M 9.809672 5.544916 C 8.923537 6.077305 8.380551 7.034525 8.378285 8.068291 L 8.378285 14.516911 L 15.756571 18.943882 L 23.134855 14.516911 L 23.134855 8.068291 C 23.132589 7.034525 22.589605 6.077305 21.70347 5.544916 L 17.276497 2.888731 C 16.341131 2.326765 15.17201 2.326765 14.236644 2.888731 L 9.809672 5.544916 Z"/>
|
|
14
|
+
<path id="path9" fill="none" stroke="#828080" stroke-linecap="round" stroke-linejoin="round" d="M 15.756571 10.827768 L 8.761956 6.622145"/>
|
|
15
|
+
<path id="path10" fill="none" stroke="#828080" stroke-linecap="round" stroke-linejoin="round" d="M 15.756571 10.827768 L 22.751184 6.622145"/>
|
|
16
|
+
<path id="path11" fill="none" stroke="#828080" stroke-linecap="round" stroke-linejoin="round" d="M 15.756571 18.943882 L 15.756571 10.827768"/>
|
|
17
|
+
</g>
|
|
18
|
+
</svg>
|
package/web/dist/index.html
CHANGED
|
@@ -1,15 +1,32 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<link
|
|
6
|
-
|
|
5
|
+
<link
|
|
6
|
+
rel="icon"
|
|
7
|
+
type="image/svg+xml"
|
|
8
|
+
href="./cntx-ui.svg"
|
|
9
|
+
/>
|
|
10
|
+
<meta
|
|
11
|
+
name="viewport"
|
|
12
|
+
content="width=device-width, initial-scale=1.0"
|
|
13
|
+
/>
|
|
7
14
|
<title>cntx-ui</title>
|
|
8
|
-
<link
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<link
|
|
15
|
+
<link
|
|
16
|
+
rel="preconnect"
|
|
17
|
+
href="https://fonts.googleapis.com"
|
|
18
|
+
/>
|
|
19
|
+
<link
|
|
20
|
+
rel="preconnect"
|
|
21
|
+
href="https://fonts.gstatic.com"
|
|
22
|
+
crossorigin
|
|
23
|
+
/>
|
|
24
|
+
<link
|
|
25
|
+
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap"
|
|
26
|
+
rel="stylesheet"
|
|
27
|
+
/>
|
|
28
|
+
<script type="module" crossorigin src="./assets/index-D0tBsKiR.js"></script>
|
|
29
|
+
<link rel="stylesheet" crossorigin href="./assets/index-B2OdTzzI.css">
|
|
13
30
|
</head>
|
|
14
31
|
<body>
|
|
15
32
|
<div id="root"></div>
|
|
@@ -1,441 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Semantic Chunking Integration for cntx-ui Server
|
|
3
|
-
* Extends the existing server with semantic analysis capabilities
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import SemanticChunker from './semantic-chunker.js'
|
|
7
|
-
import { readFileSync, writeFileSync } from 'fs'
|
|
8
|
-
import { join } from 'path'
|
|
9
|
-
|
|
10
|
-
class SemanticIntegration {
|
|
11
|
-
constructor(projectPath = process.cwd()) {
|
|
12
|
-
this.projectPath = projectPath
|
|
13
|
-
this.chunker = new SemanticChunker({
|
|
14
|
-
includeImports: true,
|
|
15
|
-
includeExports: true,
|
|
16
|
-
detectComponentTypes: true,
|
|
17
|
-
groupRelatedFiles: true,
|
|
18
|
-
minChunkSize: 100,
|
|
19
|
-
maxChunkSize: 10000
|
|
20
|
-
})
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Analyze project and generate semantic bundle suggestions
|
|
25
|
-
*/
|
|
26
|
-
async generateSemanticBundles() {
|
|
27
|
-
try {
|
|
28
|
-
console.log('š Analyzing project for semantic chunking...')
|
|
29
|
-
|
|
30
|
-
// Analyze different file types separately
|
|
31
|
-
const analyses = await Promise.all([
|
|
32
|
-
this.chunker.analyzeProject(this.projectPath, ['web/src/components/**/*.{tsx,ts}']),
|
|
33
|
-
this.chunker.analyzeProject(this.projectPath, ['web/src/hooks/**/*.{tsx,ts}']),
|
|
34
|
-
this.chunker.analyzeProject(this.projectPath, ['web/src/lib/**/*.{tsx,ts}']),
|
|
35
|
-
this.chunker.analyzeProject(this.projectPath, ['web/src/utils/**/*.{tsx,ts}']),
|
|
36
|
-
this.chunker.analyzeProject(this.projectPath, ['lib/**/*.js']),
|
|
37
|
-
])
|
|
38
|
-
|
|
39
|
-
const [componentsAnalysis, hooksAnalysis, libAnalysis, utilsAnalysis, serverAnalysis] = analyses
|
|
40
|
-
|
|
41
|
-
// Generate bundle suggestions
|
|
42
|
-
const suggestions = this.generateBundleSuggestions([
|
|
43
|
-
{ name: 'components', analysis: componentsAnalysis },
|
|
44
|
-
{ name: 'hooks', analysis: hooksAnalysis },
|
|
45
|
-
{ name: 'lib', analysis: libAnalysis },
|
|
46
|
-
{ name: 'utils', analysis: utilsAnalysis },
|
|
47
|
-
{ name: 'server', analysis: serverAnalysis }
|
|
48
|
-
])
|
|
49
|
-
|
|
50
|
-
console.log('ā
Semantic analysis complete!')
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
timestamp: new Date().toISOString(),
|
|
54
|
-
projectPath: this.projectPath,
|
|
55
|
-
suggestions,
|
|
56
|
-
analyses: {
|
|
57
|
-
components: this.chunker.formatResults(componentsAnalysis),
|
|
58
|
-
hooks: this.chunker.formatResults(hooksAnalysis),
|
|
59
|
-
lib: this.chunker.formatResults(libAnalysis),
|
|
60
|
-
utils: this.chunker.formatResults(utilsAnalysis),
|
|
61
|
-
server: this.chunker.formatResults(serverAnalysis)
|
|
62
|
-
},
|
|
63
|
-
summary: this.generateOverallSummary(analyses)
|
|
64
|
-
}
|
|
65
|
-
} catch (error) {
|
|
66
|
-
console.error('ā Semantic analysis failed:', error.message)
|
|
67
|
-
throw error
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Generate bundle configuration suggestions based on semantic analysis
|
|
73
|
-
*/
|
|
74
|
-
generateBundleSuggestions(namedAnalyses) {
|
|
75
|
-
const suggestions = {
|
|
76
|
-
recommended: {},
|
|
77
|
-
alternative: {},
|
|
78
|
-
notes: []
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
for (const { name, analysis } of namedAnalyses) {
|
|
82
|
-
if (analysis.chunks.length === 0) continue
|
|
83
|
-
|
|
84
|
-
// Recommended: Group by semantic purpose
|
|
85
|
-
const purposeGroups = this.groupChunksByPurpose(analysis.chunks)
|
|
86
|
-
|
|
87
|
-
for (const [purpose, chunks] of Object.entries(purposeGroups)) {
|
|
88
|
-
const bundleName = `${name}-${purpose}`
|
|
89
|
-
const patterns = this.generatePatternsForChunks(chunks)
|
|
90
|
-
|
|
91
|
-
suggestions.recommended[bundleName] = patterns
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Alternative: Group by directory structure
|
|
95
|
-
const dirGroups = this.groupChunksByDirectory(analysis.chunks)
|
|
96
|
-
|
|
97
|
-
for (const [dir, chunks] of Object.entries(dirGroups)) {
|
|
98
|
-
const bundleName = `${name}-${dir}`
|
|
99
|
-
const patterns = this.generatePatternsForChunks(chunks)
|
|
100
|
-
|
|
101
|
-
suggestions.alternative[bundleName] = patterns
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Add specialized bundles
|
|
106
|
-
this.addSpecializedBundles(suggestions, namedAnalyses)
|
|
107
|
-
|
|
108
|
-
// Add optimization notes
|
|
109
|
-
this.addOptimizationNotes(suggestions, namedAnalyses)
|
|
110
|
-
|
|
111
|
-
return suggestions
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Group chunks by their primary purpose
|
|
116
|
-
*/
|
|
117
|
-
groupChunksByPurpose(chunks) {
|
|
118
|
-
const groups = {}
|
|
119
|
-
|
|
120
|
-
for (const chunk of chunks) {
|
|
121
|
-
const purpose = chunk.purpose || 'misc'
|
|
122
|
-
if (!groups[purpose]) {
|
|
123
|
-
groups[purpose] = []
|
|
124
|
-
}
|
|
125
|
-
groups[purpose].push(chunk)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return groups
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Group chunks by directory structure
|
|
133
|
-
*/
|
|
134
|
-
groupChunksByDirectory(chunks) {
|
|
135
|
-
const groups = {}
|
|
136
|
-
|
|
137
|
-
for (const chunk of chunks) {
|
|
138
|
-
// Extract directory from chunk name or files
|
|
139
|
-
const dir = chunk.name.split('-')[0] || 'misc'
|
|
140
|
-
if (!groups[dir]) {
|
|
141
|
-
groups[dir] = []
|
|
142
|
-
}
|
|
143
|
-
groups[dir].push(chunk)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return groups
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Generate glob patterns for chunks
|
|
151
|
-
*/
|
|
152
|
-
generatePatternsForChunks(chunks) {
|
|
153
|
-
const patterns = new Set()
|
|
154
|
-
|
|
155
|
-
for (const chunk of chunks) {
|
|
156
|
-
for (const file of chunk.files) {
|
|
157
|
-
// Convert file paths to glob patterns
|
|
158
|
-
const pattern = this.fileToGlobPattern(file)
|
|
159
|
-
patterns.add(pattern)
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return Array.from(patterns)
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Convert file path to glob pattern
|
|
168
|
-
*/
|
|
169
|
-
fileToGlobPattern(filePath) {
|
|
170
|
-
// Extract directory and create pattern
|
|
171
|
-
const parts = filePath.split('/')
|
|
172
|
-
const dir = parts.slice(0, -1).join('/')
|
|
173
|
-
const ext = parts[parts.length - 1].split('.').pop()
|
|
174
|
-
|
|
175
|
-
return `${dir}/**/*.${ext}`
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Add specialized bundle suggestions
|
|
180
|
-
*/
|
|
181
|
-
addSpecializedBundles(suggestions, namedAnalyses) {
|
|
182
|
-
// UI Components bundle
|
|
183
|
-
const componentsAnalysis = namedAnalyses.find(a => a.name === 'components')?.analysis
|
|
184
|
-
if (componentsAnalysis?.chunks.length > 0) {
|
|
185
|
-
const uiComponents = componentsAnalysis.chunks.filter(c =>
|
|
186
|
-
c.name.includes('ui') || c.tags.includes('has-components')
|
|
187
|
-
)
|
|
188
|
-
|
|
189
|
-
if (uiComponents.length > 0) {
|
|
190
|
-
suggestions.recommended['ui-system'] = [
|
|
191
|
-
'web/src/components/ui/**/*.tsx',
|
|
192
|
-
'web/src/components/theme-*.tsx'
|
|
193
|
-
]
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// Test files bundle
|
|
198
|
-
suggestions.recommended['tests'] = [
|
|
199
|
-
'**/*.test.{js,jsx,ts,tsx}',
|
|
200
|
-
'**/*.spec.{js,jsx,ts,tsx}',
|
|
201
|
-
'**/__tests__/**/*'
|
|
202
|
-
]
|
|
203
|
-
|
|
204
|
-
// Configuration bundle
|
|
205
|
-
suggestions.recommended['config'] = [
|
|
206
|
-
'*.config.{js,ts}',
|
|
207
|
-
'*.json',
|
|
208
|
-
'package.json',
|
|
209
|
-
'tsconfig*.json',
|
|
210
|
-
'.env*'
|
|
211
|
-
]
|
|
212
|
-
|
|
213
|
-
// Documentation bundle
|
|
214
|
-
suggestions.recommended['docs'] = [
|
|
215
|
-
'**/*.md',
|
|
216
|
-
'docs/**/*',
|
|
217
|
-
'README*'
|
|
218
|
-
]
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Add optimization notes and recommendations
|
|
223
|
-
*/
|
|
224
|
-
addOptimizationNotes(suggestions, namedAnalyses) {
|
|
225
|
-
suggestions.notes = []
|
|
226
|
-
|
|
227
|
-
// Analyze bundle sizes
|
|
228
|
-
const totalFiles = namedAnalyses.reduce((sum, a) => sum + a.analysis.summary.totalFiles, 0)
|
|
229
|
-
const totalChunks = namedAnalyses.reduce((sum, a) => sum + a.analysis.summary.totalChunks, 0)
|
|
230
|
-
|
|
231
|
-
suggestions.notes.push({
|
|
232
|
-
type: 'info',
|
|
233
|
-
message: `Project has ${totalFiles} files organized into ${totalChunks} semantic chunks`
|
|
234
|
-
})
|
|
235
|
-
|
|
236
|
-
// Check for large files
|
|
237
|
-
const largeFiles = []
|
|
238
|
-
for (const { analysis } of namedAnalyses) {
|
|
239
|
-
for (const [path, file] of Object.entries(analysis.files)) {
|
|
240
|
-
if (file.lines > 300) {
|
|
241
|
-
largeFiles.push({ path, lines: file.lines })
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
if (largeFiles.length > 0) {
|
|
247
|
-
suggestions.notes.push({
|
|
248
|
-
type: 'warning',
|
|
249
|
-
message: `${largeFiles.length} files exceed 300 lines and may benefit from splitting`,
|
|
250
|
-
details: largeFiles.slice(0, 3).map(f => `${f.path} (${f.lines} lines)`)
|
|
251
|
-
})
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// Check for high complexity
|
|
255
|
-
const complexFiles = []
|
|
256
|
-
for (const { analysis } of namedAnalyses) {
|
|
257
|
-
for (const [path, file] of Object.entries(analysis.files)) {
|
|
258
|
-
if (file.complexity?.level === 'high') {
|
|
259
|
-
complexFiles.push({ path, score: file.complexity.score })
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (complexFiles.length > 0) {
|
|
265
|
-
suggestions.notes.push({
|
|
266
|
-
type: 'optimization',
|
|
267
|
-
message: `${complexFiles.length} files have high complexity and may need refactoring`,
|
|
268
|
-
details: complexFiles.slice(0, 3).map(f => `${f.path} (score: ${f.score})`)
|
|
269
|
-
})
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Suggest bundle patterns
|
|
273
|
-
suggestions.notes.push({
|
|
274
|
-
type: 'suggestion',
|
|
275
|
-
message: 'Consider using semantic bundles for better AI context understanding',
|
|
276
|
-
details: [
|
|
277
|
-
'UI components grouped by functionality',
|
|
278
|
-
'Hooks grouped by domain logic',
|
|
279
|
-
'Utilities grouped by purpose',
|
|
280
|
-
'Tests separated for focused debugging'
|
|
281
|
-
]
|
|
282
|
-
})
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Generate overall project summary
|
|
287
|
-
*/
|
|
288
|
-
generateOverallSummary(analyses) {
|
|
289
|
-
const totalFiles = analyses.reduce((sum, a) => sum + a.summary.totalFiles, 0)
|
|
290
|
-
const totalSize = analyses.reduce((sum, a) => sum + a.summary.totalSize, 0)
|
|
291
|
-
const totalLines = analyses.reduce((sum, a) => sum + a.summary.totalLines, 0)
|
|
292
|
-
const totalChunks = analyses.reduce((sum, a) => sum + a.summary.totalChunks, 0)
|
|
293
|
-
|
|
294
|
-
const fileTypes = {}
|
|
295
|
-
const filePurposes = {}
|
|
296
|
-
const complexityDistribution = {}
|
|
297
|
-
|
|
298
|
-
for (const analysis of analyses) {
|
|
299
|
-
// Merge file types
|
|
300
|
-
for (const [type, count] of Object.entries(analysis.summary.fileTypes)) {
|
|
301
|
-
fileTypes[type] = (fileTypes[type] || 0) + count
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Merge purposes
|
|
305
|
-
for (const [purpose, count] of Object.entries(analysis.summary.filePurposes)) {
|
|
306
|
-
filePurposes[purpose] = (filePurposes[purpose] || 0) + count
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
// Merge complexity
|
|
310
|
-
for (const [level, count] of Object.entries(analysis.summary.complexityDistribution)) {
|
|
311
|
-
complexityDistribution[level] = (complexityDistribution[level] || 0) + count
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
return {
|
|
316
|
-
totalFiles,
|
|
317
|
-
totalSize,
|
|
318
|
-
totalLines,
|
|
319
|
-
totalChunks,
|
|
320
|
-
fileTypes,
|
|
321
|
-
filePurposes,
|
|
322
|
-
complexityDistribution,
|
|
323
|
-
averageFileSize: Math.round(totalSize / totalFiles),
|
|
324
|
-
averageLinesPerFile: Math.round(totalLines / totalFiles),
|
|
325
|
-
formattedSize: this.formatBytes(totalSize)
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
/**
|
|
330
|
-
* Convert semantic suggestions to cntx-ui bundle format
|
|
331
|
-
*/
|
|
332
|
-
convertToConfigFormat(suggestions) {
|
|
333
|
-
return {
|
|
334
|
-
bundles: {
|
|
335
|
-
// Keep existing master bundle
|
|
336
|
-
master: ['**/*'],
|
|
337
|
-
|
|
338
|
-
// Add recommended semantic bundles
|
|
339
|
-
...suggestions.recommended,
|
|
340
|
-
|
|
341
|
-
// Add alternative bundles as commented examples
|
|
342
|
-
// ...suggestions.alternative (uncomment to use directory-based grouping)
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Save analysis results to file
|
|
349
|
-
*/
|
|
350
|
-
async saveAnalysisResults(results, outputPath = 'semantic-analysis.json') {
|
|
351
|
-
try {
|
|
352
|
-
const fullPath = join(this.projectPath, outputPath)
|
|
353
|
-
writeFileSync(fullPath, JSON.stringify(results, null, 2))
|
|
354
|
-
console.log(`š Analysis saved to ${fullPath}`)
|
|
355
|
-
return fullPath
|
|
356
|
-
} catch (error) {
|
|
357
|
-
console.error('ā Failed to save analysis:', error.message)
|
|
358
|
-
throw error
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* Generate bundle config suggestions file
|
|
364
|
-
*/
|
|
365
|
-
async generateBundleConfigSuggestions(results, outputPath = 'semantic-bundle-suggestions.json') {
|
|
366
|
-
try {
|
|
367
|
-
const config = this.convertToConfigFormat(results.suggestions)
|
|
368
|
-
const fullPath = join(this.projectPath, outputPath)
|
|
369
|
-
|
|
370
|
-
const output = {
|
|
371
|
-
timestamp: results.timestamp,
|
|
372
|
-
description: 'Semantic chunking suggestions for cntx-ui bundles',
|
|
373
|
-
usage: 'Copy the bundles object to your .cntx/bundles.json file',
|
|
374
|
-
...config,
|
|
375
|
-
notes: results.suggestions.notes,
|
|
376
|
-
summary: results.summary
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
writeFileSync(fullPath, JSON.stringify(output, null, 2))
|
|
380
|
-
console.log(`š¦ Bundle suggestions saved to ${fullPath}`)
|
|
381
|
-
return fullPath
|
|
382
|
-
} catch (error) {
|
|
383
|
-
console.error('ā Failed to save bundle suggestions:', error.message)
|
|
384
|
-
throw error
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* Format bytes to human readable
|
|
390
|
-
*/
|
|
391
|
-
formatBytes(bytes) {
|
|
392
|
-
if (bytes === 0) return '0 Bytes'
|
|
393
|
-
const k = 1024
|
|
394
|
-
const sizes = ['Bytes', 'KB', 'MB', 'GB']
|
|
395
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
|
396
|
-
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
export default SemanticIntegration
|
|
401
|
-
|
|
402
|
-
// CLI usage
|
|
403
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
404
|
-
const integration = new SemanticIntegration()
|
|
405
|
-
|
|
406
|
-
console.log('š Starting semantic analysis integration...')
|
|
407
|
-
|
|
408
|
-
try {
|
|
409
|
-
const results = await integration.generateSemanticBundles()
|
|
410
|
-
|
|
411
|
-
// Save full analysis
|
|
412
|
-
await integration.saveAnalysisResults(results)
|
|
413
|
-
|
|
414
|
-
// Save bundle suggestions
|
|
415
|
-
await integration.generateBundleConfigSuggestions(results)
|
|
416
|
-
|
|
417
|
-
console.log('\nš Project Summary:')
|
|
418
|
-
console.log(`š ${results.summary.totalFiles} files analyzed`)
|
|
419
|
-
console.log(`š¾ ${results.summary.formattedSize} total size`)
|
|
420
|
-
console.log(`š¦ ${results.summary.totalChunks} semantic chunks created`)
|
|
421
|
-
console.log(`šÆ ${Object.keys(results.suggestions.recommended).length} recommended bundles`)
|
|
422
|
-
|
|
423
|
-
console.log('\nšÆ Recommended Bundles:')
|
|
424
|
-
for (const [name, patterns] of Object.entries(results.suggestions.recommended)) {
|
|
425
|
-
console.log(` ⢠${name}: ${patterns.length} patterns`)
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
console.log('\nš” Notes:')
|
|
429
|
-
results.suggestions.notes.forEach(note => {
|
|
430
|
-
const emoji = note.type === 'warning' ? 'ā ļø' : note.type === 'optimization' ? 'š§' : 'š”'
|
|
431
|
-
console.log(` ${emoji} ${note.message}`)
|
|
432
|
-
})
|
|
433
|
-
|
|
434
|
-
console.log('\nā
Semantic integration complete!')
|
|
435
|
-
console.log('š Check semantic-bundle-suggestions.json for ready-to-use bundle configurations')
|
|
436
|
-
|
|
437
|
-
} catch (error) {
|
|
438
|
-
console.error('ā Integration failed:', error.message)
|
|
439
|
-
process.exit(1)
|
|
440
|
-
}
|
|
441
|
-
}
|