matex-cli 1.2.37 → 1.2.39
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/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +93 -165
- package/dist/commands/chat.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +89 -3
- package/dist/index.js.map +1 -1
- package/dist/utils/repo-mapper.d.ts +2 -0
- package/dist/utils/repo-mapper.d.ts.map +1 -1
- package/dist/utils/repo-mapper.js +6 -1
- package/dist/utils/repo-mapper.js.map +1 -1
- package/dist/utils/tui.js +4 -3
- package/dist/utils/tui.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/chat.ts +90 -175
- package/src/index.ts +92 -4
- package/src/utils/repo-mapper.ts +5 -1
- package/src/utils/tui.ts +3 -3
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { configManager } from './utils/config';
|
|
|
4
4
|
import { MatexAPIClient, ChatMessage } from './api/client';
|
|
5
5
|
import { spinner } from './utils/spinner';
|
|
6
6
|
import { devCommand } from './commands/dev';
|
|
7
|
+
import { chatCommand } from './commands/chat';
|
|
7
8
|
import { helpCommand } from './commands/help';
|
|
8
9
|
import { TUI } from './utils/tui';
|
|
9
10
|
|
|
@@ -18,6 +19,7 @@ program
|
|
|
18
19
|
|
|
19
20
|
// Add commands
|
|
20
21
|
program.addCommand(devCommand);
|
|
22
|
+
program.addCommand(chatCommand);
|
|
21
23
|
program.addCommand(helpCommand);
|
|
22
24
|
|
|
23
25
|
// Config commands
|
|
@@ -119,6 +121,12 @@ ${context}`
|
|
|
119
121
|
];
|
|
120
122
|
|
|
121
123
|
let fullResponse = '';
|
|
124
|
+
let buffer = '';
|
|
125
|
+
let technicalBuffer = '';
|
|
126
|
+
let technicalType: 'code' | 'file' | 'patch' | 'summary' | null = null;
|
|
127
|
+
let codeLang = 'bash';
|
|
128
|
+
let hasStarted = false;
|
|
129
|
+
|
|
122
130
|
const abortController = new AbortController();
|
|
123
131
|
let isAborted = false;
|
|
124
132
|
const streamStartTime = Date.now();
|
|
@@ -127,13 +135,12 @@ ${context}`
|
|
|
127
135
|
// 🏁 GRACE PERIOD: Ignore aborts in the first 200ms to prevent stray newlines
|
|
128
136
|
if (Date.now() - streamStartTime < 200) return;
|
|
129
137
|
|
|
130
|
-
if (!isAborted && (data
|
|
138
|
+
if (!isAborted && (data[0] === 13 || data[0] === 10 || data[0] === 27 || data[0] === 3)) {
|
|
131
139
|
isAborted = true;
|
|
132
140
|
abortController.abort();
|
|
133
141
|
}
|
|
134
142
|
};
|
|
135
143
|
|
|
136
|
-
|
|
137
144
|
const isRaw = process.stdin.isRaw;
|
|
138
145
|
process.stdin.resume();
|
|
139
146
|
if (process.stdin.setRawMode) process.stdin.setRawMode(true);
|
|
@@ -144,13 +151,94 @@ ${context}`
|
|
|
144
151
|
messages,
|
|
145
152
|
model: options.model,
|
|
146
153
|
}, (chunk) => {
|
|
147
|
-
|
|
148
|
-
|
|
154
|
+
if (!hasStarted) {
|
|
155
|
+
spinner.stop();
|
|
156
|
+
hasStarted = true;
|
|
157
|
+
}
|
|
149
158
|
fullResponse += chunk;
|
|
159
|
+
buffer += chunk;
|
|
160
|
+
|
|
161
|
+
const lines = buffer.split('\n');
|
|
162
|
+
buffer = lines.pop() || '';
|
|
163
|
+
|
|
164
|
+
for (const line of lines) {
|
|
165
|
+
// 1. Technical Block Detection
|
|
166
|
+
const codeBlockMatch = line.match(/```(\w+)?/);
|
|
167
|
+
const fileStartMatch = line.match(/<file path="([^"]+)">/);
|
|
168
|
+
const patchStartMatch = line.match(/<<<< SEARCH/);
|
|
169
|
+
const summaryStartMatch = line.match(/<summary>/);
|
|
170
|
+
|
|
171
|
+
if (!technicalType && (codeBlockMatch || fileStartMatch || patchStartMatch || summaryStartMatch)) {
|
|
172
|
+
if (codeBlockMatch) {
|
|
173
|
+
technicalType = 'code';
|
|
174
|
+
codeLang = codeBlockMatch[1] || 'bash';
|
|
175
|
+
process.stdout.write(chalk.gray('\n [⚡] Building technical block...\n'));
|
|
176
|
+
} else if (fileStartMatch) {
|
|
177
|
+
technicalType = 'file';
|
|
178
|
+
process.stdout.write(chalk.cyan(`\n [📂] Creating file: ${fileStartMatch[1]}...\n`));
|
|
179
|
+
} else if (patchStartMatch) {
|
|
180
|
+
technicalType = 'patch';
|
|
181
|
+
process.stdout.write(chalk.yellow('\n [📂] Applying surgical patch...\n'));
|
|
182
|
+
} else if (summaryStartMatch) {
|
|
183
|
+
technicalType = 'summary';
|
|
184
|
+
process.stdout.write(chalk.magenta('\n [📝] Generating Ajay\'s Work Summary...\n'));
|
|
185
|
+
}
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// 2. Technical Block End Detection
|
|
190
|
+
const fileEndMatch = line.match(/<\/file>/);
|
|
191
|
+
const patchEndMatch = line.match(/>>>> REPLACE/);
|
|
192
|
+
const summaryEndMatch = line.match(/<\/summary>/);
|
|
193
|
+
const isCodeEnd = technicalType === 'code' && line.trim() === '```';
|
|
194
|
+
|
|
195
|
+
if (isCodeEnd || fileEndMatch || patchEndMatch || summaryEndMatch) {
|
|
196
|
+
const displayContent = technicalBuffer.trim();
|
|
197
|
+
if (technicalType === 'summary') {
|
|
198
|
+
TUI.drawSummaryBox(displayContent);
|
|
199
|
+
} else {
|
|
200
|
+
TUI.drawCodeContainer(
|
|
201
|
+
technicalType === 'file' ? 'New File Content' :
|
|
202
|
+
technicalType === 'patch' ? 'Surgical Patch' : 'Generated Block',
|
|
203
|
+
technicalType === 'code' ? codeLang : 'text',
|
|
204
|
+
displayContent
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
technicalBuffer = '';
|
|
208
|
+
technicalType = null;
|
|
209
|
+
process.stdout.write('\n');
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 3. Content Handling
|
|
214
|
+
if (technicalType) {
|
|
215
|
+
technicalBuffer += line + '\n';
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Agent Detection & Dialogue Printing
|
|
220
|
+
const agentMatch = line.match(/(?:\[\**\s*|\b)(Ajay Vai|Sandip Dai|Sunil Dai|Bishal Dai|Narayan Dai)\s*\**\]?[:\s]*/i);
|
|
221
|
+
if (agentMatch) {
|
|
222
|
+
const agentName = agentMatch[1];
|
|
223
|
+
let content = line.replace(/(?:\[\**\s*|\b)(Ajay Vai|Sandip Dai|Sunil Dai|Bishal Dai|Narayan Dai)\s*\**\]?[:\s]*/i, '').trim();
|
|
224
|
+
content = content.replace(/\*{2,4}/g, '').trim();
|
|
225
|
+
|
|
226
|
+
if (agentName.toLowerCase() === 'ajay vai') {
|
|
227
|
+
const color = chalk.magenta;
|
|
228
|
+
process.stdout.write(`\n${color.bold(`[${agentName}]:`)} `);
|
|
229
|
+
if (content) process.stdout.write(chalk.gray(content + ' '));
|
|
230
|
+
} else {
|
|
231
|
+
if (content) TUI.drawSwarmDialogue(agentName, content);
|
|
232
|
+
}
|
|
233
|
+
} else if (line.trim()) {
|
|
234
|
+
process.stdout.write(chalk.gray(line.trim() + ' '));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
150
237
|
}, abortController.signal);
|
|
151
238
|
} catch (streamErr: any) {
|
|
152
239
|
if (isAborted || streamErr.name === 'CanceledError' || streamErr.message === 'canceled') {
|
|
153
240
|
console.log(chalk.gray('\n\n [🛑] Swarm stopped by brother (Enter pressed).'));
|
|
241
|
+
if (!hasStarted) spinner.stop();
|
|
154
242
|
} else {
|
|
155
243
|
throw streamErr;
|
|
156
244
|
}
|
package/src/utils/repo-mapper.ts
CHANGED
|
@@ -13,8 +13,11 @@ export class RepoMapper {
|
|
|
13
13
|
private rootPath: string;
|
|
14
14
|
private ignoreList: string[] = [
|
|
15
15
|
'.git', 'node_modules', 'dist', 'build', '.next', '.DS_Store',
|
|
16
|
-
'coverage', '.vercel', '.firebase', 'out', 'public'
|
|
16
|
+
'coverage', '.vercel', '.firebase', 'out', 'public',
|
|
17
|
+
'bin', 'obj', '.vs', 'vendor', '__pycache__', 'env', '.env', 'venv'
|
|
17
18
|
];
|
|
19
|
+
private fileCount = 0;
|
|
20
|
+
private readonly MAX_FILES = 500;
|
|
18
21
|
private fileContents: Map<string, string> = new Map();
|
|
19
22
|
|
|
20
23
|
constructor(rootPath: string) {
|
|
@@ -100,6 +103,7 @@ export class RepoMapper {
|
|
|
100
103
|
try {
|
|
101
104
|
const items = fs.readdirSync(currentPath);
|
|
102
105
|
for (const item of items) {
|
|
106
|
+
if (this.fileCount > this.MAX_FILES) break;
|
|
103
107
|
if (this.ignoreList.includes(item)) continue;
|
|
104
108
|
|
|
105
109
|
const fullPath = path.join(currentPath, item);
|
package/src/utils/tui.ts
CHANGED
|
@@ -80,10 +80,10 @@ export class TUI {
|
|
|
80
80
|
if (width <= 0 || height <= 0) return;
|
|
81
81
|
|
|
82
82
|
const leftTag = chalk.bgHex('#1E1E1E').hex('#D97757').bold(' ⚡ MATEX AI ');
|
|
83
|
-
const modelTag = chalk.bgHex('#333333').white(` 🤖
|
|
84
|
-
const cwdTag = chalk.bgHex('#1E1E1E').gray(` 📂
|
|
83
|
+
const modelTag = chalk.bgHex('#333333').white(` 🤖 ${model} `);
|
|
84
|
+
const cwdTag = chalk.bgHex('#1E1E1E').gray(` 📂 ${path.basename(process.cwd())} `);
|
|
85
85
|
|
|
86
|
-
const mainMessage = chalk.bgHex('#1E1E1E').white(`
|
|
86
|
+
const mainMessage = chalk.bgHex('#1E1E1E').white(` ${message} `);
|
|
87
87
|
const remainingWidth = width - (12 + modelTag.length + cwdTag.length + mainMessage.length);
|
|
88
88
|
const spacer = chalk.bgHex('#1E1E1E')(' '.repeat(Math.max(0, remainingWidth)));
|
|
89
89
|
|