matex-cli 1.2.84 → 1.2.88
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/index.js +559 -288
- package/package.json +8 -7
- package/dist/api/client.js +0 -173
- package/dist/commands/ask.js +0 -63
- package/dist/commands/augov.js +0 -273
- package/dist/commands/bro.js +0 -304
- package/dist/commands/chaos.js +0 -58
- package/dist/commands/chat.js +0 -59
- package/dist/commands/code.js +0 -94
- package/dist/commands/config.js +0 -74
- package/dist/commands/dev.js +0 -66
- package/dist/commands/help.js +0 -50
- package/dist/commands/login.js +0 -47
- package/dist/commands/models.js +0 -77
- package/dist/commands/student.js +0 -28
- package/dist/commands/study.js +0 -72
- package/dist/prompts/banter-augov.js +0 -21
- package/dist/prompts/banter.js +0 -101
- package/dist/prompts/chaos-prompts.js +0 -57
- package/dist/prompts/system-prompts.js +0 -148
- package/dist/session/agent-session.js +0 -450
- package/dist/utils/agent-orchestrator.js +0 -251
- package/dist/utils/augov-logger.js +0 -35
- package/dist/utils/augov-scrubber.js +0 -68
- package/dist/utils/command-executor.js +0 -507
- package/dist/utils/config.js +0 -139
- package/dist/utils/mcp-server.js +0 -396
- package/dist/utils/patcher.js +0 -202
- package/dist/utils/repo-mapper.js +0 -214
- package/dist/utils/spinner.js +0 -67
- package/dist/utils/tui.js +0 -779
|
@@ -1,507 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.commandHistory = exports.CommandHistory = void 0;
|
|
40
|
-
exports.extractCommands = extractCommands;
|
|
41
|
-
exports.isSafeAutoCommand = isSafeAutoCommand;
|
|
42
|
-
exports.askPermission = askPermission;
|
|
43
|
-
exports.executeCommand = executeCommand;
|
|
44
|
-
exports.executeWithPermission = executeWithPermission;
|
|
45
|
-
const fs = __importStar(require("fs"));
|
|
46
|
-
const path = __importStar(require("path"));
|
|
47
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
48
|
-
const child_process_1 = require("child_process");
|
|
49
|
-
const util_1 = require("util");
|
|
50
|
-
const inquirer_1 = __importDefault(require("inquirer"));
|
|
51
|
-
const tui_1 = require("./tui");
|
|
52
|
-
const agent_orchestrator_1 = require("./agent-orchestrator");
|
|
53
|
-
const patcher_1 = require("./patcher");
|
|
54
|
-
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
55
|
-
/**
|
|
56
|
-
* Extract executable commands from AI response
|
|
57
|
-
*/
|
|
58
|
-
function extractCommands(response) {
|
|
59
|
-
const commands = [];
|
|
60
|
-
// Match code blocks with language tags (case-insensitive)
|
|
61
|
-
const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/gi;
|
|
62
|
-
let match;
|
|
63
|
-
while ((match = codeBlockRegex.exec(response)) !== null) {
|
|
64
|
-
const language = match[1] || 'bash';
|
|
65
|
-
const code = match[2].trim();
|
|
66
|
-
// 🛡️ HEURISTIC: Reject directory trees formatted as "commands"
|
|
67
|
-
const isTree = /├──|└──|│\s+├──/.test(code);
|
|
68
|
-
if (isTree)
|
|
69
|
-
continue;
|
|
70
|
-
// Only extract shell commands
|
|
71
|
-
if (['bash', 'sh', 'zsh', 'shell', 'powershell', 'cmd'].includes(language.toLowerCase())) {
|
|
72
|
-
// 🛡️ DIALOGUE FILTER: Strip lines that look like agent banter [Ajay Vai]: etc.
|
|
73
|
-
const lines = code.split('\n');
|
|
74
|
-
const filteredLines = lines.filter(line => {
|
|
75
|
-
const trimmed = line.trim();
|
|
76
|
-
// If it starts with [Agent Name] or typical agent markers, it's NOT a command
|
|
77
|
-
const isAgent = /^(?:\[\**\s*|\b)(Ajay|Sunil|Sandip|Bishal|Narayan|Big Bro)\s*(?:Vai|Dai)?\s*\**\]?[:\s]*/i.test(trimmed);
|
|
78
|
-
return !isAgent;
|
|
79
|
-
});
|
|
80
|
-
const filteredCode = filteredLines.join('\n').trim();
|
|
81
|
-
if (filteredCode) {
|
|
82
|
-
commands.push({
|
|
83
|
-
language,
|
|
84
|
-
code: filteredCode,
|
|
85
|
-
dangerous: isDangerousCommand(filteredCode)
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return commands;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Check if command is potentially dangerous
|
|
94
|
-
*/
|
|
95
|
-
function isDangerousCommand(command) {
|
|
96
|
-
const dangerousPatterns = [
|
|
97
|
-
/rm\s+-rf\s+\//, // rm -rf /
|
|
98
|
-
/rm\s+-rf\s+~/, // rm -rf ~
|
|
99
|
-
/rm\s+-rf\s+\*/, // rm -rf *
|
|
100
|
-
/:\(\)\{.*\}/, // Fork bomb
|
|
101
|
-
/dd\s+if=.*of=\/dev/, // Disk operations
|
|
102
|
-
/mkfs/, // Format filesystem
|
|
103
|
-
/fdisk/, // Partition operations
|
|
104
|
-
/>\s*\/dev\/sd/, // Write to disk
|
|
105
|
-
/chmod\s+-R\s+777/, // Dangerous permissions
|
|
106
|
-
/curl.*\|\s*bash/, // Pipe to bash
|
|
107
|
-
/wget.*\|\s*sh/, // Pipe to shell
|
|
108
|
-
/sudo\s+rm/, // Sudo remove
|
|
109
|
-
/format\s+[A-Z]:/, // Windows format
|
|
110
|
-
/del\s+\/[FS]/, // Windows delete
|
|
111
|
-
];
|
|
112
|
-
return dangerousPatterns.some(pattern => pattern.test(command));
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Check if command is safe to auto-execute
|
|
116
|
-
*/
|
|
117
|
-
function isSafeAutoCommand(command) {
|
|
118
|
-
const safePrefixes = [
|
|
119
|
-
// File Discovery & Read
|
|
120
|
-
'cat ', 'ls ', 'grep ', 'find ', 'pwd', 'echo ', 'read ', 'type ', 'dir',
|
|
121
|
-
// File Operations
|
|
122
|
-
'mkdir ', 'touch ', 'cp ', 'mv ', 'rm ', 'del ', 'copy ', 'move ',
|
|
123
|
-
// Dev Tools
|
|
124
|
-
'npm ', 'npx ', 'git ', 'node ', 'python ', 'python3 ', 'pip ', 'pip3 ',
|
|
125
|
-
// Cloud & Mobile
|
|
126
|
-
'firebase ', 'gcloud ', 'docker ', 'flutter ', 'react-native ',
|
|
127
|
-
// Build & Package
|
|
128
|
-
'cd ', 'tsc ', 'vite ', 'next ', 'cargo ', 'go ', 'swift '
|
|
129
|
-
];
|
|
130
|
-
const trimmed = command.trim();
|
|
131
|
-
return safePrefixes.some(prefix => trimmed.startsWith(prefix));
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Ask user for permission to execute command
|
|
135
|
-
*/
|
|
136
|
-
async function askPermission(command) {
|
|
137
|
-
// Clean Codex-style Prompt with Multi-Agent Iconography
|
|
138
|
-
console.log();
|
|
139
|
-
// Remove auto-execution logic to prevent infinite "run forever" loops
|
|
140
|
-
// The user should always be prompted or have the option to safely step through.
|
|
141
|
-
console.log(chalk_1.default.yellow('🛡️ SyntaxGuard ') + chalk_1.default.white('Analysis:'));
|
|
142
|
-
console.log(chalk_1.default.gray('> ') + chalk_1.default.white(command.code));
|
|
143
|
-
console.log();
|
|
144
|
-
if (command.dangerous) {
|
|
145
|
-
console.log(chalk_1.default.red('🚨 WARNING: Dangerous command'));
|
|
146
|
-
}
|
|
147
|
-
const { execute } = await inquirer_1.default.prompt([{
|
|
148
|
-
type: 'confirm',
|
|
149
|
-
name: 'execute',
|
|
150
|
-
message: command.dangerous ?
|
|
151
|
-
chalk_1.default.red('Execute?') :
|
|
152
|
-
chalk_1.default.gray('Execute?'),
|
|
153
|
-
default: true // Default to true for seamless flow (Codex style)
|
|
154
|
-
}]);
|
|
155
|
-
return execute;
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Execute a shell command with real-time streaming and interruption support
|
|
159
|
-
*/
|
|
160
|
-
async function executeCommand(command, shell, cwd) {
|
|
161
|
-
return new Promise((resolve, reject) => {
|
|
162
|
-
const shellPath = shell || process.env.SHELL || '/bin/bash';
|
|
163
|
-
const child = (0, child_process_1.spawn)(shellPath, ['-c', command], {
|
|
164
|
-
cwd: cwd || process.cwd(),
|
|
165
|
-
env: { ...process.env, FORCE_COLOR: 'true' }
|
|
166
|
-
});
|
|
167
|
-
let stdout = '';
|
|
168
|
-
let stderr = '';
|
|
169
|
-
let isAborted = false;
|
|
170
|
-
const commandStartTime = Date.now();
|
|
171
|
-
// Listen for "Enter" or "Escape" to kill the command
|
|
172
|
-
const onData = (data) => {
|
|
173
|
-
// Check for Enter (13), Newline (10), Escape (27), or Ctrl+C (3)
|
|
174
|
-
// 🏁 GRACE PERIOD: Ignore aborts in the first 200ms to prevent stray newlines
|
|
175
|
-
if (Date.now() - commandStartTime < 200)
|
|
176
|
-
return;
|
|
177
|
-
if (data[0] === 13 || data[0] === 10 || data[0] === 27 || data[0] === 3) {
|
|
178
|
-
isAborted = true;
|
|
179
|
-
child.kill('SIGINT'); // Send SIGINT to gracefully terminate
|
|
180
|
-
}
|
|
181
|
-
};
|
|
182
|
-
const isRaw = process.stdin.isRaw;
|
|
183
|
-
process.stdin.resume();
|
|
184
|
-
if (process.stdin.setRawMode)
|
|
185
|
-
process.stdin.setRawMode(true);
|
|
186
|
-
process.stdin.on('data', onData);
|
|
187
|
-
child.stdout.on('data', (data) => {
|
|
188
|
-
const chunk = data.toString();
|
|
189
|
-
stdout += chunk;
|
|
190
|
-
// No direct process.stdout.write here to prevent leaks
|
|
191
|
-
});
|
|
192
|
-
child.stderr.on('data', (data) => {
|
|
193
|
-
const chunk = data.toString();
|
|
194
|
-
stderr += chunk;
|
|
195
|
-
// No direct process.stderr.write here to prevent leaks
|
|
196
|
-
});
|
|
197
|
-
child.on('close', (code) => {
|
|
198
|
-
// Restore terminal state
|
|
199
|
-
process.stdin.removeListener('data', onData);
|
|
200
|
-
if (process.stdin.setRawMode)
|
|
201
|
-
process.stdin.setRawMode(isRaw);
|
|
202
|
-
process.stdin.pause();
|
|
203
|
-
if (isAborted) {
|
|
204
|
-
resolve({ stdout, stderr, aborted: true });
|
|
205
|
-
}
|
|
206
|
-
else if (code === 0) {
|
|
207
|
-
resolve({ stdout, stderr });
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
resolve({ stdout, stderr }); // Resolve instead of reject to keep agent loop alive
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
child.on('error', (err) => {
|
|
214
|
-
process.stdin.removeListener('data', onData);
|
|
215
|
-
if (process.stdin.setRawMode)
|
|
216
|
-
process.stdin.setRawMode(isRaw);
|
|
217
|
-
process.stdin.pause();
|
|
218
|
-
reject(err);
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
/**
|
|
223
|
-
* Execute commands and surgical patches with user permission
|
|
224
|
-
*/
|
|
225
|
-
async function executeWithPermission(response, currentSessionCwd) {
|
|
226
|
-
const commands = extractCommands(response);
|
|
227
|
-
const patches = patcher_1.Patcher.parseEditBlocks(response);
|
|
228
|
-
const files = patcher_1.Patcher.parseFileBlocks(response);
|
|
229
|
-
let activeCwd = currentSessionCwd || process.cwd();
|
|
230
|
-
let accumulatedOutput = '';
|
|
231
|
-
let accumulatedError = '';
|
|
232
|
-
if (commands.length === 0 && patches.length === 0 && files.length === 0) {
|
|
233
|
-
return { success: true, executed: false, newCwd: activeCwd };
|
|
234
|
-
}
|
|
235
|
-
// 1. Handle New File Creation
|
|
236
|
-
for (const file of files) {
|
|
237
|
-
// Ensure creation happens relative to activeCwd if path is relative
|
|
238
|
-
const originalPath = file.filePath;
|
|
239
|
-
if (!path.isAbsolute(file.filePath)) {
|
|
240
|
-
file.filePath = path.join(activeCwd, file.filePath);
|
|
241
|
-
}
|
|
242
|
-
let showFull = false;
|
|
243
|
-
let decided = false;
|
|
244
|
-
while (!decided) {
|
|
245
|
-
const isTruncated = patcher_1.Patcher.showDiff(file, showFull);
|
|
246
|
-
const choices = [
|
|
247
|
-
{ name: '✅ Create this new file brother', value: 'create' },
|
|
248
|
-
{ name: '⏭️ Skip', value: 'skip' }
|
|
249
|
-
];
|
|
250
|
-
if (isTruncated && !showFull) {
|
|
251
|
-
choices.splice(1, 0, { name: '🔍 View Full Code', value: 'full' });
|
|
252
|
-
}
|
|
253
|
-
const { action } = await inquirer_1.default.prompt([{
|
|
254
|
-
type: 'list',
|
|
255
|
-
name: 'action',
|
|
256
|
-
message: chalk_1.default.cyan(`Create ${originalPath}?`),
|
|
257
|
-
choices: choices
|
|
258
|
-
}]);
|
|
259
|
-
if (action === 'full') {
|
|
260
|
-
showFull = true;
|
|
261
|
-
continue;
|
|
262
|
-
}
|
|
263
|
-
if (action === 'create') {
|
|
264
|
-
const result = patcher_1.Patcher.createFile(file);
|
|
265
|
-
if (!result.success)
|
|
266
|
-
return { success: false, executed: true, error: result.error, newCwd: activeCwd };
|
|
267
|
-
}
|
|
268
|
-
decided = true;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
// 2. Handle Shell Commands
|
|
272
|
-
for (let i = 0; i < commands.length; i++) {
|
|
273
|
-
const command = commands[i];
|
|
274
|
-
// 🛡️ PRE-EXECUTION HALLUCINATION GUARD: Check for fake directories
|
|
275
|
-
const commandLines = command.code.split('\n');
|
|
276
|
-
let skipThisCommand = false;
|
|
277
|
-
let sanitizedCode = command.code;
|
|
278
|
-
for (const line of commandLines) {
|
|
279
|
-
const trimmed = line.trim();
|
|
280
|
-
// Check standalone cd commands
|
|
281
|
-
if (trimmed.startsWith('cd ')) {
|
|
282
|
-
let targetDir = trimmed.substring(3).replace(/['"]/g, '').trim();
|
|
283
|
-
const potentialCwd = path.isAbsolute(targetDir) ? targetDir : path.resolve(activeCwd, targetDir);
|
|
284
|
-
if (!fs.existsSync(potentialCwd) || !fs.statSync(potentialCwd).isDirectory()) {
|
|
285
|
-
console.log(chalk_1.default.yellow(`\n ⚠️ Skipped hallucinated directory: "${targetDir}"`));
|
|
286
|
-
console.log(chalk_1.default.gray(` (Does not exist at: ${potentialCwd})`));
|
|
287
|
-
console.log(chalk_1.default.gray(` Current CWD stays: ${activeCwd}\n`));
|
|
288
|
-
skipThisCommand = true;
|
|
289
|
-
break;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
// Check cd inside combined commands like: cd "fake" && npm install
|
|
293
|
-
const cdChainMatch = trimmed.match(/^cd\s+["']?([^"'&]+)["']?\s*&&/);
|
|
294
|
-
if (cdChainMatch) {
|
|
295
|
-
let targetDir = cdChainMatch[1].trim();
|
|
296
|
-
const potentialCwd = path.isAbsolute(targetDir) ? targetDir : path.resolve(activeCwd, targetDir);
|
|
297
|
-
if (!fs.existsSync(potentialCwd) || !fs.statSync(potentialCwd).isDirectory()) {
|
|
298
|
-
console.log(chalk_1.default.yellow(`\n ⚠️ Stripping hallucinated cd from command: "${targetDir}"`));
|
|
299
|
-
// Remove the cd part and execute the rest
|
|
300
|
-
sanitizedCode = trimmed.replace(/^cd\s+["']?[^"'&]+["']?\s*&&\s*/, '');
|
|
301
|
-
console.log(chalk_1.default.gray(` Running remaining: ${sanitizedCode}\n`));
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
if (skipThisCommand)
|
|
306
|
-
continue;
|
|
307
|
-
// Update command code with sanitized version
|
|
308
|
-
command.code = sanitizedCode;
|
|
309
|
-
// 🚀 MCP INTERCEPTION: If the command matches an MCP tool directly, use MCPServer
|
|
310
|
-
const mcpMatch = command.code.trim().match(/^(web_search|read_file|write_file|list_directory|search_files|run_command|fetch_url|git_status)\s+(.*)$/);
|
|
311
|
-
if (mcpMatch) {
|
|
312
|
-
const toolName = mcpMatch[1];
|
|
313
|
-
const rawArgs = mcpMatch[2].trim();
|
|
314
|
-
console.log(chalk_1.default.cyan(`⚡ Intercepted MCP Tool: `) + chalk_1.default.white(`${toolName}(${rawArgs})`));
|
|
315
|
-
try {
|
|
316
|
-
const { MCPServer } = await Promise.resolve().then(() => __importStar(require('./mcp-server')));
|
|
317
|
-
const mcp = new MCPServer(activeCwd);
|
|
318
|
-
// Heuristic: If it's just a string, wrap it in a query/path object
|
|
319
|
-
let args = {};
|
|
320
|
-
if (toolName === 'web_search')
|
|
321
|
-
args = { query: rawArgs.replace(/^['"]|['"]$/g, '') };
|
|
322
|
-
else if (toolName === 'fetch_url')
|
|
323
|
-
args = { url: rawArgs.replace(/^['"]|['"]$/g, '') };
|
|
324
|
-
else if (['read_file', 'list_directory', 'git_status'].includes(toolName))
|
|
325
|
-
args = { path: rawArgs.replace(/^['"]|['"]$/g, '') };
|
|
326
|
-
else
|
|
327
|
-
args = { command: rawArgs }; // Default fallback
|
|
328
|
-
const result = await mcp.execute(toolName, args);
|
|
329
|
-
if (result.success) {
|
|
330
|
-
accumulatedOutput += `[MCP ${toolName} Output]:\n${result.output}\n\n`;
|
|
331
|
-
agent_orchestrator_1.AgentOrchestrator.terminal(command.code, result.output);
|
|
332
|
-
}
|
|
333
|
-
else {
|
|
334
|
-
accumulatedError += `[MCP ${toolName} Error]: ${result.error}\n`;
|
|
335
|
-
agent_orchestrator_1.AgentOrchestrator.terminal(command.code, undefined, result.error);
|
|
336
|
-
}
|
|
337
|
-
continue; // Move to next command
|
|
338
|
-
}
|
|
339
|
-
catch (e) {
|
|
340
|
-
console.log(chalk_1.default.red(` ❌ MCP Execution Error: ${e.message}`));
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
const shouldExecute = await askPermission(command);
|
|
344
|
-
if (shouldExecute) {
|
|
345
|
-
try {
|
|
346
|
-
// Persistent CWD logic: Trace 'cd' commands
|
|
347
|
-
const lines = command.code.split('\n');
|
|
348
|
-
for (const line of lines) {
|
|
349
|
-
const trimmed = line.trim();
|
|
350
|
-
if (trimmed.startsWith('cd ')) {
|
|
351
|
-
let targetDir = trimmed.substring(3).replace(/['"]/g, '').trim();
|
|
352
|
-
// Resolve relative to activeCwd
|
|
353
|
-
const potentialCwd = path.isAbsolute(targetDir) ? targetDir : path.resolve(activeCwd, targetDir);
|
|
354
|
-
if (fs.existsSync(potentialCwd) && fs.statSync(potentialCwd).isDirectory()) {
|
|
355
|
-
activeCwd = potentialCwd;
|
|
356
|
-
}
|
|
357
|
-
else {
|
|
358
|
-
// Directory doesn't exist - skip silently instead of crashing
|
|
359
|
-
console.log(chalk_1.default.yellow(` ⚠️ Directory not found: ${targetDir} — staying in ${activeCwd}`));
|
|
360
|
-
continue;
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
tui_1.TUI.drawLiveTerminalStart(command.code);
|
|
365
|
-
const shellPath = process.env.SHELL || '/bin/bash';
|
|
366
|
-
const child = (0, child_process_1.spawn)(shellPath, ['-c', command.code], {
|
|
367
|
-
cwd: activeCwd,
|
|
368
|
-
env: { ...process.env, FORCE_COLOR: 'true' }
|
|
369
|
-
});
|
|
370
|
-
let stdout = '';
|
|
371
|
-
let stderr = '';
|
|
372
|
-
let isAborted = false;
|
|
373
|
-
const commandStartTime = Date.now();
|
|
374
|
-
const onData = (data) => {
|
|
375
|
-
if (Date.now() - commandStartTime < 500)
|
|
376
|
-
return; // Hardened 500ms grace period
|
|
377
|
-
if (data[0] === 13 || data[0] === 10 || data[0] === 27 || data[0] === 3) {
|
|
378
|
-
isAborted = true;
|
|
379
|
-
child.kill('SIGINT');
|
|
380
|
-
}
|
|
381
|
-
};
|
|
382
|
-
const isRaw = process.stdin.isRaw;
|
|
383
|
-
process.stdin.resume();
|
|
384
|
-
if (process.stdin.setRawMode)
|
|
385
|
-
process.stdin.setRawMode(true);
|
|
386
|
-
process.stdin.on('data', onData);
|
|
387
|
-
child.stdout.on('data', (data) => {
|
|
388
|
-
const chunk = data.toString();
|
|
389
|
-
stdout += chunk;
|
|
390
|
-
tui_1.TUI.drawLiveTerminalLine(chunk);
|
|
391
|
-
});
|
|
392
|
-
child.stderr.on('data', (data) => {
|
|
393
|
-
const chunk = data.toString();
|
|
394
|
-
stderr += chunk;
|
|
395
|
-
tui_1.TUI.drawLiveTerminalLine(chunk, true);
|
|
396
|
-
});
|
|
397
|
-
const { code } = await new Promise(resolve => {
|
|
398
|
-
child.on('close', (code) => {
|
|
399
|
-
process.stdin.removeListener('data', onData);
|
|
400
|
-
if (process.stdin.setRawMode)
|
|
401
|
-
process.stdin.setRawMode(isRaw);
|
|
402
|
-
process.stdin.pause();
|
|
403
|
-
tui_1.TUI.drawLiveTerminalEnd();
|
|
404
|
-
resolve({ code });
|
|
405
|
-
});
|
|
406
|
-
});
|
|
407
|
-
accumulatedOutput += stdout;
|
|
408
|
-
accumulatedError += stderr;
|
|
409
|
-
if (isAborted) {
|
|
410
|
-
console.log(chalk_1.default.yellow(' [🛑] Command aborted by brother.\n'));
|
|
411
|
-
agent_orchestrator_1.AgentOrchestrator.terminal(command.code, stdout, stderr + '\n(Aborted)');
|
|
412
|
-
}
|
|
413
|
-
else if (code === 0) {
|
|
414
|
-
if (stdout || stderr) {
|
|
415
|
-
agent_orchestrator_1.AgentOrchestrator.terminal(command.code, stdout, stderr);
|
|
416
|
-
}
|
|
417
|
-
else {
|
|
418
|
-
agent_orchestrator_1.AgentOrchestrator.terminal(command.code, '✓ Success (No output)');
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
else {
|
|
422
|
-
agent_orchestrator_1.AgentOrchestrator.terminal(command.code, stdout, stderr || `Failed with code ${code}`);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
catch (error) {
|
|
426
|
-
accumulatedError += error.message;
|
|
427
|
-
agent_orchestrator_1.AgentOrchestrator.terminal(command.code, undefined, error.message);
|
|
428
|
-
return { success: false, executed: true, error: accumulatedError, output: accumulatedOutput, newCwd: activeCwd };
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
// 3. Handle Surgical Patches
|
|
433
|
-
for (const surgicalPatch of patches) {
|
|
434
|
-
// Ensure patch happens relative to activeCwd if path is relative
|
|
435
|
-
const originalPath = surgicalPatch.filePath;
|
|
436
|
-
if (!path.isAbsolute(surgicalPatch.filePath)) {
|
|
437
|
-
surgicalPatch.filePath = path.join(activeCwd, surgicalPatch.filePath);
|
|
438
|
-
}
|
|
439
|
-
let showFull = false;
|
|
440
|
-
let decided = false;
|
|
441
|
-
while (!decided) {
|
|
442
|
-
const isTruncated = patcher_1.Patcher.showDiff(surgicalPatch, showFull);
|
|
443
|
-
const choices = [
|
|
444
|
-
{ name: '✅ Apply this surgical patch brother', value: 'apply' },
|
|
445
|
-
{ name: '⏭️ Skip', value: 'skip' }
|
|
446
|
-
];
|
|
447
|
-
if (isTruncated && !showFull) {
|
|
448
|
-
choices.splice(1, 0, { name: '🔍 View Full Diff', value: 'full' });
|
|
449
|
-
}
|
|
450
|
-
const { action } = await inquirer_1.default.prompt([{
|
|
451
|
-
type: 'list',
|
|
452
|
-
name: 'action',
|
|
453
|
-
message: chalk_1.default.cyan(`Patch ${originalPath}?`),
|
|
454
|
-
choices: choices
|
|
455
|
-
}]);
|
|
456
|
-
if (action === 'full') {
|
|
457
|
-
showFull = true;
|
|
458
|
-
continue;
|
|
459
|
-
}
|
|
460
|
-
if (action === 'apply') {
|
|
461
|
-
const result = patcher_1.Patcher.applyPatch(surgicalPatch);
|
|
462
|
-
if (result.success) {
|
|
463
|
-
console.log(chalk_1.default.green(` ✅ Applied surgical patch to ${originalPath}\n`));
|
|
464
|
-
}
|
|
465
|
-
else {
|
|
466
|
-
console.log(chalk_1.default.red(` ❌ Error applying patch: ${result.error}\n`));
|
|
467
|
-
return { success: false, executed: true, error: result.error, newCwd: activeCwd };
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
else {
|
|
471
|
-
console.log(chalk_1.default.gray(' Skipped.\n'));
|
|
472
|
-
}
|
|
473
|
-
decided = true;
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
return {
|
|
477
|
-
success: true,
|
|
478
|
-
executed: true,
|
|
479
|
-
output: accumulatedOutput.trim(),
|
|
480
|
-
error: accumulatedError.trim(),
|
|
481
|
-
newCwd: activeCwd
|
|
482
|
-
};
|
|
483
|
-
}
|
|
484
|
-
/**
|
|
485
|
-
* Command history for undo/rollback
|
|
486
|
-
*/
|
|
487
|
-
class CommandHistory {
|
|
488
|
-
constructor() {
|
|
489
|
-
this.history = [];
|
|
490
|
-
}
|
|
491
|
-
add(command, success) {
|
|
492
|
-
this.history.push({
|
|
493
|
-
command,
|
|
494
|
-
timestamp: new Date(),
|
|
495
|
-
success
|
|
496
|
-
});
|
|
497
|
-
}
|
|
498
|
-
getHistory() {
|
|
499
|
-
return this.history;
|
|
500
|
-
}
|
|
501
|
-
clear() {
|
|
502
|
-
this.history = [];
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
exports.CommandHistory = CommandHistory;
|
|
506
|
-
exports.commandHistory = new CommandHistory();
|
|
507
|
-
//# sourceMappingURL=command-executor.js.map
|
package/dist/utils/config.js
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.configManager = exports.ConfigManager = void 0;
|
|
37
|
-
const fs = __importStar(require("fs"));
|
|
38
|
-
const path = __importStar(require("path"));
|
|
39
|
-
const os = __importStar(require("os"));
|
|
40
|
-
class ConfigManager {
|
|
41
|
-
constructor() {
|
|
42
|
-
this.configDir = path.join(os.homedir(), '.matex');
|
|
43
|
-
this.configPath = path.join(this.configDir, 'config.json');
|
|
44
|
-
// Ensure config directory exists
|
|
45
|
-
if (!fs.existsSync(this.configDir)) {
|
|
46
|
-
fs.mkdirSync(this.configDir, { recursive: true });
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Load config from file
|
|
51
|
-
*/
|
|
52
|
-
loadConfig() {
|
|
53
|
-
if (!fs.existsSync(this.configPath)) {
|
|
54
|
-
return {};
|
|
55
|
-
}
|
|
56
|
-
try {
|
|
57
|
-
const data = fs.readFileSync(this.configPath, 'utf-8');
|
|
58
|
-
return JSON.parse(data);
|
|
59
|
-
}
|
|
60
|
-
catch (error) {
|
|
61
|
-
return {};
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Save config to file
|
|
66
|
-
*/
|
|
67
|
-
saveConfig(config) {
|
|
68
|
-
fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Set API key
|
|
72
|
-
*/
|
|
73
|
-
setAPIKey(apiKey) {
|
|
74
|
-
const config = this.loadConfig();
|
|
75
|
-
config.apiKey = apiKey;
|
|
76
|
-
this.saveConfig(config);
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Get API key
|
|
80
|
-
*/
|
|
81
|
-
getAPIKey() {
|
|
82
|
-
return this.loadConfig().apiKey;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Set default model
|
|
86
|
-
*/
|
|
87
|
-
setDefaultModel(model) {
|
|
88
|
-
const config = this.loadConfig();
|
|
89
|
-
let normalizedModel = model.toLowerCase().trim().replace(/\s+/g, '');
|
|
90
|
-
if (normalizedModel === 'matexfree') {
|
|
91
|
-
normalizedModel = 'matex-free';
|
|
92
|
-
}
|
|
93
|
-
config.defaultModel = normalizedModel;
|
|
94
|
-
this.saveConfig(config);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Get default model
|
|
98
|
-
*/
|
|
99
|
-
getDefaultModel() {
|
|
100
|
-
return this.loadConfig().defaultModel || 'matexcodex';
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Set base URL
|
|
104
|
-
*/
|
|
105
|
-
setBaseURL(url) {
|
|
106
|
-
const config = this.loadConfig();
|
|
107
|
-
config.baseURL = url;
|
|
108
|
-
this.saveConfig(config);
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Get base URL
|
|
112
|
-
*/
|
|
113
|
-
getBaseURL() {
|
|
114
|
-
return this.loadConfig().baseURL || 'https://matexai-backend-550499663766.us-central1.run.app';
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Get all config
|
|
118
|
-
*/
|
|
119
|
-
getAll() {
|
|
120
|
-
return this.loadConfig();
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Clear all config
|
|
124
|
-
*/
|
|
125
|
-
clear() {
|
|
126
|
-
if (fs.existsSync(this.configPath)) {
|
|
127
|
-
fs.unlinkSync(this.configPath);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Check if API key is set
|
|
132
|
-
*/
|
|
133
|
-
hasAPIKey() {
|
|
134
|
-
return !!this.getAPIKey();
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
exports.ConfigManager = ConfigManager;
|
|
138
|
-
exports.configManager = new ConfigManager();
|
|
139
|
-
//# sourceMappingURL=config.js.map
|