matex-cli 1.1.0 → 1.1.2
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/code.d.ts.map +1 -1
- package/dist/commands/code.js +6 -0
- package/dist/commands/code.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +6 -0
- package/dist/commands/dev.js.map +1 -1
- package/dist/index.js +94 -15
- package/dist/index.js.map +1 -1
- package/dist/utils/command-executor.d.ts +49 -0
- package/dist/utils/command-executor.d.ts.map +1 -0
- package/dist/utils/command-executor.js +159 -0
- package/dist/utils/command-executor.js.map +1 -0
- package/package.json +1 -1
- package/src/commands/code.ts +7 -0
- package/src/commands/dev.ts +7 -0
- package/src/index.ts +70 -18
- package/src/utils/command-executor.ts +190 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code.d.ts","sourceRoot":"","sources":["../../src/commands/code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"code.d.ts","sourceRoot":"","sources":["../../src/commands/code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,WAAW,SA2FlB,CAAC"}
|
package/dist/commands/code.js
CHANGED
|
@@ -9,6 +9,7 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
9
9
|
const config_1 = require("../utils/config");
|
|
10
10
|
const client_1 = require("../api/client");
|
|
11
11
|
const spinner_1 = require("../utils/spinner");
|
|
12
|
+
const command_executor_1 = require("../utils/command-executor");
|
|
12
13
|
exports.codeCommand = new commander_1.Command('code')
|
|
13
14
|
.description('Generate code with MATEXCodex (optimized for coding)')
|
|
14
15
|
.argument('<prompt>', 'What code do you need?')
|
|
@@ -16,6 +17,7 @@ exports.codeCommand = new commander_1.Command('code')
|
|
|
16
17
|
.option('-l, --language <lang>', 'Programming language (auto-detected if not specified)')
|
|
17
18
|
.option('-t, --temperature <number>', 'Temperature (0-1)', '0.3')
|
|
18
19
|
.option('--max-tokens <number>', 'Maximum tokens in response', '8000')
|
|
20
|
+
.option('-x, --execute', 'Execute commands found in response (with permission prompts)')
|
|
19
21
|
.action(async (prompt, options) => {
|
|
20
22
|
try {
|
|
21
23
|
// Check for API key
|
|
@@ -68,6 +70,10 @@ exports.codeCommand = new commander_1.Command('code')
|
|
|
68
70
|
fs.writeFileSync(options.output, codeContent.trim());
|
|
69
71
|
console.log(chalk_1.default.green(`✅ Code saved to: ${options.output}`));
|
|
70
72
|
}
|
|
73
|
+
// Execute commands if requested
|
|
74
|
+
if (options.execute) {
|
|
75
|
+
await (0, command_executor_1.executeWithPermission)(response);
|
|
76
|
+
}
|
|
71
77
|
}
|
|
72
78
|
catch (error) {
|
|
73
79
|
spinner_1.spinner.fail('Code generation failed');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/commands/code.ts"],"names":[],"mappings":";;;;;;AAAA,yCAAoC;AACpC,kDAA0B;AAC1B,4CAAgD;AAChD,0CAA+C;AAC/C,8CAA2C;
|
|
1
|
+
{"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/commands/code.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,eAAO,MAAM,UAAU,SAoGjB,CAAC"}
|
package/dist/commands/dev.js
CHANGED
|
@@ -10,9 +10,11 @@ const inquirer_1 = __importDefault(require("inquirer"));
|
|
|
10
10
|
const config_1 = require("../utils/config");
|
|
11
11
|
const client_1 = require("../api/client");
|
|
12
12
|
const spinner_1 = require("../utils/spinner");
|
|
13
|
+
const command_executor_1 = require("../utils/command-executor");
|
|
13
14
|
exports.devCommand = new commander_1.Command('dev')
|
|
14
15
|
.description('Start interactive development session with MATEXCodex')
|
|
15
16
|
.option('-m, --model <model>', 'AI model to use', 'matexcodex')
|
|
17
|
+
.option('-x, --execute', 'Auto-prompt for command execution (Ollama-style)')
|
|
16
18
|
.action(async (options) => {
|
|
17
19
|
try {
|
|
18
20
|
// Check for API key
|
|
@@ -77,6 +79,10 @@ exports.devCommand = new commander_1.Command('dev')
|
|
|
77
79
|
console.log(chalk_1.default.green('\nMATEXCodex:'));
|
|
78
80
|
console.log(chalk_1.default.white(response));
|
|
79
81
|
console.log();
|
|
82
|
+
// Execute commands if requested
|
|
83
|
+
if (options.execute) {
|
|
84
|
+
await (0, command_executor_1.executeWithPermission)(response);
|
|
85
|
+
}
|
|
80
86
|
}
|
|
81
87
|
catch (error) {
|
|
82
88
|
spinner_1.spinner.fail('Request failed');
|
package/dist/commands/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":";;;;;;AAAA,yCAAoC;AACpC,kDAA0B;AAC1B,wDAAgC;AAChC,4CAAgD;AAChD,0CAA4D;AAC5D,8CAA2C;
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
3
36
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
37
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
38
|
};
|
|
@@ -60,21 +93,67 @@ if (args.length > 0 && !args[0].startsWith('-') && !knownCommands.includes(args[
|
|
|
60
93
|
process.exit(1);
|
|
61
94
|
}
|
|
62
95
|
const client = new client_1.MatexAPIClient(apiKey, config_2.configManager.getBaseURL());
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
96
|
+
// Get current directory context
|
|
97
|
+
const fs = require('fs');
|
|
98
|
+
const files = fs.readdirSync(process.cwd()).slice(0, 20).join(', '); // fast list
|
|
99
|
+
const context = `Current directory: ${process.cwd()}\nFiles: ${files}`;
|
|
100
|
+
let messages = [
|
|
101
|
+
{
|
|
102
|
+
role: 'system', content: `You are MATEXCodex, an expert agentic coding assistant.
|
|
103
|
+
1. Your goal is to COMPLETE the user's task.
|
|
104
|
+
2. You can execute shell commands by wrapping them in code blocks (bash, sh, zsh).
|
|
105
|
+
3. PREFER simple one-line shell commands (like 'mkdir', 'touch', 'npm install') over complex scripts.
|
|
106
|
+
4. If you need to create a file, use 'echo "content" > file.js' or similar.
|
|
107
|
+
5. If a command fails, I will send you the error - FIX IT and try again.
|
|
108
|
+
6. Look at the current directory context to avoid "file not found" errors.
|
|
109
|
+
${context}`
|
|
110
|
+
},
|
|
111
|
+
{ role: 'user', content: prompt }
|
|
112
|
+
];
|
|
113
|
+
let loopCount = 0;
|
|
114
|
+
const MAX_LOOPS = 5;
|
|
115
|
+
while (loopCount < MAX_LOOPS) {
|
|
116
|
+
loopCount++;
|
|
117
|
+
spinner_1.spinner.start(loopCount === 1 ? 'Generating plan...' : 'Analyzing result...');
|
|
118
|
+
const response = await client.chat({
|
|
119
|
+
messages,
|
|
120
|
+
model: 'matexcodex',
|
|
121
|
+
temperature: 0.3,
|
|
122
|
+
max_tokens: 8000,
|
|
123
|
+
stream: false,
|
|
124
|
+
});
|
|
125
|
+
spinner_1.spinner.stop();
|
|
126
|
+
// Display response
|
|
127
|
+
console.log(chalk_1.default.cyan(`\n💻 MATEXCodex (Step ${loopCount}):\n`));
|
|
128
|
+
console.log(chalk_1.default.white(response));
|
|
129
|
+
console.log();
|
|
130
|
+
// Auto-execute commands (Ollama-style)
|
|
131
|
+
const { executeWithPermission } = await Promise.resolve().then(() => __importStar(require('./utils/command-executor')));
|
|
132
|
+
const result = await executeWithPermission(response);
|
|
133
|
+
if (result.executed) {
|
|
134
|
+
if (result.success) {
|
|
135
|
+
// Success!
|
|
136
|
+
if (loopCount > 1) {
|
|
137
|
+
console.log(chalk_1.default.green('✅ Fix succeeded!'));
|
|
138
|
+
}
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
// Failure - Loop back
|
|
143
|
+
console.log(chalk_1.default.yellow('\n↺ Command failed. Asking AI to fix...'));
|
|
144
|
+
messages.push({ role: 'assistant', content: response });
|
|
145
|
+
messages.push({
|
|
146
|
+
role: 'user',
|
|
147
|
+
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.`
|
|
148
|
+
});
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
// No command to execute - we are done
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
78
157
|
}
|
|
79
158
|
catch (error) {
|
|
80
159
|
spinner_1.spinner.fail('Failed');
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export interface CommandBlock {
|
|
2
|
+
language: string;
|
|
3
|
+
code: string;
|
|
4
|
+
dangerous: boolean;
|
|
5
|
+
description?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Extract executable commands from AI response
|
|
9
|
+
*/
|
|
10
|
+
export declare function extractCommands(response: string): CommandBlock[];
|
|
11
|
+
/**
|
|
12
|
+
* Ask user for permission to execute command
|
|
13
|
+
*/
|
|
14
|
+
export declare function askPermission(command: CommandBlock): Promise<boolean>;
|
|
15
|
+
/**
|
|
16
|
+
* Execute a shell command
|
|
17
|
+
*/
|
|
18
|
+
export declare function executeCommand(command: string, shell?: string): Promise<{
|
|
19
|
+
stdout: string;
|
|
20
|
+
stderr: string;
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* Execute commands with user permission
|
|
24
|
+
*/
|
|
25
|
+
export interface ExecutionResult {
|
|
26
|
+
success: boolean;
|
|
27
|
+
executed: boolean;
|
|
28
|
+
output?: string;
|
|
29
|
+
error?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Execute commands with user permission
|
|
33
|
+
*/
|
|
34
|
+
export declare function executeWithPermission(response: string): Promise<ExecutionResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Command history for undo/rollback
|
|
37
|
+
*/
|
|
38
|
+
export declare class CommandHistory {
|
|
39
|
+
private history;
|
|
40
|
+
add(command: string, success: boolean): void;
|
|
41
|
+
getHistory(): {
|
|
42
|
+
command: string;
|
|
43
|
+
timestamp: Date;
|
|
44
|
+
success: boolean;
|
|
45
|
+
}[];
|
|
46
|
+
clear(): void;
|
|
47
|
+
}
|
|
48
|
+
export declare const commandHistory: CommandHistory;
|
|
49
|
+
//# sourceMappingURL=command-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-executor.d.ts","sourceRoot":"","sources":["../../src/utils/command-executor.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,YAAY;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAsBhE;AA0BD;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAoB3E;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAYjH;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA4CtF;AAED;;GAEG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,OAAO,CAAqE;IAEpF,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAQrC,UAAU;iBAVwB,MAAM;mBAAa,IAAI;iBAAW,OAAO;;IAc3E,KAAK;CAGR;AAED,eAAO,MAAM,cAAc,gBAAuB,CAAC"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.commandHistory = exports.CommandHistory = void 0;
|
|
7
|
+
exports.extractCommands = extractCommands;
|
|
8
|
+
exports.askPermission = askPermission;
|
|
9
|
+
exports.executeCommand = executeCommand;
|
|
10
|
+
exports.executeWithPermission = executeWithPermission;
|
|
11
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
+
const child_process_1 = require("child_process");
|
|
13
|
+
const util_1 = require("util");
|
|
14
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
15
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
16
|
+
/**
|
|
17
|
+
* Extract executable commands from AI response
|
|
18
|
+
*/
|
|
19
|
+
function extractCommands(response) {
|
|
20
|
+
const commands = [];
|
|
21
|
+
// Match code blocks with language tags
|
|
22
|
+
const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
|
|
23
|
+
let match;
|
|
24
|
+
while ((match = codeBlockRegex.exec(response)) !== null) {
|
|
25
|
+
const language = match[1] || 'bash';
|
|
26
|
+
const code = match[2].trim();
|
|
27
|
+
// Only extract shell commands
|
|
28
|
+
if (['bash', 'sh', 'zsh', 'shell', 'powershell', 'cmd'].includes(language.toLowerCase())) {
|
|
29
|
+
commands.push({
|
|
30
|
+
language,
|
|
31
|
+
code,
|
|
32
|
+
dangerous: isDangerousCommand(code)
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return commands;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Check if command is potentially dangerous
|
|
40
|
+
*/
|
|
41
|
+
function isDangerousCommand(command) {
|
|
42
|
+
const dangerousPatterns = [
|
|
43
|
+
/rm\s+-rf\s+\//, // rm -rf /
|
|
44
|
+
/rm\s+-rf\s+~/, // rm -rf ~
|
|
45
|
+
/rm\s+-rf\s+\*/, // rm -rf *
|
|
46
|
+
/:\(\)\{.*\}/, // Fork bomb
|
|
47
|
+
/dd\s+if=.*of=\/dev/, // Disk operations
|
|
48
|
+
/mkfs/, // Format filesystem
|
|
49
|
+
/fdisk/, // Partition operations
|
|
50
|
+
/>\s*\/dev\/sd/, // Write to disk
|
|
51
|
+
/chmod\s+-R\s+777/, // Dangerous permissions
|
|
52
|
+
/curl.*\|\s*bash/, // Pipe to bash
|
|
53
|
+
/wget.*\|\s*sh/, // Pipe to shell
|
|
54
|
+
/sudo\s+rm/, // Sudo remove
|
|
55
|
+
/format\s+[A-Z]:/, // Windows format
|
|
56
|
+
/del\s+\/[FS]/, // Windows delete
|
|
57
|
+
];
|
|
58
|
+
return dangerousPatterns.some(pattern => pattern.test(command));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Ask user for permission to execute command
|
|
62
|
+
*/
|
|
63
|
+
async function askPermission(command) {
|
|
64
|
+
console.log(chalk_1.default.yellow('\n⚠️ Command detected:'));
|
|
65
|
+
console.log(chalk_1.default.cyan('─'.repeat(50)));
|
|
66
|
+
console.log(chalk_1.default.white(command.code));
|
|
67
|
+
console.log(chalk_1.default.cyan('─'.repeat(50)));
|
|
68
|
+
if (command.dangerous) {
|
|
69
|
+
console.log(chalk_1.default.red('🚨 WARNING: This command may be dangerous!'));
|
|
70
|
+
}
|
|
71
|
+
const { execute } = await inquirer_1.default.prompt([{
|
|
72
|
+
type: 'confirm',
|
|
73
|
+
name: 'execute',
|
|
74
|
+
message: command.dangerous ?
|
|
75
|
+
chalk_1.default.red('Are you SURE you want to execute this?') :
|
|
76
|
+
'Execute this command?',
|
|
77
|
+
default: false
|
|
78
|
+
}]);
|
|
79
|
+
return execute;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Execute a shell command
|
|
83
|
+
*/
|
|
84
|
+
async function executeCommand(command, shell) {
|
|
85
|
+
try {
|
|
86
|
+
const result = await execAsync(command, {
|
|
87
|
+
shell: shell || process.env.SHELL || '/bin/bash',
|
|
88
|
+
maxBuffer: 1024 * 1024 * 10, // 10MB buffer
|
|
89
|
+
timeout: 300000 // 5 minute timeout
|
|
90
|
+
});
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
throw new Error(`Command failed: ${error.message}\n${error.stderr || ''}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Execute commands with user permission
|
|
99
|
+
*/
|
|
100
|
+
async function executeWithPermission(response) {
|
|
101
|
+
const commands = extractCommands(response);
|
|
102
|
+
if (commands.length === 0) {
|
|
103
|
+
return { success: true, executed: false };
|
|
104
|
+
}
|
|
105
|
+
console.log(chalk_1.default.cyan(`\n\n🔧 Found ${commands.length} executable command(s)\n`));
|
|
106
|
+
for (let i = 0; i < commands.length; i++) {
|
|
107
|
+
const command = commands[i];
|
|
108
|
+
console.log(chalk_1.default.gray(`Command ${i + 1}/${commands.length}:`));
|
|
109
|
+
const shouldExecute = await askPermission(command);
|
|
110
|
+
if (shouldExecute) {
|
|
111
|
+
try {
|
|
112
|
+
console.log(chalk_1.default.blue('\n⏳ Executing...'));
|
|
113
|
+
const { stdout, stderr } = await executeCommand(command.code);
|
|
114
|
+
if (stdout) {
|
|
115
|
+
console.log(chalk_1.default.green('\n✓ Output:'));
|
|
116
|
+
console.log(chalk_1.default.white(stdout));
|
|
117
|
+
}
|
|
118
|
+
if (stderr) {
|
|
119
|
+
console.log(chalk_1.default.yellow('\n⚠️ Warnings:'));
|
|
120
|
+
console.log(chalk_1.default.white(stderr));
|
|
121
|
+
}
|
|
122
|
+
console.log(chalk_1.default.green('✓ Command completed successfully!\n'));
|
|
123
|
+
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
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
console.error(chalk_1.default.red(`\n✗ Error: ${error.message}\n`));
|
|
127
|
+
return { success: false, executed: true, error: error.message };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
console.log(chalk_1.default.gray('Skipped.\n'));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return { success: true, executed: false }; // Skipped all
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Command history for undo/rollback
|
|
138
|
+
*/
|
|
139
|
+
class CommandHistory {
|
|
140
|
+
constructor() {
|
|
141
|
+
this.history = [];
|
|
142
|
+
}
|
|
143
|
+
add(command, success) {
|
|
144
|
+
this.history.push({
|
|
145
|
+
command,
|
|
146
|
+
timestamp: new Date(),
|
|
147
|
+
success
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
getHistory() {
|
|
151
|
+
return this.history;
|
|
152
|
+
}
|
|
153
|
+
clear() {
|
|
154
|
+
this.history = [];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
exports.CommandHistory = CommandHistory;
|
|
158
|
+
exports.commandHistory = new CommandHistory();
|
|
159
|
+
//# sourceMappingURL=command-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-executor.js","sourceRoot":"","sources":["../../src/utils/command-executor.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/commands/code.ts
CHANGED
|
@@ -3,6 +3,7 @@ import chalk from 'chalk';
|
|
|
3
3
|
import { configManager } from '../utils/config';
|
|
4
4
|
import { MatexAPIClient } from '../api/client';
|
|
5
5
|
import { spinner } from '../utils/spinner';
|
|
6
|
+
import { executeWithPermission } from '../utils/command-executor';
|
|
6
7
|
|
|
7
8
|
export const codeCommand = new Command('code')
|
|
8
9
|
.description('Generate code with MATEXCodex (optimized for coding)')
|
|
@@ -11,6 +12,7 @@ export const codeCommand = new Command('code')
|
|
|
11
12
|
.option('-l, --language <lang>', 'Programming language (auto-detected if not specified)')
|
|
12
13
|
.option('-t, --temperature <number>', 'Temperature (0-1)', '0.3')
|
|
13
14
|
.option('--max-tokens <number>', 'Maximum tokens in response', '8000')
|
|
15
|
+
.option('-x, --execute', 'Execute commands found in response (with permission prompts)')
|
|
14
16
|
.action(async (prompt: string, options: any) => {
|
|
15
17
|
try {
|
|
16
18
|
// Check for API key
|
|
@@ -74,6 +76,11 @@ export const codeCommand = new Command('code')
|
|
|
74
76
|
console.log(chalk.green(`✅ Code saved to: ${options.output}`));
|
|
75
77
|
}
|
|
76
78
|
|
|
79
|
+
// Execute commands if requested
|
|
80
|
+
if (options.execute) {
|
|
81
|
+
await executeWithPermission(response);
|
|
82
|
+
}
|
|
83
|
+
|
|
77
84
|
} catch (error: any) {
|
|
78
85
|
spinner.fail('Code generation failed');
|
|
79
86
|
|
package/src/commands/dev.ts
CHANGED
|
@@ -4,10 +4,12 @@ import inquirer from 'inquirer';
|
|
|
4
4
|
import { configManager } from '../utils/config';
|
|
5
5
|
import { MatexAPIClient, ChatMessage } from '../api/client';
|
|
6
6
|
import { spinner } from '../utils/spinner';
|
|
7
|
+
import { executeWithPermission } from '../utils/command-executor';
|
|
7
8
|
|
|
8
9
|
export const devCommand = new Command('dev')
|
|
9
10
|
.description('Start interactive development session with MATEXCodex')
|
|
10
11
|
.option('-m, --model <model>', 'AI model to use', 'matexcodex')
|
|
12
|
+
.option('-x, --execute', 'Auto-prompt for command execution (Ollama-style)')
|
|
11
13
|
.action(async (options: any) => {
|
|
12
14
|
try {
|
|
13
15
|
// Check for API key
|
|
@@ -86,6 +88,11 @@ export const devCommand = new Command('dev')
|
|
|
86
88
|
console.log(chalk.white(response));
|
|
87
89
|
console.log();
|
|
88
90
|
|
|
91
|
+
// Execute commands if requested
|
|
92
|
+
if (options.execute) {
|
|
93
|
+
await executeWithPermission(response);
|
|
94
|
+
}
|
|
95
|
+
|
|
89
96
|
} catch (error: any) {
|
|
90
97
|
spinner.fail('Request failed');
|
|
91
98
|
console.error(chalk.red(`Error: ${error.message}\n`));
|
package/src/index.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { modelsCommand } from './commands/models';
|
|
|
9
9
|
import { codeCommand } from './commands/code';
|
|
10
10
|
import { devCommand } from './commands/dev';
|
|
11
11
|
import { configManager } from './utils/config';
|
|
12
|
-
import { MatexAPIClient } from './api/client';
|
|
12
|
+
import { MatexAPIClient, ChatMessage } from './api/client';
|
|
13
13
|
import { spinner } from './utils/spinner';
|
|
14
14
|
|
|
15
15
|
const program = new Command();
|
|
@@ -65,23 +65,75 @@ if (args.length > 0 && !args[0].startsWith('-') && !knownCommands.includes(args[
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
const client = new MatexAPIClient(apiKey, configManager.getBaseURL());
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
68
|
+
|
|
69
|
+
// Get current directory context
|
|
70
|
+
const fs = require('fs');
|
|
71
|
+
const files = fs.readdirSync(process.cwd()).slice(0, 20).join(', '); // fast list
|
|
72
|
+
const context = `Current directory: ${process.cwd()}\nFiles: ${files}`;
|
|
73
|
+
|
|
74
|
+
let messages: ChatMessage[] = [
|
|
75
|
+
{
|
|
76
|
+
role: 'system', content: `You are MATEXCodex, an expert agentic coding assistant.
|
|
77
|
+
1. Your goal is to COMPLETE the user's task.
|
|
78
|
+
2. You can execute shell commands by wrapping them in code blocks (bash, sh, zsh).
|
|
79
|
+
3. PREFER simple one-line shell commands (like 'mkdir', 'touch', 'npm install') over complex scripts.
|
|
80
|
+
4. If you need to create a file, use 'echo "content" > file.js' or similar.
|
|
81
|
+
5. If a command fails, I will send you the error - FIX IT and try again.
|
|
82
|
+
6. Look at the current directory context to avoid "file not found" errors.
|
|
83
|
+
${context}`
|
|
84
|
+
},
|
|
85
|
+
{ role: 'user', content: prompt }
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
let loopCount = 0;
|
|
89
|
+
const MAX_LOOPS = 5;
|
|
90
|
+
|
|
91
|
+
while (loopCount < MAX_LOOPS) {
|
|
92
|
+
loopCount++;
|
|
93
|
+
|
|
94
|
+
spinner.start(loopCount === 1 ? 'Generating plan...' : 'Analyzing result...');
|
|
95
|
+
|
|
96
|
+
const response = await client.chat({
|
|
97
|
+
messages,
|
|
98
|
+
model: 'matexcodex',
|
|
99
|
+
temperature: 0.3,
|
|
100
|
+
max_tokens: 8000,
|
|
101
|
+
stream: false,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
spinner.stop();
|
|
105
|
+
|
|
106
|
+
// Display response
|
|
107
|
+
console.log(chalk.cyan(`\n💻 MATEXCodex (Step ${loopCount}):\n`));
|
|
108
|
+
console.log(chalk.white(response));
|
|
109
|
+
console.log();
|
|
110
|
+
|
|
111
|
+
// Auto-execute commands (Ollama-style)
|
|
112
|
+
const { executeWithPermission } = await import('./utils/command-executor');
|
|
113
|
+
const result = await executeWithPermission(response);
|
|
114
|
+
|
|
115
|
+
if (result.executed) {
|
|
116
|
+
if (result.success) {
|
|
117
|
+
// Success!
|
|
118
|
+
if (loopCount > 1) {
|
|
119
|
+
console.log(chalk.green('✅ Fix succeeded!'));
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
} else {
|
|
123
|
+
// Failure - Loop back
|
|
124
|
+
console.log(chalk.yellow('\n↺ Command failed. Asking AI to fix...'));
|
|
125
|
+
messages.push({ role: 'assistant', content: response });
|
|
126
|
+
messages.push({
|
|
127
|
+
role: 'user',
|
|
128
|
+
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.`
|
|
129
|
+
});
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
// No command to execute - we are done
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
85
137
|
} catch (error: any) {
|
|
86
138
|
spinner.fail('Failed');
|
|
87
139
|
console.error(chalk.red(`\n❌ ${error.message}`));
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { exec } from 'child_process';
|
|
3
|
+
import { promisify } from 'util';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
|
|
6
|
+
const execAsync = promisify(exec);
|
|
7
|
+
|
|
8
|
+
export interface CommandBlock {
|
|
9
|
+
language: string;
|
|
10
|
+
code: string;
|
|
11
|
+
dangerous: boolean;
|
|
12
|
+
description?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Extract executable commands from AI response
|
|
17
|
+
*/
|
|
18
|
+
export function extractCommands(response: string): CommandBlock[] {
|
|
19
|
+
const commands: CommandBlock[] = [];
|
|
20
|
+
|
|
21
|
+
// Match code blocks with language tags
|
|
22
|
+
const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
|
|
23
|
+
let match;
|
|
24
|
+
|
|
25
|
+
while ((match = codeBlockRegex.exec(response)) !== null) {
|
|
26
|
+
const language = match[1] || 'bash';
|
|
27
|
+
const code = match[2].trim();
|
|
28
|
+
|
|
29
|
+
// Only extract shell commands
|
|
30
|
+
if (['bash', 'sh', 'zsh', 'shell', 'powershell', 'cmd'].includes(language.toLowerCase())) {
|
|
31
|
+
commands.push({
|
|
32
|
+
language,
|
|
33
|
+
code,
|
|
34
|
+
dangerous: isDangerousCommand(code)
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return commands;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Check if command is potentially dangerous
|
|
44
|
+
*/
|
|
45
|
+
function isDangerousCommand(command: string): boolean {
|
|
46
|
+
const dangerousPatterns = [
|
|
47
|
+
/rm\s+-rf\s+\//, // rm -rf /
|
|
48
|
+
/rm\s+-rf\s+~/, // rm -rf ~
|
|
49
|
+
/rm\s+-rf\s+\*/, // rm -rf *
|
|
50
|
+
/:\(\)\{.*\}/, // Fork bomb
|
|
51
|
+
/dd\s+if=.*of=\/dev/, // Disk operations
|
|
52
|
+
/mkfs/, // Format filesystem
|
|
53
|
+
/fdisk/, // Partition operations
|
|
54
|
+
/>\s*\/dev\/sd/, // Write to disk
|
|
55
|
+
/chmod\s+-R\s+777/, // Dangerous permissions
|
|
56
|
+
/curl.*\|\s*bash/, // Pipe to bash
|
|
57
|
+
/wget.*\|\s*sh/, // Pipe to shell
|
|
58
|
+
/sudo\s+rm/, // Sudo remove
|
|
59
|
+
/format\s+[A-Z]:/, // Windows format
|
|
60
|
+
/del\s+\/[FS]/, // Windows delete
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
return dangerousPatterns.some(pattern => pattern.test(command));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Ask user for permission to execute command
|
|
68
|
+
*/
|
|
69
|
+
export async function askPermission(command: CommandBlock): Promise<boolean> {
|
|
70
|
+
console.log(chalk.yellow('\n⚠️ Command detected:'));
|
|
71
|
+
console.log(chalk.cyan('─'.repeat(50)));
|
|
72
|
+
console.log(chalk.white(command.code));
|
|
73
|
+
console.log(chalk.cyan('─'.repeat(50)));
|
|
74
|
+
|
|
75
|
+
if (command.dangerous) {
|
|
76
|
+
console.log(chalk.red('🚨 WARNING: This command may be dangerous!'));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const { execute } = await inquirer.prompt([{
|
|
80
|
+
type: 'confirm',
|
|
81
|
+
name: 'execute',
|
|
82
|
+
message: command.dangerous ?
|
|
83
|
+
chalk.red('Are you SURE you want to execute this?') :
|
|
84
|
+
'Execute this command?',
|
|
85
|
+
default: false
|
|
86
|
+
}]);
|
|
87
|
+
|
|
88
|
+
return execute;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Execute a shell command
|
|
93
|
+
*/
|
|
94
|
+
export async function executeCommand(command: string, shell?: string): Promise<{ stdout: string; stderr: string }> {
|
|
95
|
+
try {
|
|
96
|
+
const result = await execAsync(command, {
|
|
97
|
+
shell: shell || process.env.SHELL || '/bin/bash',
|
|
98
|
+
maxBuffer: 1024 * 1024 * 10, // 10MB buffer
|
|
99
|
+
timeout: 300000 // 5 minute timeout
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return result;
|
|
103
|
+
} catch (error: any) {
|
|
104
|
+
throw new Error(`Command failed: ${error.message}\n${error.stderr || ''}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Execute commands with user permission
|
|
110
|
+
*/
|
|
111
|
+
export interface ExecutionResult {
|
|
112
|
+
success: boolean;
|
|
113
|
+
executed: boolean;
|
|
114
|
+
output?: string;
|
|
115
|
+
error?: string;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Execute commands with user permission
|
|
120
|
+
*/
|
|
121
|
+
export async function executeWithPermission(response: string): Promise<ExecutionResult> {
|
|
122
|
+
const commands = extractCommands(response);
|
|
123
|
+
|
|
124
|
+
if (commands.length === 0) {
|
|
125
|
+
return { success: true, executed: false };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
console.log(chalk.cyan(`\n\n🔧 Found ${commands.length} executable command(s)\n`));
|
|
129
|
+
|
|
130
|
+
for (let i = 0; i < commands.length; i++) {
|
|
131
|
+
const command = commands[i];
|
|
132
|
+
|
|
133
|
+
console.log(chalk.gray(`Command ${i + 1}/${commands.length}:`));
|
|
134
|
+
|
|
135
|
+
const shouldExecute = await askPermission(command);
|
|
136
|
+
|
|
137
|
+
if (shouldExecute) {
|
|
138
|
+
try {
|
|
139
|
+
console.log(chalk.blue('\n⏳ Executing...'));
|
|
140
|
+
|
|
141
|
+
const { stdout, stderr } = await executeCommand(command.code);
|
|
142
|
+
|
|
143
|
+
if (stdout) {
|
|
144
|
+
console.log(chalk.green('\n✓ Output:'));
|
|
145
|
+
console.log(chalk.white(stdout));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (stderr) {
|
|
149
|
+
console.log(chalk.yellow('\n⚠️ Warnings:'));
|
|
150
|
+
console.log(chalk.white(stderr));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
console.log(chalk.green('✓ Command completed successfully!\n'));
|
|
154
|
+
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
|
|
155
|
+
} catch (error: any) {
|
|
156
|
+
console.error(chalk.red(`\n✗ Error: ${error.message}\n`));
|
|
157
|
+
return { success: false, executed: true, error: error.message };
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
console.log(chalk.gray('Skipped.\n'));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return { success: true, executed: false }; // Skipped all
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Command history for undo/rollback
|
|
169
|
+
*/
|
|
170
|
+
export class CommandHistory {
|
|
171
|
+
private history: Array<{ command: string; timestamp: Date; success: boolean }> = [];
|
|
172
|
+
|
|
173
|
+
add(command: string, success: boolean) {
|
|
174
|
+
this.history.push({
|
|
175
|
+
command,
|
|
176
|
+
timestamp: new Date(),
|
|
177
|
+
success
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
getHistory() {
|
|
182
|
+
return this.history;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
clear() {
|
|
186
|
+
this.history = [];
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export const commandHistory = new CommandHistory();
|