matex-cli 1.2.81 → 1.2.84

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 (142) hide show
  1. package/dist/commands/chaos.js +3 -8
  2. package/dist/prompts/chaos-prompts.js +26 -21
  3. package/dist/session/agent-session.js +38 -9
  4. package/dist/utils/agent-orchestrator.js +7 -0
  5. package/dist/utils/mcp-server.js +6 -0
  6. package/dist/utils/tui.js +84 -7
  7. package/package.json +7 -1
  8. package/.agents/skills/mcp-server-dev/SKILL.md +0 -60
  9. package/.agents/skills/mcp-server-dev/examples/basic-ts-server/package.json +0 -20
  10. package/.agents/skills/mcp-server-dev/examples/basic-ts-server/src/index.ts +0 -66
  11. package/.agents/skills/mcp-server-dev/resources/best_practices.md +0 -20
  12. package/.agents/skills/pptx-presentation-builder/SKILL.md +0 -338
  13. package/.agents/workflows/deploy.md +0 -27
  14. package/dist/api/client.d.ts +0 -40
  15. package/dist/api/client.d.ts.map +0 -1
  16. package/dist/api/client.js.map +0 -1
  17. package/dist/commands/ask.d.ts +0 -3
  18. package/dist/commands/ask.d.ts.map +0 -1
  19. package/dist/commands/ask.js.map +0 -1
  20. package/dist/commands/augov.d.ts +0 -3
  21. package/dist/commands/augov.d.ts.map +0 -1
  22. package/dist/commands/augov.js.map +0 -1
  23. package/dist/commands/bro.d.ts +0 -4
  24. package/dist/commands/bro.d.ts.map +0 -1
  25. package/dist/commands/bro.js.map +0 -1
  26. package/dist/commands/chaos.d.ts +0 -3
  27. package/dist/commands/chaos.d.ts.map +0 -1
  28. package/dist/commands/chaos.js.map +0 -1
  29. package/dist/commands/chat.d.ts +0 -3
  30. package/dist/commands/chat.d.ts.map +0 -1
  31. package/dist/commands/chat.js.map +0 -1
  32. package/dist/commands/code.d.ts +0 -3
  33. package/dist/commands/code.d.ts.map +0 -1
  34. package/dist/commands/code.js.map +0 -1
  35. package/dist/commands/config.d.ts +0 -3
  36. package/dist/commands/config.d.ts.map +0 -1
  37. package/dist/commands/config.js.map +0 -1
  38. package/dist/commands/dev.d.ts +0 -3
  39. package/dist/commands/dev.d.ts.map +0 -1
  40. package/dist/commands/dev.js.map +0 -1
  41. package/dist/commands/help.d.ts +0 -3
  42. package/dist/commands/help.d.ts.map +0 -1
  43. package/dist/commands/help.js.map +0 -1
  44. package/dist/commands/login.d.ts +0 -3
  45. package/dist/commands/login.d.ts.map +0 -1
  46. package/dist/commands/login.js.map +0 -1
  47. package/dist/commands/models.d.ts +0 -3
  48. package/dist/commands/models.d.ts.map +0 -1
  49. package/dist/commands/models.js.map +0 -1
  50. package/dist/commands/student.d.ts +0 -3
  51. package/dist/commands/student.d.ts.map +0 -1
  52. package/dist/commands/student.js.map +0 -1
  53. package/dist/commands/study.d.ts +0 -3
  54. package/dist/commands/study.d.ts.map +0 -1
  55. package/dist/commands/study.js.map +0 -1
  56. package/dist/index.d.ts +0 -3
  57. package/dist/index.d.ts.map +0 -1
  58. package/dist/index.js.map +0 -1
  59. package/dist/prompts/banter-augov.d.ts +0 -2
  60. package/dist/prompts/banter-augov.d.ts.map +0 -1
  61. package/dist/prompts/banter-augov.js.map +0 -1
  62. package/dist/prompts/banter.d.ts +0 -6
  63. package/dist/prompts/banter.d.ts.map +0 -1
  64. package/dist/prompts/banter.js.map +0 -1
  65. package/dist/prompts/chaos-prompts.d.ts +0 -3
  66. package/dist/prompts/chaos-prompts.d.ts.map +0 -1
  67. package/dist/prompts/chaos-prompts.js.map +0 -1
  68. package/dist/prompts/system-prompts.d.ts +0 -4
  69. package/dist/prompts/system-prompts.d.ts.map +0 -1
  70. package/dist/prompts/system-prompts.js.map +0 -1
  71. package/dist/session/agent-session.d.ts +0 -41
  72. package/dist/session/agent-session.d.ts.map +0 -1
  73. package/dist/session/agent-session.js.map +0 -1
  74. package/dist/utils/agent-orchestrator.d.ts +0 -44
  75. package/dist/utils/agent-orchestrator.d.ts.map +0 -1
  76. package/dist/utils/agent-orchestrator.js.map +0 -1
  77. package/dist/utils/augov-logger.d.ts +0 -11
  78. package/dist/utils/augov-logger.d.ts.map +0 -1
  79. package/dist/utils/augov-logger.js.map +0 -1
  80. package/dist/utils/augov-scrubber.d.ts +0 -23
  81. package/dist/utils/augov-scrubber.d.ts.map +0 -1
  82. package/dist/utils/augov-scrubber.js.map +0 -1
  83. package/dist/utils/command-executor.d.ts +0 -56
  84. package/dist/utils/command-executor.d.ts.map +0 -1
  85. package/dist/utils/command-executor.js.map +0 -1
  86. package/dist/utils/config.d.ts +0 -56
  87. package/dist/utils/config.d.ts.map +0 -1
  88. package/dist/utils/config.js.map +0 -1
  89. package/dist/utils/mcp-server.d.ts +0 -77
  90. package/dist/utils/mcp-server.d.ts.map +0 -1
  91. package/dist/utils/mcp-server.js.map +0 -1
  92. package/dist/utils/patcher.d.ts +0 -45
  93. package/dist/utils/patcher.d.ts.map +0 -1
  94. package/dist/utils/patcher.js.map +0 -1
  95. package/dist/utils/repo-mapper.d.ts +0 -32
  96. package/dist/utils/repo-mapper.d.ts.map +0 -1
  97. package/dist/utils/repo-mapper.js.map +0 -1
  98. package/dist/utils/spinner.d.ts +0 -15
  99. package/dist/utils/spinner.d.ts.map +0 -1
  100. package/dist/utils/spinner.js.map +0 -1
  101. package/dist/utils/tui.d.ts +0 -134
  102. package/dist/utils/tui.d.ts.map +0 -1
  103. package/dist/utils/tui.js.map +0 -1
  104. package/fix-npm-permissions.sh +0 -23
  105. package/publish-local.sh +0 -16
  106. package/skills-lock.json +0 -10
  107. package/src/api/client.ts +0 -197
  108. package/src/commands/ask.ts +0 -62
  109. package/src/commands/augov.ts +0 -301
  110. package/src/commands/bro.ts +0 -336
  111. package/src/commands/chaos.ts +0 -67
  112. package/src/commands/chat.ts +0 -61
  113. package/src/commands/code.ts +0 -99
  114. package/src/commands/config.ts +0 -78
  115. package/src/commands/dev.ts +0 -68
  116. package/src/commands/help.ts +0 -67
  117. package/src/commands/login.ts +0 -47
  118. package/src/commands/models.ts +0 -81
  119. package/src/commands/student.ts +0 -23
  120. package/src/commands/study.ts +0 -75
  121. package/src/index.ts +0 -284
  122. package/src/prompts/banter-augov.ts +0 -17
  123. package/src/prompts/banter.ts +0 -101
  124. package/src/prompts/chaos-prompts.ts +0 -48
  125. package/src/prompts/system-prompts.ts +0 -145
  126. package/src/session/agent-session.ts +0 -428
  127. package/src/utils/agent-orchestrator.ts +0 -264
  128. package/src/utils/augov-logger.ts +0 -34
  129. package/src/utils/augov-scrubber.ts +0 -67
  130. package/src/utils/command-executor.ts +0 -529
  131. package/src/utils/config.ts +0 -124
  132. package/src/utils/mcp-server.ts +0 -388
  133. package/src/utils/patcher.ts +0 -229
  134. package/src/utils/repo-mapper.ts +0 -198
  135. package/src/utils/spinner.ts +0 -66
  136. package/src/utils/tui.ts +0 -749
  137. package/test-chaos-container.js +0 -16
  138. package/test-chaos-fix.js +0 -18
  139. package/test-config.ts +0 -2
  140. package/test-ui-output.js +0 -16
  141. package/tsconfig.json +0 -27
  142. package/vertex_ai_agent.py +0 -52
@@ -1,229 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import chalk from 'chalk';
4
- import { TUI } from './tui';
5
-
6
- export interface EditBlock {
7
- filePath: string;
8
- search: string;
9
- replace: string;
10
- }
11
-
12
- export class Patcher {
13
- /**
14
- * Parse surgical edit blocks from AI response
15
- * Format:
16
- * **filename**
17
- * <<<< SEARCH
18
- * content
19
- * ====
20
- * replacement
21
- * >>>> REPLACE
22
- */
23
- static parseEditBlocks(response: string): EditBlock[] {
24
- // Emergency closure for unclosed REPLACE blocks
25
- if (response.includes('<<<< SEARCH') && !response.includes('>>>> REPLACE')) {
26
- response += '\n>>>> REPLACE';
27
- }
28
-
29
- const blocks: EditBlock[] = [];
30
- // Robust regex: Matches filename with or without stars, handle potential leading/trailing spaces
31
- const blockRegex = /(?:\*\*?\s*)?([^*<\n]+?)(?:\s*\*?\*)?\s*<<<< SEARCH\n([\s\S]*?)\n====\n([\s\S]*?)\n>>>> REPLACE/gi;
32
-
33
- let match;
34
- while ((match = blockRegex.exec(response)) !== null) {
35
- blocks.push({
36
- filePath: match[1].trim(),
37
- search: match[2],
38
- replace: match[3]
39
- });
40
- }
41
-
42
- return blocks;
43
- }
44
-
45
- /**
46
- * Parse file creation blocks from AI response
47
- * Format:
48
- * <file path="path/to/file.ext">
49
- * content
50
- * </file>
51
- */
52
- static parseFileBlocks(response: string): EditBlock[] {
53
- // Emergency closure for unclosed file blocks
54
- if (response.toLowerCase().includes('<file path=') && !response.toLowerCase().includes('</file>')) {
55
- response += '\n</file>';
56
- }
57
-
58
- const blocks: EditBlock[] = [];
59
- const fileRegex = /<file path="([^"]+)">([\s\S]*?)<\/file>/gi;
60
-
61
- let match;
62
- while ((match = fileRegex.exec(response)) !== null) {
63
- blocks.push({
64
- filePath: match[1].trim(),
65
- search: '', // Not used for new files
66
- replace: match[2]
67
- });
68
- }
69
-
70
- return blocks;
71
- }
72
-
73
- /**
74
- * Create a new file (and its directories)
75
- */
76
- static createFile(block: EditBlock): { success: boolean; error?: string } {
77
- TUI.drawStatusBar(`Creating File: ${block.filePath}...`);
78
- try {
79
- const fullPath = path.resolve(process.cwd(), block.filePath);
80
- const dir = path.dirname(fullPath);
81
-
82
- if (!fs.existsSync(dir)) {
83
- fs.mkdirSync(dir, { recursive: true });
84
- }
85
-
86
- fs.writeFileSync(fullPath, block.replace, 'utf8');
87
-
88
- TUI.drawStatusBar(`✅ Success: ${block.filePath} created.`);
89
- return { success: true };
90
- } catch (err: any) {
91
- TUI.drawStatusBar(`❌ Error: ${err.message}`);
92
- return { success: false, error: err.message };
93
- }
94
- }
95
-
96
- /**
97
- * Apply a surgical patch to a file
98
- */
99
- static applyPatch(block: EditBlock): { success: boolean; error?: string } {
100
- TUI.drawStatusBar(`Applying Patch: ${block.filePath}...`);
101
- try {
102
- const fullPath = path.resolve(process.cwd(), block.filePath);
103
-
104
- if (!fs.existsSync(fullPath)) {
105
- TUI.drawStatusBar(`Error: File not found: ${block.filePath}`);
106
- return { success: false, error: `File not found: ${block.filePath}` };
107
- }
108
-
109
- const startTime = Date.now();
110
- const content = fs.readFileSync(fullPath, 'utf8');
111
- const stats = fs.statSync(fullPath);
112
- const fileSizeMB = stats.size / (1024 * 1024);
113
-
114
- if (fileSizeMB > 1) {
115
- TUI.log(chalk.gray(` [⏱️] Processing large file (${fileSizeMB.toFixed(2)} MB)...`));
116
- }
117
-
118
- // 1. Precise Normalization
119
- const normalize = (text: string) => text.replace(/\r\n/g, '\n').split('\n').map(l => l.trimEnd()).join('\n');
120
- const normalizedContent = normalize(content);
121
- const normalizedSearch = normalize(block.search);
122
- const normalizedReplace = normalize(block.replace);
123
-
124
- // 2. Exact Match Check (Post-Normalization)
125
- if (normalizedContent.includes(normalizedSearch)) {
126
- const updatedContent = normalizedContent.replace(normalizedSearch, normalizedReplace);
127
- fs.writeFileSync(fullPath, updatedContent, 'utf8');
128
- TUI.drawStatusBar(`✅ Success: ${block.filePath} patched.`);
129
- return { success: true };
130
- }
131
-
132
- // 3. Ultra-Fuzzy Matching (Line-by-line trim and compare)
133
- const contentLines = normalizedContent.split('\n');
134
- const searchLines = normalizedSearch.split('\n');
135
-
136
- let matchIndex = -1;
137
- for (let i = 0; i <= contentLines.length - searchLines.length; i++) {
138
- let match = true;
139
- for (let j = 0; j < searchLines.length; j++) {
140
- if (contentLines[i + j].trim() !== searchLines[j].trim()) {
141
- match = false;
142
- break;
143
- }
144
- }
145
- if (match) {
146
- matchIndex = i;
147
- break;
148
- }
149
- }
150
-
151
- if (matchIndex !== -1) {
152
- // Apply replacement while preserving surrounding lines
153
- const updatedLines = [
154
- ...contentLines.slice(0, matchIndex),
155
- normalizedReplace,
156
- ...contentLines.slice(matchIndex + searchLines.length)
157
- ];
158
- fs.writeFileSync(fullPath, updatedLines.join('\n'), 'utf8');
159
- const elapsed = Date.now() - startTime;
160
- if (fileSizeMB > 1) {
161
- TUI.drawStatusBar(`✅ Success (Fuzzy): ${block.filePath} patched in ${elapsed}ms.`);
162
- } else {
163
- TUI.drawStatusBar(`✅ Success (Fuzzy): ${block.filePath} patched.`);
164
- }
165
- return { success: true };
166
- }
167
-
168
- TUI.drawStatusBar(`❌ Patch Failed: Search block not found in ${block.filePath}`);
169
- return {
170
- success: false,
171
- error: `Search block not found in ${block.filePath}. Please ensure the code snippet matches exactly (ignoring whitespace).`
172
- };
173
- } catch (err: any) {
174
- TUI.drawStatusBar(`❌ Error: ${err.message}`);
175
- return { success: false, error: err.message };
176
- }
177
- }
178
-
179
- /**
180
- * Visualize the diff in a premium "Bro" style with Window-like container
181
- */
182
- static showDiff(block: EditBlock, full: boolean = false): boolean {
183
- const width = Math.min(process.stdout.columns || 80, 100);
184
- const searchLines = (block.search || '').split('\n');
185
- const replaceLines = block.replace.split('\n');
186
-
187
- const isNewFile = !block.search;
188
- const isLarge = replaceLines.length > 12;
189
- const shouldTruncate = isLarge && !full;
190
-
191
- const displaySearch = shouldTruncate ? searchLines.slice(0, 8) : searchLines;
192
- const displayReplace = shouldTruncate ? replaceLines.slice(0, 8) : replaceLines;
193
-
194
- const redGlow = chalk.hex('#ef4444');
195
- const greenGlow = chalk.hex('#22c55e');
196
- const border = chalk.hex('#334155');
197
-
198
- console.log('\n' + border(` ┌${'─'.repeat(width - 4)}┐`));
199
- const type = isNewFile ? '🆕 NEW FILE' : '🔧 PATCH';
200
- const title = ` ${type}: ${block.filePath} `;
201
- console.log(border(' │ ') + chalk.bgHex('#1e293b').cyan.bold(title).padEnd(width - 6) + border(' │'));
202
- console.log(border(' ├' + '╌'.repeat(width - 4) + '┤'));
203
-
204
- if (!isNewFile) {
205
- displaySearch.forEach((line) => {
206
- const displayLine = line.length > width - 12 ? line.substring(0, width - 15) + '...' : line;
207
- console.log(redGlow(' │ ') + chalk.bgRed.white(' - ') + ' ' + redGlow(displayLine.padEnd(width - 10)) + redGlow(' │'));
208
- });
209
- if (shouldTruncate && searchLines.length > 8) {
210
- console.log(redGlow(' │ ') + chalk.dim(` ... ${searchLines.length - 8} more lines removed ...`).padEnd(width - 6) + redGlow(' │'));
211
- }
212
- console.log(border(' ├' + '─'.repeat(width - 4) + '┤'));
213
- }
214
-
215
- displayReplace.forEach((line) => {
216
- const displayLine = line.length > width - 12 ? line.substring(0, width - 15) + '...' : line;
217
- console.log(greenGlow(' │ ') + chalk.bgGreen.black(' + ') + ' ' + greenGlow(displayLine.padEnd(width - 10)) + greenGlow(' │'));
218
- });
219
-
220
- if (replaceLines.length > 8) {
221
- console.log(greenGlow(' │ ') + chalk.hex('#06b6d4').bold(` ^ [ ${replaceLines.length - 8} MORE LINES • USE ^ TO SEE ALL ] ^`).padEnd(width - 6) + greenGlow(' │'));
222
- }
223
-
224
- console.log(border(` └${'─'.repeat(width - 4)}┘`));
225
- console.log();
226
-
227
- return shouldTruncate;
228
- }
229
- }
@@ -1,198 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import chalk from 'chalk';
4
- import { AgentOrchestrator } from './agent-orchestrator';
5
-
6
- export interface RepoNode {
7
- path: string;
8
- type: 'file' | 'directory';
9
- children?: RepoNode[];
10
- summary?: string; // e.g., "Class: AuthManager, Func: login"
11
- }
12
-
13
- export class RepoMapper {
14
- private rootPath: string;
15
- private ignoreList: string[] = [
16
- '.git', 'node_modules', 'dist', 'build', '.next', '.DS_Store',
17
- 'coverage', '.vercel', '.firebase', 'out', 'public',
18
- 'bin', 'obj', '.vs', 'vendor', '__pycache__', 'env', '.env', 'venv'
19
- ];
20
- private fileCount = 0;
21
- private readonly MAX_FILES = 500;
22
- private fileContents: Map<string, string> = new Map();
23
-
24
- constructor(rootPath: string) {
25
- this.rootPath = rootPath;
26
- }
27
-
28
- /**
29
- * Generate a hierarchical map of the repository with deep entry-point analysis
30
- */
31
- public async generateMap(silent: boolean = false): Promise<string> {
32
- if (!silent) AgentOrchestrator.speak('System', `God-Mode Research: Indexing ${this.rootPath}...`);
33
-
34
- this.fileContents.clear();
35
-
36
- // 1. Identify Entry Points
37
- const entryPoints = ['README.md', 'package.json', 'index.ts', 'App.tsx', 'main.go', 'requirements.txt', 'index.html', 'style.css'];
38
-
39
- let delayMs = 15; // Animation delay
40
-
41
- if (!silent) {
42
- AgentOrchestrator.speak('System', `God-Mode Research: Injecting scanners into ${this.rootPath}...`);
43
- console.log();
44
- }
45
-
46
- for (const file of entryPoints) {
47
- const fullPath = path.join(this.rootPath, file);
48
- if (fs.existsSync(fullPath)) {
49
- try {
50
- const content = fs.readFileSync(fullPath, 'utf-8').slice(0, 5000); // 5KB limit
51
- this.fileContents.set(file, content);
52
- if (!silent) console.log(chalk.hex('#4ade80')(` ⚡ [Core Injection] `) + chalk.gray(`Mapped entry node: `) + chalk.white.bold(file));
53
- } catch (e) { }
54
- }
55
- }
56
-
57
- if (!silent) console.log(chalk.cyan(` 🔍 [Deep Scan] `) + chalk.gray(`Mapping topology...`));
58
- const tree = this.scanDirectory(this.rootPath, 0);
59
-
60
- if (!silent) {
61
- console.log(chalk.hex('#FF6B00')(` 🔥 [Knowledge Graph] `) + chalk.gray(`Extracted ${this.fileContents.size} semantic nodes from source.`));
62
- console.log();
63
- }
64
-
65
- // Build the final map
66
- let finalMap = `--- ABSOLUTE WORKING DIRECTORY ---\n${this.rootPath}\n\n`;
67
-
68
- if (!tree.children || tree.children.length === 0) {
69
- finalMap += `⚠️ [CRITICAL WARNING]: THIS DIRECTORY IS COMPLETELY EMPTY.\nTHERE ARE NO FILES OR FOLDERS HERE.\nDO NOT HALLUCINATE ANY CONTENT!\n\n`;
70
- } else {
71
- finalMap += `--- DIRECTORY STRUCTURE ---\n` + this.formatTree(tree);
72
- }
73
-
74
- if (this.fileContents.size > 0) {
75
- finalMap += '\n\n--- CRAWLED FILE CONTENTS ---\n';
76
- for (const [filePath, content] of this.fileContents) {
77
- finalMap += `\nFILE: ${filePath}\n\`\`\`\n${content}\n\`\`\`\n----------------\n`;
78
- }
79
- }
80
-
81
- return finalMap;
82
- }
83
-
84
- /**
85
- * Recursive directory scan
86
- */
87
- private scanDirectory(currentPath: string, depth: number): RepoNode {
88
- const stats = fs.statSync(currentPath);
89
- const name = path.basename(currentPath);
90
-
91
- if (stats.isFile()) {
92
- const summary = this.extractSummary(currentPath);
93
-
94
- // Also auto-crawl any .ts, .js, .css, .html files if they are small
95
- const ext = path.extname(currentPath);
96
- const relPath = path.relative(this.rootPath, currentPath);
97
-
98
- if (stats.size < 5120 && ['.ts', '.js', '.css', '.html', '.json', '.py'].includes(ext)) {
99
- if (!this.fileContents.has(relPath)) {
100
- try {
101
- const content = fs.readFileSync(currentPath, 'utf-8');
102
- this.fileContents.set(relPath, content);
103
- } catch (e) { }
104
- }
105
- }
106
-
107
- return {
108
- path: currentPath,
109
- type: 'file',
110
- summary: summary
111
- };
112
- }
113
-
114
- // It's a directory
115
- if (depth > 5) return { path: currentPath, type: 'directory', children: [] }; // Max depth safety
116
-
117
- const children: RepoNode[] = [];
118
- try {
119
- const items = fs.readdirSync(currentPath);
120
- for (const item of items) {
121
- if (this.fileCount > this.MAX_FILES) break;
122
- if (this.ignoreList.includes(item)) continue;
123
-
124
- const fullPath = path.join(currentPath, item);
125
- // Simple ignore check for hidden files
126
- if (item.startsWith('.') && item !== '.gitignore') continue;
127
-
128
- children.push(this.scanDirectory(fullPath, depth + 1));
129
- }
130
- } catch (error) {
131
- // Permission denied or other error
132
- }
133
-
134
- return {
135
- path: currentPath,
136
- type: 'directory',
137
- children: children
138
- };
139
- }
140
-
141
- /**
142
- * Extract key definitions (Classes, Functions) from file content
143
- * A lightweight "ctags" style summary
144
- */
145
- private extractSummary(filePath: string): string {
146
- const ext = path.extname(filePath);
147
- if (!['.ts', '.tsx', '.js', '.jsx', '.py', '.go', '.rs'].includes(ext)) return '';
148
-
149
- try {
150
- const content = fs.readFileSync(filePath, 'utf-8');
151
- const lines = content.split('\n');
152
- const definitions: string[] = [];
153
-
154
- // Very header-heavy regex matching for speed
155
- for (const line of lines) {
156
- const trimmed = line.trim();
157
- if (trimmed.startsWith('export class ')) {
158
- definitions.push(`Class: ${trimmed.split(' ')[2]}`);
159
- } else if (trimmed.startsWith('function ') || trimmed.startsWith('export function ')) {
160
- const funcName = trimmed.split('(')[0].split(' ').pop();
161
- definitions.push(`Func: ${funcName}`);
162
- } else if (trimmed.includes('const ') && trimmed.includes(' = (') && trimmed.includes('=>')) {
163
- // Arrow functions
164
- const parts = trimmed.split(' = ');
165
- const name = parts[0].split(' ').pop();
166
- if (name && /^[A-Z]/.test(name)) {
167
- definitions.push(`Component: ${name}`); // React component guess
168
- }
169
- }
170
- }
171
-
172
- return definitions.slice(0, 5).join(', '); // Limit to top 5
173
- } catch (e) {
174
- return '';
175
- }
176
- }
177
-
178
- /**
179
- * Format the tree into a compressed string for the LLM
180
- */
181
- private formatTree(node: RepoNode, indent: string = ''): string {
182
- const name = path.basename(node.path);
183
- let output = `${indent}${name}`;
184
-
185
- if (node.type === 'file' && node.summary) {
186
- output += ` [${node.summary}]`;
187
- }
188
- output += '\n';
189
-
190
- if (node.children) {
191
- for (const child of node.children) {
192
- output += this.formatTree(child, indent + ' ');
193
- }
194
- }
195
-
196
- return output;
197
- }
198
- }
@@ -1,66 +0,0 @@
1
- import ora, { Ora } from 'ora';
2
- import chalk from 'chalk';
3
-
4
- export class Spinner {
5
- private spinner: Ora | null = null;
6
-
7
- /**
8
- * Start the premium MATEX loading spinner
9
- */
10
- start(text: string): void {
11
- this.spinner = ora({
12
- text: chalk.hex('#00fb08ff').bold(text),
13
- color: 'cyan',
14
- spinner: {
15
- interval: 80,
16
- frames: [
17
- '⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'
18
- ].map(f => chalk.cyan(f)) // Inject cyan into each frame
19
- },
20
- prefixText: chalk.bgHex('#1E1E1E').green(' ⚡ MATEX_SWARM_ACTIVE ') + ' ',
21
- }).start();
22
- }
23
-
24
- succeed(text?: string): void {
25
- if (this.spinner) {
26
- this.spinner.succeed(chalk.green('✓ ') + chalk.white.bold(text || 'Done'));
27
- this.spinner = null;
28
- }
29
- }
30
-
31
- fail(text?: string): void {
32
- if (this.spinner) {
33
- this.spinner.fail(chalk.red('✗ ') + chalk.white.bold(text || 'Failed'));
34
- this.spinner = null;
35
- }
36
- }
37
-
38
- warn(text?: string): void {
39
- if (this.spinner) {
40
- this.spinner.warn(chalk.yellow('⚠ ') + chalk.white(text || 'Warning'));
41
- this.spinner = null;
42
- }
43
- }
44
-
45
- info(text?: string): void {
46
- if (this.spinner) {
47
- this.spinner.info(chalk.blue('ℹ ') + chalk.white(text || 'Info'));
48
- this.spinner = null;
49
- }
50
- }
51
-
52
- stop(): void {
53
- if (this.spinner) {
54
- this.spinner.stop();
55
- this.spinner = null;
56
- }
57
- }
58
-
59
- updateText(text: string): void {
60
- if (this.spinner) {
61
- this.spinner.text = chalk.hex('#00fb08ff').bold(text);
62
- }
63
- }
64
- }
65
-
66
- export const spinner = new Spinner();