matex-cli 1.2.3 ā 1.2.5
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/api/client.d.ts +5 -1
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +56 -1
- package/dist/api/client.js.map +1 -1
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +66 -48
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +63 -55
- package/dist/commands/dev.js.map +1 -1
- package/dist/utils/agent-orchestrator.d.ts +9 -1
- package/dist/utils/agent-orchestrator.d.ts.map +1 -1
- package/dist/utils/agent-orchestrator.js +51 -3
- package/dist/utils/agent-orchestrator.js.map +1 -1
- package/dist/utils/command-executor.d.ts.map +1 -1
- package/dist/utils/command-executor.js +7 -9
- package/dist/utils/command-executor.js.map +1 -1
- package/dist/utils/repo-mapper.d.ts +1 -0
- package/dist/utils/repo-mapper.d.ts.map +1 -1
- package/dist/utils/repo-mapper.js +28 -15
- package/dist/utils/repo-mapper.js.map +1 -1
- package/package.json +1 -1
- package/src/api/client.ts +60 -1
- package/src/commands/chat.ts +72 -45
- package/src/commands/dev.ts +69 -55
- package/src/utils/agent-orchestrator.ts +60 -4
- package/src/utils/command-executor.ts +7 -11
- package/src/utils/repo-mapper.ts +32 -15
package/src/commands/dev.ts
CHANGED
|
@@ -48,13 +48,15 @@ You operate as a high-fidelity engineering swarm with an Aussie Bro persona.
|
|
|
48
48
|
### š§ CORE PERSONA: RESEARCH COMMANDER
|
|
49
49
|
- **Vibe:** Aussie expert developer. "Too easy," "Ripper," "Mate."
|
|
50
50
|
- **Duty:** Verify all facts before building.
|
|
51
|
+
- **THINKING PROTOCOL:** Always start complex tasks with a \`[Thinking]\` or \`š§ \` marker within your agent segment to explain your reasoning before providing code.
|
|
51
52
|
|
|
52
53
|
### š ļø ACTION-FIRST PROTOCOL (Rule of the Swarm)
|
|
53
54
|
- **PASSIVITY IS A FAILURE:** NEVER say "You can drop this code into style.css". **YOU** must do it.
|
|
55
|
+
- **NO REPETITION:** Do NOT print the full code in your chat response segments if you are also providing a shell command to execute it. The system will automatically bridge your commands to the UI.
|
|
54
56
|
- **WORLD COMMAND SUITE (Autonomous Execution):**
|
|
55
57
|
* **Mac/Linux (POSIX):** cat, ls, grep, find, mkdir -p, touch, cp, mv, npm, git, firebase.
|
|
56
58
|
* **Windows (PowerShell/CMD):** type, dir, mkdir, copy, move, del, npm, git, firebase.
|
|
57
|
-
- **PROACTIVE EXECUTION:** If a task requires creating or modifying a file, you **MUST** use a shell command block (e.g.,
|
|
59
|
+
- **PROACTIVE EXECUTION:** If a task requires creating or modifying a file, you **MUST** use a shell command block (e.g., \`cat > filename <<EOF\` or PowerShell \`Set-Content\`).
|
|
58
60
|
- **ACT, DON'T ASK:** You have autonomous permission for the suite above.
|
|
59
61
|
|
|
60
62
|
### 𧬠CODE ARCHITECT STANDARDS
|
|
@@ -71,9 +73,7 @@ ${repoMap}`
|
|
|
71
73
|
console.log(chalk.gray('State your request to begin...'));
|
|
72
74
|
|
|
73
75
|
// Interactive loop
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
while (continueChat) {
|
|
76
|
+
while (true) {
|
|
77
77
|
// Get user input
|
|
78
78
|
const { userInput } = await inquirer.prompt([
|
|
79
79
|
{
|
|
@@ -98,11 +98,9 @@ ${repoMap}`
|
|
|
98
98
|
// Add user message to history
|
|
99
99
|
messages.push({ role: 'user', content: userInput });
|
|
100
100
|
|
|
101
|
-
// Show thinking indicator
|
|
102
101
|
// Agentic Loop
|
|
103
102
|
let loopCount = 0;
|
|
104
103
|
const MAX_LOOPS = 10;
|
|
105
|
-
let currentPrompt = userInput;
|
|
106
104
|
|
|
107
105
|
while (loopCount < MAX_LOOPS) {
|
|
108
106
|
loopCount++;
|
|
@@ -114,64 +112,85 @@ ${repoMap}`
|
|
|
114
112
|
}
|
|
115
113
|
|
|
116
114
|
try {
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
let fullResponse = '';
|
|
116
|
+
let buffer = '';
|
|
117
|
+
let hasStarted = false;
|
|
118
|
+
let inCodeBlock = false;
|
|
119
|
+
let codeLanguage = '';
|
|
120
|
+
|
|
121
|
+
await client.chatStream({
|
|
119
122
|
messages,
|
|
120
123
|
model: options.model,
|
|
121
124
|
temperature: 0.3,
|
|
122
125
|
max_tokens: 8000,
|
|
123
|
-
|
|
126
|
+
}, (chunk) => {
|
|
127
|
+
if (!hasStarted) {
|
|
128
|
+
spinner.stop();
|
|
129
|
+
hasStarted = true;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
buffer += chunk;
|
|
133
|
+
fullResponse += chunk;
|
|
134
|
+
|
|
135
|
+
// Process buffer line by line or segment by segment
|
|
136
|
+
const lines = buffer.split('\n');
|
|
137
|
+
if (lines.length > 1) {
|
|
138
|
+
buffer = lines.pop() || ''; // Keep the last incomplete line
|
|
139
|
+
|
|
140
|
+
for (const line of lines) {
|
|
141
|
+
const trimmed = line.trim();
|
|
142
|
+
|
|
143
|
+
// Code block detection
|
|
144
|
+
if (trimmed.startsWith('```')) {
|
|
145
|
+
if (!inCodeBlock) {
|
|
146
|
+
inCodeBlock = true;
|
|
147
|
+
codeLanguage = trimmed.substring(3).toLowerCase();
|
|
148
|
+
if (options.execute && ['bash', 'sh', 'zsh', 'powershell', 'cmd'].includes(codeLanguage)) {
|
|
149
|
+
console.log(chalk.gray('\n[Running Shell Command in Terminal Block...]'));
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
inCodeBlock = false;
|
|
153
|
+
}
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Agent Tag detection
|
|
158
|
+
const agentMatch = trimmed.match(/^\[(MatexCodeArchitect|SyntaxGuard|VisualAgent|CoreAgent|CrawlerAgent|DetailedResearch|MatexResearchCommander)\]$/);
|
|
159
|
+
if (agentMatch) {
|
|
160
|
+
console.log(`\n${chalk.bold.cyan(trimmed)}`);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Normal text output (if not in a hidden code block)
|
|
165
|
+
if (!inCodeBlock) {
|
|
166
|
+
if (trimmed) console.log(chalk.gray(trimmed));
|
|
167
|
+
} else if (!options.execute) {
|
|
168
|
+
// If not executing, show the code anyway
|
|
169
|
+
console.log(chalk.blue(line));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
124
173
|
});
|
|
125
174
|
|
|
126
175
|
spinner.stop();
|
|
127
176
|
|
|
128
|
-
//
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
// Enhanced Multi-Agent Display (Updated for Vertex AI ADK)
|
|
132
|
-
const segments = response.split(/(\[MatexCodeArchitect\]|\[SyntaxGuard\]|\[VisualAgent\]|\[CoreAgent\]|\[CrawlerAgent\]|\[DetailedResearch\]|\[MatexResearchCommander\])/);
|
|
133
|
-
let hasAgents = false;
|
|
134
|
-
|
|
135
|
-
for (let i = 0; i < segments.length; i++) {
|
|
136
|
-
const segment = segments[i].trim();
|
|
137
|
-
if (!segment) continue;
|
|
138
|
-
|
|
139
|
-
if (segment === '[MatexCodeArchitect]') {
|
|
140
|
-
AgentOrchestrator.speak('Architect', segments[++i]?.split('[')[0].trim());
|
|
141
|
-
hasAgents = true;
|
|
142
|
-
} else if (segment === '[SyntaxGuard]') {
|
|
143
|
-
AgentOrchestrator.speak('Syntax', segments[++i]?.split('[')[0].trim());
|
|
144
|
-
hasAgents = true;
|
|
145
|
-
} else if (segment === '[VisualAgent]') {
|
|
146
|
-
AgentOrchestrator.speak('Frontend', segments[++i]?.split('[')[0].trim());
|
|
147
|
-
hasAgents = true;
|
|
148
|
-
} else if (segment === '[CoreAgent]') {
|
|
149
|
-
AgentOrchestrator.speak('Backend', segments[++i]?.split('[')[0].trim());
|
|
150
|
-
hasAgents = true;
|
|
151
|
-
} else if (segment === '[MatexResearchCommander]' || segment === '[CrawlerAgent]' || segment === '[DetailedResearch]') {
|
|
152
|
-
AgentOrchestrator.speak('Commander', segments[++i]?.split('[')[0].trim());
|
|
153
|
-
hasAgents = true;
|
|
154
|
-
} else if (!hasAgents || i === segments.length - 1) {
|
|
155
|
-
// Final summary or fallback
|
|
156
|
-
if (segment.includes('`')) {
|
|
157
|
-
console.log('\n' + chalk.white(segment));
|
|
158
|
-
} else {
|
|
159
|
-
console.log('\n' + chalk.gray(segment));
|
|
160
|
-
}
|
|
161
|
-
}
|
|
177
|
+
// Final flush
|
|
178
|
+
if (buffer.trim() && !inCodeBlock) {
|
|
179
|
+
console.log(chalk.gray(buffer.trim()));
|
|
162
180
|
}
|
|
181
|
+
|
|
182
|
+
// Add assistant response to history
|
|
183
|
+
messages.push({ role: 'assistant', content: fullResponse });
|
|
184
|
+
const response = fullResponse;
|
|
163
185
|
console.log();
|
|
164
186
|
|
|
165
|
-
// Execute commands
|
|
166
|
-
// User asked for "seamless", but prompt still asks permission.
|
|
167
|
-
// We'll keep permission for safety but loop on failure.)
|
|
187
|
+
// Execute commands
|
|
168
188
|
if (options.execute) {
|
|
169
189
|
const { executeWithPermission } = await import('../utils/command-executor');
|
|
170
190
|
const result = await executeWithPermission(response);
|
|
171
191
|
|
|
172
192
|
if (result.executed) {
|
|
173
193
|
if (result.success) {
|
|
174
|
-
// Success! Feed output back to AI for next step
|
|
175
194
|
console.log(chalk.gray('āŗ Feeding output to AI...'));
|
|
176
195
|
messages.push({
|
|
177
196
|
role: 'user',
|
|
@@ -179,32 +198,27 @@ ${repoMap}`
|
|
|
179
198
|
});
|
|
180
199
|
continue;
|
|
181
200
|
} else {
|
|
182
|
-
// Failure - Loop back
|
|
183
201
|
console.log(chalk.yellow('\nāŗ Command failed. Asking AI to fix...'));
|
|
184
|
-
|
|
185
|
-
// Add error to history
|
|
186
202
|
messages.push({
|
|
187
203
|
role: 'user',
|
|
188
204
|
content: `ā Command failed with error:\n${result.error}\n\nPlease fix this. If the file doesn't exist, create it first. Or use a different command.`
|
|
189
205
|
});
|
|
190
|
-
// Continue loop
|
|
191
206
|
continue;
|
|
192
207
|
}
|
|
193
208
|
} else {
|
|
194
|
-
break;
|
|
209
|
+
break;
|
|
195
210
|
}
|
|
196
211
|
} else {
|
|
197
|
-
break;
|
|
212
|
+
break;
|
|
198
213
|
}
|
|
199
214
|
} catch (error: any) {
|
|
200
215
|
spinner.fail('Request failed');
|
|
201
216
|
console.error(chalk.red(`Error: ${error.message}\n`));
|
|
202
|
-
messages.pop();
|
|
217
|
+
messages.pop();
|
|
203
218
|
break;
|
|
204
219
|
}
|
|
205
220
|
}
|
|
206
221
|
}
|
|
207
|
-
|
|
208
222
|
} catch (error: any) {
|
|
209
223
|
console.error(chalk.red(`\nā Error: ${error.message}`));
|
|
210
224
|
process.exit(1);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
|
|
3
|
-
export type AgentRole = 'Architect' | 'Syntax' | 'Frontend' | 'Backend' | 'System' | 'Commander';
|
|
3
|
+
export type AgentRole = 'Architect' | 'Syntax' | 'Frontend' | 'Backend' | 'System' | 'Commander' | 'Researcher';
|
|
4
4
|
|
|
5
5
|
export interface AgentConfig {
|
|
6
6
|
name: string;
|
|
@@ -38,6 +38,11 @@ const AGENT_CONFIGS: Record<AgentRole, AgentConfig> = {
|
|
|
38
38
|
name: 'MatexResearchCommander',
|
|
39
39
|
icon: 'š',
|
|
40
40
|
color: chalk.green,
|
|
41
|
+
},
|
|
42
|
+
Researcher: {
|
|
43
|
+
name: 'DetailedResearch',
|
|
44
|
+
icon: 'šµļø',
|
|
45
|
+
color: chalk.green,
|
|
41
46
|
}
|
|
42
47
|
};
|
|
43
48
|
|
|
@@ -46,19 +51,70 @@ export class AgentOrchestrator {
|
|
|
46
51
|
* Display an agent's "thought" or action
|
|
47
52
|
*/
|
|
48
53
|
static speak(role: AgentRole, message: string) {
|
|
49
|
-
const config = AGENT_CONFIGS[role];
|
|
54
|
+
const config = AGENT_CONFIGS[role] || AGENT_CONFIGS.System;
|
|
50
55
|
console.log(`\n${config.icon} ${config.color(`${config.name}:`)} ${chalk.white(message)}`);
|
|
51
56
|
}
|
|
52
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Display an agent's internal deliberation (Thinking Channel)
|
|
60
|
+
*/
|
|
61
|
+
static think(role: AgentRole, thought: string) {
|
|
62
|
+
const config = AGENT_CONFIGS[role] || AGENT_CONFIGS.System;
|
|
63
|
+
const indent = ' ';
|
|
64
|
+
console.log(`${indent}${config.color('š§ ')} ${chalk.gray(`${config.name} thinking:`)} ${chalk.italic.gray(`"${thought}"`)}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
53
67
|
/**
|
|
54
68
|
* Display a collaboration transition
|
|
55
69
|
*/
|
|
56
70
|
static transition(from: AgentRole, to: AgentRole) {
|
|
57
|
-
const fromCfg = AGENT_CONFIGS[from];
|
|
58
|
-
const toCfg = AGENT_CONFIGS[to];
|
|
71
|
+
const fromCfg = AGENT_CONFIGS[from] || AGENT_CONFIGS.System;
|
|
72
|
+
const toCfg = AGENT_CONFIGS[to] || AGENT_CONFIGS.System;
|
|
59
73
|
console.log(chalk.gray(` āā ${fromCfg.icon} ā ${toCfg.icon} Handover to ${toCfg.name}...`));
|
|
60
74
|
}
|
|
61
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Display a boxed terminal for command execution
|
|
78
|
+
*/
|
|
79
|
+
static terminal(command: string, output?: string, error?: string) {
|
|
80
|
+
const width = 75;
|
|
81
|
+
const line = 'ā'.repeat(width);
|
|
82
|
+
|
|
83
|
+
console.log(chalk.gray(`\nāāā TERMINAL ${line.substring(13)}ā`));
|
|
84
|
+
|
|
85
|
+
// Command
|
|
86
|
+
const lines = command.split('\n');
|
|
87
|
+
lines.forEach(l => {
|
|
88
|
+
const truncated = l.length > width - 4 ? l.substring(0, width - 7) + '...' : l;
|
|
89
|
+
console.log(chalk.gray('ā ') + chalk.cyan(`$ ${truncated.padEnd(width - 2)}`) + chalk.gray(' ā'));
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (output || error) {
|
|
93
|
+
console.log(chalk.gray(`ā${'ā'.repeat(width)}ā¤`));
|
|
94
|
+
|
|
95
|
+
if (output) {
|
|
96
|
+
const outLines = output.split('\n').filter(l => l.trim()).slice(0, 15);
|
|
97
|
+
outLines.forEach(l => {
|
|
98
|
+
const truncated = l.length > width - 4 ? l.substring(0, width - 7) + '...' : l;
|
|
99
|
+
console.log(chalk.gray('ā ') + chalk.white(truncated.padEnd(width - 2)) + chalk.gray(' ā'));
|
|
100
|
+
});
|
|
101
|
+
if (output.split('\n').filter(l => l.trim()).length > 15) {
|
|
102
|
+
console.log(chalk.gray('ā ') + chalk.gray('... (output truncated for brevity)'.padEnd(width - 2)) + chalk.gray(' ā'));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (error) {
|
|
107
|
+
const errLines = error.split('\n').filter(l => l.trim()).slice(0, 10);
|
|
108
|
+
errLines.forEach(l => {
|
|
109
|
+
const truncated = l.length > width - 4 ? l.substring(0, width - 7) + '...' : l;
|
|
110
|
+
console.log(chalk.gray('ā ') + chalk.red(truncated.padEnd(width - 2)) + chalk.gray(' ā'));
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
console.log(chalk.gray(`ā${'ā'.repeat(width)}ā\n`));
|
|
116
|
+
}
|
|
117
|
+
|
|
62
118
|
/**
|
|
63
119
|
* Clean system message
|
|
64
120
|
*/
|
|
@@ -2,6 +2,7 @@ import chalk from 'chalk';
|
|
|
2
2
|
import { exec } from 'child_process';
|
|
3
3
|
import { promisify } from 'util';
|
|
4
4
|
import inquirer from 'inquirer';
|
|
5
|
+
import { AgentOrchestrator } from './agent-orchestrator';
|
|
5
6
|
|
|
6
7
|
const execAsync = promisify(exec);
|
|
7
8
|
|
|
@@ -172,20 +173,15 @@ export async function executeWithPermission(response: string): Promise<Execution
|
|
|
172
173
|
// Minimal execution feedback
|
|
173
174
|
const { stdout, stderr } = await executeCommand(command.code);
|
|
174
175
|
|
|
175
|
-
if (stdout) {
|
|
176
|
-
|
|
177
|
-
|
|
176
|
+
if (stdout || stderr) {
|
|
177
|
+
AgentOrchestrator.terminal(command.code, stdout, stderr);
|
|
178
|
+
} else {
|
|
179
|
+
AgentOrchestrator.terminal(command.code, 'ā Success (No output)');
|
|
178
180
|
}
|
|
179
181
|
|
|
180
|
-
|
|
181
|
-
console.log(chalk.yellow('\nā ļø Warnings:'));
|
|
182
|
-
console.log(chalk.white(stderr));
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
console.log(chalk.green('ā Command completed successfully!\n'));
|
|
186
|
-
return { success: true, executed: true, output: stdout, error: stderr }; // Return first successful result (or last if multiple?) limits to 1 for now or we need array
|
|
182
|
+
return { success: true, executed: true, output: stdout, error: stderr };
|
|
187
183
|
} catch (error: any) {
|
|
188
|
-
|
|
184
|
+
AgentOrchestrator.terminal(command.code, undefined, error.message);
|
|
189
185
|
return { success: false, executed: true, error: error.message };
|
|
190
186
|
}
|
|
191
187
|
} else {
|
package/src/utils/repo-mapper.ts
CHANGED
|
@@ -15,6 +15,7 @@ export class RepoMapper {
|
|
|
15
15
|
'.git', 'node_modules', 'dist', 'build', '.next', '.DS_Store',
|
|
16
16
|
'coverage', '.vercel', '.firebase', 'out', 'public'
|
|
17
17
|
];
|
|
18
|
+
private fileContents: Map<string, string> = new Map();
|
|
18
19
|
|
|
19
20
|
constructor(rootPath: string) {
|
|
20
21
|
this.rootPath = rootPath;
|
|
@@ -26,20 +27,34 @@ export class RepoMapper {
|
|
|
26
27
|
public async generateMap(): Promise<string> {
|
|
27
28
|
AgentOrchestrator.speak('System', `God-Mode Research: Indexing ${this.rootPath}...`);
|
|
28
29
|
|
|
30
|
+
this.fileContents.clear();
|
|
31
|
+
|
|
29
32
|
// 1. Identify Entry Points
|
|
30
|
-
const entryPoints = ['README.md', 'package.json', 'index.ts', 'App.tsx', 'main.go', 'requirements.txt'];
|
|
31
|
-
let entryPointContext = '\n--- CRITICAL PROJECT CONTEXT ---\n';
|
|
33
|
+
const entryPoints = ['README.md', 'package.json', 'index.ts', 'App.tsx', 'main.go', 'requirements.txt', 'index.html', 'style.css'];
|
|
32
34
|
|
|
33
35
|
for (const file of entryPoints) {
|
|
34
36
|
const fullPath = path.join(this.rootPath, file);
|
|
35
37
|
if (fs.existsSync(fullPath)) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
try {
|
|
39
|
+
const content = fs.readFileSync(fullPath, 'utf-8').slice(0, 5000); // 5KB limit
|
|
40
|
+
this.fileContents.set(file, content);
|
|
41
|
+
} catch (e) { }
|
|
38
42
|
}
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
const tree = this.scanDirectory(this.rootPath, 0);
|
|
42
|
-
|
|
46
|
+
|
|
47
|
+
// Build the final map
|
|
48
|
+
let finalMap = '--- DIRECTORY STRUCTURE ---\n' + this.formatTree(tree);
|
|
49
|
+
|
|
50
|
+
if (this.fileContents.size > 0) {
|
|
51
|
+
finalMap += '\n\n--- CRAWLED FILE CONTENTS ---\n';
|
|
52
|
+
for (const [filePath, content] of this.fileContents) {
|
|
53
|
+
finalMap += `\nFILE: ${filePath}\n\`\`\`\n${content}\n\`\`\`\n----------------\n`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return finalMap;
|
|
43
58
|
}
|
|
44
59
|
|
|
45
60
|
/**
|
|
@@ -50,16 +65,18 @@ export class RepoMapper {
|
|
|
50
65
|
const name = path.basename(currentPath);
|
|
51
66
|
|
|
52
67
|
if (stats.isFile()) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
68
|
+
const summary = this.extractSummary(currentPath);
|
|
69
|
+
|
|
70
|
+
// Also auto-crawl any .ts, .js, .css, .html files if they are small
|
|
71
|
+
const ext = path.extname(currentPath);
|
|
72
|
+
const relPath = path.relative(this.rootPath, currentPath);
|
|
73
|
+
|
|
74
|
+
if (stats.size < 5120 && ['.ts', '.js', '.css', '.html', '.json', '.py'].includes(ext)) {
|
|
75
|
+
if (!this.fileContents.has(relPath)) {
|
|
76
|
+
try {
|
|
77
|
+
const content = fs.readFileSync(currentPath, 'utf-8');
|
|
78
|
+
this.fileContents.set(relPath, content);
|
|
79
|
+
} catch (e) { }
|
|
63
80
|
}
|
|
64
81
|
}
|
|
65
82
|
|