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.
- package/dist/commands/chaos.js +3 -8
- package/dist/prompts/chaos-prompts.js +26 -21
- package/dist/session/agent-session.js +38 -9
- package/dist/utils/agent-orchestrator.js +7 -0
- package/dist/utils/mcp-server.js +6 -0
- package/dist/utils/tui.js +84 -7
- package/package.json +7 -1
- package/.agents/skills/mcp-server-dev/SKILL.md +0 -60
- package/.agents/skills/mcp-server-dev/examples/basic-ts-server/package.json +0 -20
- package/.agents/skills/mcp-server-dev/examples/basic-ts-server/src/index.ts +0 -66
- package/.agents/skills/mcp-server-dev/resources/best_practices.md +0 -20
- package/.agents/skills/pptx-presentation-builder/SKILL.md +0 -338
- package/.agents/workflows/deploy.md +0 -27
- package/dist/api/client.d.ts +0 -40
- package/dist/api/client.d.ts.map +0 -1
- package/dist/api/client.js.map +0 -1
- package/dist/commands/ask.d.ts +0 -3
- package/dist/commands/ask.d.ts.map +0 -1
- package/dist/commands/ask.js.map +0 -1
- package/dist/commands/augov.d.ts +0 -3
- package/dist/commands/augov.d.ts.map +0 -1
- package/dist/commands/augov.js.map +0 -1
- package/dist/commands/bro.d.ts +0 -4
- package/dist/commands/bro.d.ts.map +0 -1
- package/dist/commands/bro.js.map +0 -1
- package/dist/commands/chaos.d.ts +0 -3
- package/dist/commands/chaos.d.ts.map +0 -1
- package/dist/commands/chaos.js.map +0 -1
- package/dist/commands/chat.d.ts +0 -3
- package/dist/commands/chat.d.ts.map +0 -1
- package/dist/commands/chat.js.map +0 -1
- package/dist/commands/code.d.ts +0 -3
- package/dist/commands/code.d.ts.map +0 -1
- package/dist/commands/code.js.map +0 -1
- package/dist/commands/config.d.ts +0 -3
- package/dist/commands/config.d.ts.map +0 -1
- package/dist/commands/config.js.map +0 -1
- package/dist/commands/dev.d.ts +0 -3
- package/dist/commands/dev.d.ts.map +0 -1
- package/dist/commands/dev.js.map +0 -1
- package/dist/commands/help.d.ts +0 -3
- package/dist/commands/help.d.ts.map +0 -1
- package/dist/commands/help.js.map +0 -1
- package/dist/commands/login.d.ts +0 -3
- package/dist/commands/login.d.ts.map +0 -1
- package/dist/commands/login.js.map +0 -1
- package/dist/commands/models.d.ts +0 -3
- package/dist/commands/models.d.ts.map +0 -1
- package/dist/commands/models.js.map +0 -1
- package/dist/commands/student.d.ts +0 -3
- package/dist/commands/student.d.ts.map +0 -1
- package/dist/commands/student.js.map +0 -1
- package/dist/commands/study.d.ts +0 -3
- package/dist/commands/study.d.ts.map +0 -1
- package/dist/commands/study.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/prompts/banter-augov.d.ts +0 -2
- package/dist/prompts/banter-augov.d.ts.map +0 -1
- package/dist/prompts/banter-augov.js.map +0 -1
- package/dist/prompts/banter.d.ts +0 -6
- package/dist/prompts/banter.d.ts.map +0 -1
- package/dist/prompts/banter.js.map +0 -1
- package/dist/prompts/chaos-prompts.d.ts +0 -3
- package/dist/prompts/chaos-prompts.d.ts.map +0 -1
- package/dist/prompts/chaos-prompts.js.map +0 -1
- package/dist/prompts/system-prompts.d.ts +0 -4
- package/dist/prompts/system-prompts.d.ts.map +0 -1
- package/dist/prompts/system-prompts.js.map +0 -1
- package/dist/session/agent-session.d.ts +0 -41
- package/dist/session/agent-session.d.ts.map +0 -1
- package/dist/session/agent-session.js.map +0 -1
- package/dist/utils/agent-orchestrator.d.ts +0 -44
- package/dist/utils/agent-orchestrator.d.ts.map +0 -1
- package/dist/utils/agent-orchestrator.js.map +0 -1
- package/dist/utils/augov-logger.d.ts +0 -11
- package/dist/utils/augov-logger.d.ts.map +0 -1
- package/dist/utils/augov-logger.js.map +0 -1
- package/dist/utils/augov-scrubber.d.ts +0 -23
- package/dist/utils/augov-scrubber.d.ts.map +0 -1
- package/dist/utils/augov-scrubber.js.map +0 -1
- package/dist/utils/command-executor.d.ts +0 -56
- package/dist/utils/command-executor.d.ts.map +0 -1
- package/dist/utils/command-executor.js.map +0 -1
- package/dist/utils/config.d.ts +0 -56
- package/dist/utils/config.d.ts.map +0 -1
- package/dist/utils/config.js.map +0 -1
- package/dist/utils/mcp-server.d.ts +0 -77
- package/dist/utils/mcp-server.d.ts.map +0 -1
- package/dist/utils/mcp-server.js.map +0 -1
- package/dist/utils/patcher.d.ts +0 -45
- package/dist/utils/patcher.d.ts.map +0 -1
- package/dist/utils/patcher.js.map +0 -1
- package/dist/utils/repo-mapper.d.ts +0 -32
- package/dist/utils/repo-mapper.d.ts.map +0 -1
- package/dist/utils/repo-mapper.js.map +0 -1
- package/dist/utils/spinner.d.ts +0 -15
- package/dist/utils/spinner.d.ts.map +0 -1
- package/dist/utils/spinner.js.map +0 -1
- package/dist/utils/tui.d.ts +0 -134
- package/dist/utils/tui.d.ts.map +0 -1
- package/dist/utils/tui.js.map +0 -1
- package/fix-npm-permissions.sh +0 -23
- package/publish-local.sh +0 -16
- package/skills-lock.json +0 -10
- package/src/api/client.ts +0 -197
- package/src/commands/ask.ts +0 -62
- package/src/commands/augov.ts +0 -301
- package/src/commands/bro.ts +0 -336
- package/src/commands/chaos.ts +0 -67
- package/src/commands/chat.ts +0 -61
- package/src/commands/code.ts +0 -99
- package/src/commands/config.ts +0 -78
- package/src/commands/dev.ts +0 -68
- package/src/commands/help.ts +0 -67
- package/src/commands/login.ts +0 -47
- package/src/commands/models.ts +0 -81
- package/src/commands/student.ts +0 -23
- package/src/commands/study.ts +0 -75
- package/src/index.ts +0 -284
- package/src/prompts/banter-augov.ts +0 -17
- package/src/prompts/banter.ts +0 -101
- package/src/prompts/chaos-prompts.ts +0 -48
- package/src/prompts/system-prompts.ts +0 -145
- package/src/session/agent-session.ts +0 -428
- package/src/utils/agent-orchestrator.ts +0 -264
- package/src/utils/augov-logger.ts +0 -34
- package/src/utils/augov-scrubber.ts +0 -67
- package/src/utils/command-executor.ts +0 -529
- package/src/utils/config.ts +0 -124
- package/src/utils/mcp-server.ts +0 -388
- package/src/utils/patcher.ts +0 -229
- package/src/utils/repo-mapper.ts +0 -198
- package/src/utils/spinner.ts +0 -66
- package/src/utils/tui.ts +0 -749
- package/test-chaos-container.js +0 -16
- package/test-chaos-fix.js +0 -18
- package/test-config.ts +0 -2
- package/test-ui-output.js +0 -16
- package/tsconfig.json +0 -27
- package/vertex_ai_agent.py +0 -52
package/src/utils/patcher.ts
DELETED
|
@@ -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
|
-
}
|
package/src/utils/repo-mapper.ts
DELETED
|
@@ -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
|
-
}
|
package/src/utils/spinner.ts
DELETED
|
@@ -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();
|