matex-cli 1.0.1 → 1.1.1
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.map +1 -1
- package/dist/api/client.js +2 -5
- package/dist/api/client.js.map +1 -1
- package/dist/commands/code.d.ts +3 -0
- package/dist/commands/code.d.ts.map +1 -0
- package/dist/commands/code.js +94 -0
- package/dist/commands/code.js.map +1 -0
- package/dist/commands/dev.d.ts +3 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +100 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/index.js +93 -10
- package/dist/index.js.map +1 -1
- package/dist/utils/command-executor.d.ts +40 -0
- package/dist/utils/command-executor.d.ts.map +1 -0
- package/dist/utils/command-executor.js +156 -0
- package/dist/utils/command-executor.js.map +1 -0
- package/package.json +1 -1
- package/src/api/client.ts +2 -6
- package/src/commands/code.ts +99 -0
- package/src/commands/dev.ts +109 -0
- package/src/index.ts +64 -10
- package/src/utils/command-executor.ts +176 -0
package/dist/api/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,cAAc;IACvB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,MAAmE;IAcxG;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,cAAc;IACvB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,MAAmE;IAcxG;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBjD;;OAEG;YACW,uBAAuB;IA+BrC;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC;IAKjC;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;CAY3C"}
|
package/dist/api/client.js
CHANGED
|
@@ -27,11 +27,8 @@ class MatexAPIClient {
|
|
|
27
27
|
...request,
|
|
28
28
|
uid: 'cli-user', // Placeholder, backend uses API key for auth
|
|
29
29
|
});
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
return this.handleStreamingResponse(response.data);
|
|
33
|
-
}
|
|
34
|
-
return response.data;
|
|
30
|
+
// Backend always returns SSE format, parse it
|
|
31
|
+
return this.handleStreamingResponse(response.data);
|
|
35
32
|
}
|
|
36
33
|
catch (error) {
|
|
37
34
|
if (error.response) {
|
package/dist/api/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA6C;AAe7C,MAAa,cAAc;IAKvB,YAAY,MAAc,EAAE,UAAkB,0DAA0D;QACpG,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QAEvB,IAAI,CAAC,MAAM,GAAG,eAAK,CAAC,MAAM,CAAC;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,OAAO,EAAE;gBACL,WAAW,EAAE,IAAI,CAAC,MAAM;gBACxB,cAAc,EAAE,kBAAkB;aACrC;YACD,OAAO,EAAE,KAAK,EAAE,aAAa;SAChC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI,CAAC,OAAoB;QAC3B,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE;gBACpD,GAAG,OAAO;gBACV,GAAG,EAAE,UAAU,EAAE,6CAA6C;aACjE,CAAC,CAAC;YAEH,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
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.codeCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const config_1 = require("../utils/config");
|
|
10
|
+
const client_1 = require("../api/client");
|
|
11
|
+
const spinner_1 = require("../utils/spinner");
|
|
12
|
+
const command_executor_1 = require("../utils/command-executor");
|
|
13
|
+
exports.codeCommand = new commander_1.Command('code')
|
|
14
|
+
.description('Generate code with MATEXCodex (optimized for coding)')
|
|
15
|
+
.argument('<prompt>', 'What code do you need?')
|
|
16
|
+
.option('-o, --output <file>', 'Save output to file')
|
|
17
|
+
.option('-l, --language <lang>', 'Programming language (auto-detected if not specified)')
|
|
18
|
+
.option('-t, --temperature <number>', 'Temperature (0-1)', '0.3')
|
|
19
|
+
.option('--max-tokens <number>', 'Maximum tokens in response', '8000')
|
|
20
|
+
.option('-x, --execute', 'Execute commands found in response (with permission prompts)')
|
|
21
|
+
.action(async (prompt, options) => {
|
|
22
|
+
try {
|
|
23
|
+
// Check for API key
|
|
24
|
+
const apiKey = config_1.configManager.getAPIKey();
|
|
25
|
+
if (!apiKey) {
|
|
26
|
+
console.error(chalk_1.default.red('❌ No API key configured.'));
|
|
27
|
+
console.log(chalk_1.default.yellow('Run: matex config set-key <your-api-key>'));
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
// Create API client
|
|
31
|
+
const client = new client_1.MatexAPIClient(apiKey, config_1.configManager.getBaseURL());
|
|
32
|
+
// Enhance prompt for code generation
|
|
33
|
+
let enhancedPrompt = prompt;
|
|
34
|
+
if (options.language) {
|
|
35
|
+
enhancedPrompt = `Generate ${options.language} code: ${prompt}`;
|
|
36
|
+
}
|
|
37
|
+
// Show thinking indicator
|
|
38
|
+
spinner_1.spinner.start('Generating code with MATEXCodex...');
|
|
39
|
+
// Send request (always use matexcodex for code command)
|
|
40
|
+
const response = await client.chat({
|
|
41
|
+
messages: [
|
|
42
|
+
{ role: 'system', content: 'You are MATEXCodex, an expert coding assistant. Generate clean, production-ready code with comments and best practices. Always include complete, working code.' },
|
|
43
|
+
{ role: 'user', content: enhancedPrompt }
|
|
44
|
+
],
|
|
45
|
+
model: 'matexcodex',
|
|
46
|
+
temperature: parseFloat(options.temperature),
|
|
47
|
+
max_tokens: parseInt(options.maxTokens),
|
|
48
|
+
stream: false,
|
|
49
|
+
});
|
|
50
|
+
spinner_1.spinner.succeed('Code generated!');
|
|
51
|
+
// Display response
|
|
52
|
+
console.log(chalk_1.default.cyan('\n💻 MATEXCodex:\n'));
|
|
53
|
+
console.log(chalk_1.default.white(response));
|
|
54
|
+
console.log();
|
|
55
|
+
// Save to file if requested
|
|
56
|
+
if (options.output) {
|
|
57
|
+
const fs = require('fs');
|
|
58
|
+
const path = require('path');
|
|
59
|
+
// Ensure directory exists
|
|
60
|
+
const dir = path.dirname(options.output);
|
|
61
|
+
if (!fs.existsSync(dir) && dir !== '.') {
|
|
62
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
63
|
+
}
|
|
64
|
+
// Extract code from response (remove markdown if present)
|
|
65
|
+
let codeContent = response;
|
|
66
|
+
const codeBlockMatch = response.match(/```[\w]*\n([\s\S]*?)```/);
|
|
67
|
+
if (codeBlockMatch) {
|
|
68
|
+
codeContent = codeBlockMatch[1];
|
|
69
|
+
}
|
|
70
|
+
fs.writeFileSync(options.output, codeContent.trim());
|
|
71
|
+
console.log(chalk_1.default.green(`✅ Code saved to: ${options.output}`));
|
|
72
|
+
}
|
|
73
|
+
// Execute commands if requested
|
|
74
|
+
if (options.execute) {
|
|
75
|
+
await (0, command_executor_1.executeWithPermission)(response);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
spinner_1.spinner.fail('Code generation failed');
|
|
80
|
+
if (error.message.includes('403')) {
|
|
81
|
+
console.error(chalk_1.default.red('\n❌ Invalid or revoked API key.'));
|
|
82
|
+
console.log(chalk_1.default.yellow('Please check your API key or generate a new one from the MATEX AI platform.'));
|
|
83
|
+
}
|
|
84
|
+
else if (error.message.includes('429')) {
|
|
85
|
+
console.error(chalk_1.default.red('\n❌ Rate limit exceeded.'));
|
|
86
|
+
console.log(chalk_1.default.yellow('Please wait a moment before trying again.'));
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
console.error(chalk_1.default.red(`\n❌ Error: ${error.message}`));
|
|
90
|
+
}
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
//# sourceMappingURL=code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/commands/code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
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.devCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
|
+
const config_1 = require("../utils/config");
|
|
11
|
+
const client_1 = require("../api/client");
|
|
12
|
+
const spinner_1 = require("../utils/spinner");
|
|
13
|
+
const command_executor_1 = require("../utils/command-executor");
|
|
14
|
+
exports.devCommand = new commander_1.Command('dev')
|
|
15
|
+
.description('Start interactive development session with MATEXCodex')
|
|
16
|
+
.option('-m, --model <model>', 'AI model to use', 'matexcodex')
|
|
17
|
+
.option('-x, --execute', 'Auto-prompt for command execution (Ollama-style)')
|
|
18
|
+
.action(async (options) => {
|
|
19
|
+
try {
|
|
20
|
+
// Check for API key
|
|
21
|
+
const apiKey = config_1.configManager.getAPIKey();
|
|
22
|
+
if (!apiKey) {
|
|
23
|
+
console.error(chalk_1.default.red('❌ No API key configured.'));
|
|
24
|
+
console.log(chalk_1.default.yellow('Run: matex config set-key <your-api-key>'));
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
// Create API client
|
|
28
|
+
const client = new client_1.MatexAPIClient(apiKey, config_1.configManager.getBaseURL());
|
|
29
|
+
// Welcome message
|
|
30
|
+
console.log(chalk_1.default.cyan.bold('\n🚀 MATEX Development Session'));
|
|
31
|
+
console.log(chalk_1.default.gray('━'.repeat(50)));
|
|
32
|
+
console.log(chalk_1.default.white(`Model: ${chalk_1.default.cyan(options.model)}`));
|
|
33
|
+
console.log(chalk_1.default.gray('Type your requests, or "exit" to quit\n'));
|
|
34
|
+
// Conversation history
|
|
35
|
+
const messages = [
|
|
36
|
+
{
|
|
37
|
+
role: 'system',
|
|
38
|
+
content: 'You are MATEXCodex, an expert software development assistant. Help the user build their application step by step. Provide complete, production-ready code with explanations. Be concise but thorough.'
|
|
39
|
+
}
|
|
40
|
+
];
|
|
41
|
+
// Interactive loop
|
|
42
|
+
let continueChat = true;
|
|
43
|
+
while (continueChat) {
|
|
44
|
+
// Get user input
|
|
45
|
+
const { userInput } = await inquirer_1.default.prompt([
|
|
46
|
+
{
|
|
47
|
+
type: 'input',
|
|
48
|
+
name: 'userInput',
|
|
49
|
+
message: chalk_1.default.cyan('You:'),
|
|
50
|
+
prefix: ''
|
|
51
|
+
}
|
|
52
|
+
]);
|
|
53
|
+
// Check for exit
|
|
54
|
+
if (userInput.toLowerCase() === 'exit' || userInput.toLowerCase() === 'quit') {
|
|
55
|
+
console.log(chalk_1.default.yellow('\n👋 Ending development session. Happy coding!\n'));
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
// Skip empty input
|
|
59
|
+
if (!userInput.trim()) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
// Add user message to history
|
|
63
|
+
messages.push({ role: 'user', content: userInput });
|
|
64
|
+
// Show thinking indicator
|
|
65
|
+
spinner_1.spinner.start('Thinking...');
|
|
66
|
+
try {
|
|
67
|
+
// Send request
|
|
68
|
+
const response = await client.chat({
|
|
69
|
+
messages,
|
|
70
|
+
model: options.model,
|
|
71
|
+
temperature: 0.3,
|
|
72
|
+
max_tokens: 8000,
|
|
73
|
+
stream: false,
|
|
74
|
+
});
|
|
75
|
+
spinner_1.spinner.stop();
|
|
76
|
+
// Add assistant response to history
|
|
77
|
+
messages.push({ role: 'assistant', content: response });
|
|
78
|
+
// Display response
|
|
79
|
+
console.log(chalk_1.default.green('\nMATEXCodex:'));
|
|
80
|
+
console.log(chalk_1.default.white(response));
|
|
81
|
+
console.log();
|
|
82
|
+
// Execute commands if requested
|
|
83
|
+
if (options.execute) {
|
|
84
|
+
await (0, command_executor_1.executeWithPermission)(response);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
spinner_1.spinner.fail('Request failed');
|
|
89
|
+
console.error(chalk_1.default.red(`Error: ${error.message}\n`));
|
|
90
|
+
// Remove the failed user message
|
|
91
|
+
messages.pop();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
console.error(chalk_1.default.red(`\n❌ Error: ${error.message}`));
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
//# sourceMappingURL=dev.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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
|
};
|
|
@@ -10,11 +43,16 @@ const config_1 = require("./commands/config");
|
|
|
10
43
|
const ask_1 = require("./commands/ask");
|
|
11
44
|
const chat_1 = require("./commands/chat");
|
|
12
45
|
const models_1 = require("./commands/models");
|
|
46
|
+
const code_1 = require("./commands/code");
|
|
47
|
+
const dev_1 = require("./commands/dev");
|
|
48
|
+
const config_2 = require("./utils/config");
|
|
49
|
+
const client_1 = require("./api/client");
|
|
50
|
+
const spinner_1 = require("./utils/spinner");
|
|
13
51
|
const program = new commander_1.Command();
|
|
14
52
|
program
|
|
15
53
|
.name('matex')
|
|
16
54
|
.description('Official CLI tool for MATEX AI - Access powerful AI models from your terminal')
|
|
17
|
-
.version('1.0.
|
|
55
|
+
.version('1.0.2');
|
|
18
56
|
// ASCII Art Banner
|
|
19
57
|
const banner = `
|
|
20
58
|
${chalk_1.default.cyan('╔═══════════════════════════════════════╗')}
|
|
@@ -26,9 +64,9 @@ program.on('--help', () => {
|
|
|
26
64
|
console.log(banner);
|
|
27
65
|
console.log(chalk_1.default.gray('\nExamples:'));
|
|
28
66
|
console.log(chalk_1.default.white(' $ matex config set-key sk-matex-xxxxx'));
|
|
29
|
-
console.log(chalk_1.default.white(' $ matex
|
|
30
|
-
console.log(chalk_1.default.white(' $ matex
|
|
31
|
-
console.log(chalk_1.default.white(' $ matex
|
|
67
|
+
console.log(chalk_1.default.white(' $ matex code "Create a React login component"'));
|
|
68
|
+
console.log(chalk_1.default.white(' $ matex dev'));
|
|
69
|
+
console.log(chalk_1.default.white(' $ matex "build a todo app" # Direct input'));
|
|
32
70
|
console.log();
|
|
33
71
|
console.log(chalk_1.default.gray('Get your API key from: ') + chalk_1.default.cyan('https://matexai.space/platform'));
|
|
34
72
|
console.log();
|
|
@@ -38,11 +76,56 @@ program.addCommand(config_1.configCommand);
|
|
|
38
76
|
program.addCommand(ask_1.askCommand);
|
|
39
77
|
program.addCommand(chat_1.chatCommand);
|
|
40
78
|
program.addCommand(models_1.modelsCommand);
|
|
41
|
-
|
|
42
|
-
program.
|
|
43
|
-
//
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
79
|
+
program.addCommand(code_1.codeCommand);
|
|
80
|
+
program.addCommand(dev_1.devCommand);
|
|
81
|
+
// Handle direct input (no subcommand)
|
|
82
|
+
const args = process.argv.slice(2);
|
|
83
|
+
const knownCommands = ['config', 'ask', 'chat', 'models', 'code', 'dev', 'help', '--help', '-h', '--version', '-V'];
|
|
84
|
+
if (args.length > 0 && !args[0].startsWith('-') && !knownCommands.includes(args[0])) {
|
|
85
|
+
// Direct input mode - treat as code generation
|
|
86
|
+
const prompt = args.join(' ');
|
|
87
|
+
(async () => {
|
|
88
|
+
try {
|
|
89
|
+
const apiKey = config_2.configManager.getAPIKey();
|
|
90
|
+
if (!apiKey) {
|
|
91
|
+
console.error(chalk_1.default.red('❌ No API key configured.'));
|
|
92
|
+
console.log(chalk_1.default.yellow('Run: matex config set-key <your-api-key>'));
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
const client = new client_1.MatexAPIClient(apiKey, config_2.configManager.getBaseURL());
|
|
96
|
+
spinner_1.spinner.start('Generating with MATEXCodex...');
|
|
97
|
+
const response = await client.chat({
|
|
98
|
+
messages: [
|
|
99
|
+
{ role: 'system', content: 'You are MATEXCodex, an expert coding assistant. Provide complete, production-ready code with explanations.' },
|
|
100
|
+
{ role: 'user', content: prompt }
|
|
101
|
+
],
|
|
102
|
+
model: 'matexcodex',
|
|
103
|
+
temperature: 0.3,
|
|
104
|
+
max_tokens: 8000,
|
|
105
|
+
stream: false,
|
|
106
|
+
});
|
|
107
|
+
spinner_1.spinner.succeed('Done!');
|
|
108
|
+
console.log(chalk_1.default.cyan('\n💻 MATEXCodex:\n'));
|
|
109
|
+
console.log(chalk_1.default.white(response));
|
|
110
|
+
console.log();
|
|
111
|
+
// Auto-execute commands (Ollama-style)
|
|
112
|
+
const { executeWithPermission } = await Promise.resolve().then(() => __importStar(require('./utils/command-executor')));
|
|
113
|
+
await executeWithPermission(response);
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
spinner_1.spinner.fail('Failed');
|
|
117
|
+
console.error(chalk_1.default.red(`\n❌ ${error.message}`));
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
})();
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
// Parse arguments normally
|
|
124
|
+
program.parse(process.argv);
|
|
125
|
+
// Show help if no command provided
|
|
126
|
+
if (!args.length) {
|
|
127
|
+
console.log(banner);
|
|
128
|
+
program.outputHelp();
|
|
129
|
+
}
|
|
47
130
|
}
|
|
48
131
|
//# sourceMappingURL=index.js.map
|
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,40 @@
|
|
|
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 declare function executeWithPermission(response: string): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Command history for undo/rollback
|
|
28
|
+
*/
|
|
29
|
+
export declare class CommandHistory {
|
|
30
|
+
private history;
|
|
31
|
+
add(command: string, success: boolean): void;
|
|
32
|
+
getHistory(): {
|
|
33
|
+
command: string;
|
|
34
|
+
timestamp: Date;
|
|
35
|
+
success: boolean;
|
|
36
|
+
}[];
|
|
37
|
+
clear(): void;
|
|
38
|
+
}
|
|
39
|
+
export declare const commandHistory: CommandHistory;
|
|
40
|
+
//# 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,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwC3E;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,156 @@
|
|
|
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;
|
|
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
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
console.error(chalk_1.default.red(`\n✗ Error: ${error.message}\n`));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
console.log(chalk_1.default.gray('Skipped.\n'));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Command history for undo/rollback
|
|
135
|
+
*/
|
|
136
|
+
class CommandHistory {
|
|
137
|
+
constructor() {
|
|
138
|
+
this.history = [];
|
|
139
|
+
}
|
|
140
|
+
add(command, success) {
|
|
141
|
+
this.history.push({
|
|
142
|
+
command,
|
|
143
|
+
timestamp: new Date(),
|
|
144
|
+
success
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
getHistory() {
|
|
148
|
+
return this.history;
|
|
149
|
+
}
|
|
150
|
+
clear() {
|
|
151
|
+
this.history = [];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
exports.CommandHistory = CommandHistory;
|
|
155
|
+
exports.commandHistory = new CommandHistory();
|
|
156
|
+
//# 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/api/client.ts
CHANGED
|
@@ -42,12 +42,8 @@ export class MatexAPIClient {
|
|
|
42
42
|
uid: 'cli-user', // Placeholder, backend uses API key for auth
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
return this.handleStreamingResponse(response.data);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return response.data;
|
|
45
|
+
// Backend always returns SSE format, parse it
|
|
46
|
+
return this.handleStreamingResponse(response.data);
|
|
51
47
|
} catch (error: any) {
|
|
52
48
|
if (error.response) {
|
|
53
49
|
throw new Error(`API Error: ${error.response.data.detail || error.response.statusText}`);
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { configManager } from '../utils/config';
|
|
4
|
+
import { MatexAPIClient } from '../api/client';
|
|
5
|
+
import { spinner } from '../utils/spinner';
|
|
6
|
+
import { executeWithPermission } from '../utils/command-executor';
|
|
7
|
+
|
|
8
|
+
export const codeCommand = new Command('code')
|
|
9
|
+
.description('Generate code with MATEXCodex (optimized for coding)')
|
|
10
|
+
.argument('<prompt>', 'What code do you need?')
|
|
11
|
+
.option('-o, --output <file>', 'Save output to file')
|
|
12
|
+
.option('-l, --language <lang>', 'Programming language (auto-detected if not specified)')
|
|
13
|
+
.option('-t, --temperature <number>', 'Temperature (0-1)', '0.3')
|
|
14
|
+
.option('--max-tokens <number>', 'Maximum tokens in response', '8000')
|
|
15
|
+
.option('-x, --execute', 'Execute commands found in response (with permission prompts)')
|
|
16
|
+
.action(async (prompt: string, options: any) => {
|
|
17
|
+
try {
|
|
18
|
+
// Check for API key
|
|
19
|
+
const apiKey = configManager.getAPIKey();
|
|
20
|
+
if (!apiKey) {
|
|
21
|
+
console.error(chalk.red('❌ No API key configured.'));
|
|
22
|
+
console.log(chalk.yellow('Run: matex config set-key <your-api-key>'));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Create API client
|
|
27
|
+
const client = new MatexAPIClient(apiKey, configManager.getBaseURL());
|
|
28
|
+
|
|
29
|
+
// Enhance prompt for code generation
|
|
30
|
+
let enhancedPrompt = prompt;
|
|
31
|
+
if (options.language) {
|
|
32
|
+
enhancedPrompt = `Generate ${options.language} code: ${prompt}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Show thinking indicator
|
|
36
|
+
spinner.start('Generating code with MATEXCodex...');
|
|
37
|
+
|
|
38
|
+
// Send request (always use matexcodex for code command)
|
|
39
|
+
const response = await client.chat({
|
|
40
|
+
messages: [
|
|
41
|
+
{ role: 'system', content: 'You are MATEXCodex, an expert coding assistant. Generate clean, production-ready code with comments and best practices. Always include complete, working code.' },
|
|
42
|
+
{ role: 'user', content: enhancedPrompt }
|
|
43
|
+
],
|
|
44
|
+
model: 'matexcodex',
|
|
45
|
+
temperature: parseFloat(options.temperature),
|
|
46
|
+
max_tokens: parseInt(options.maxTokens),
|
|
47
|
+
stream: false,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
spinner.succeed('Code generated!');
|
|
51
|
+
|
|
52
|
+
// Display response
|
|
53
|
+
console.log(chalk.cyan('\n💻 MATEXCodex:\n'));
|
|
54
|
+
console.log(chalk.white(response));
|
|
55
|
+
console.log();
|
|
56
|
+
|
|
57
|
+
// Save to file if requested
|
|
58
|
+
if (options.output) {
|
|
59
|
+
const fs = require('fs');
|
|
60
|
+
const path = require('path');
|
|
61
|
+
|
|
62
|
+
// Ensure directory exists
|
|
63
|
+
const dir = path.dirname(options.output);
|
|
64
|
+
if (!fs.existsSync(dir) && dir !== '.') {
|
|
65
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Extract code from response (remove markdown if present)
|
|
69
|
+
let codeContent = response;
|
|
70
|
+
const codeBlockMatch = response.match(/```[\w]*\n([\s\S]*?)```/);
|
|
71
|
+
if (codeBlockMatch) {
|
|
72
|
+
codeContent = codeBlockMatch[1];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
fs.writeFileSync(options.output, codeContent.trim());
|
|
76
|
+
console.log(chalk.green(`✅ Code saved to: ${options.output}`));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Execute commands if requested
|
|
80
|
+
if (options.execute) {
|
|
81
|
+
await executeWithPermission(response);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
} catch (error: any) {
|
|
85
|
+
spinner.fail('Code generation failed');
|
|
86
|
+
|
|
87
|
+
if (error.message.includes('403')) {
|
|
88
|
+
console.error(chalk.red('\n❌ Invalid or revoked API key.'));
|
|
89
|
+
console.log(chalk.yellow('Please check your API key or generate a new one from the MATEX AI platform.'));
|
|
90
|
+
} else if (error.message.includes('429')) {
|
|
91
|
+
console.error(chalk.red('\n❌ Rate limit exceeded.'));
|
|
92
|
+
console.log(chalk.yellow('Please wait a moment before trying again.'));
|
|
93
|
+
} else {
|
|
94
|
+
console.error(chalk.red(`\n❌ Error: ${error.message}`));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import { configManager } from '../utils/config';
|
|
5
|
+
import { MatexAPIClient, ChatMessage } from '../api/client';
|
|
6
|
+
import { spinner } from '../utils/spinner';
|
|
7
|
+
import { executeWithPermission } from '../utils/command-executor';
|
|
8
|
+
|
|
9
|
+
export const devCommand = new Command('dev')
|
|
10
|
+
.description('Start interactive development session with MATEXCodex')
|
|
11
|
+
.option('-m, --model <model>', 'AI model to use', 'matexcodex')
|
|
12
|
+
.option('-x, --execute', 'Auto-prompt for command execution (Ollama-style)')
|
|
13
|
+
.action(async (options: any) => {
|
|
14
|
+
try {
|
|
15
|
+
// Check for API key
|
|
16
|
+
const apiKey = configManager.getAPIKey();
|
|
17
|
+
if (!apiKey) {
|
|
18
|
+
console.error(chalk.red('❌ No API key configured.'));
|
|
19
|
+
console.log(chalk.yellow('Run: matex config set-key <your-api-key>'));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Create API client
|
|
24
|
+
const client = new MatexAPIClient(apiKey, configManager.getBaseURL());
|
|
25
|
+
|
|
26
|
+
// Welcome message
|
|
27
|
+
console.log(chalk.cyan.bold('\n🚀 MATEX Development Session'));
|
|
28
|
+
console.log(chalk.gray('━'.repeat(50)));
|
|
29
|
+
console.log(chalk.white(`Model: ${chalk.cyan(options.model)}`));
|
|
30
|
+
console.log(chalk.gray('Type your requests, or "exit" to quit\n'));
|
|
31
|
+
|
|
32
|
+
// Conversation history
|
|
33
|
+
const messages: ChatMessage[] = [
|
|
34
|
+
{
|
|
35
|
+
role: 'system',
|
|
36
|
+
content: 'You are MATEXCodex, an expert software development assistant. Help the user build their application step by step. Provide complete, production-ready code with explanations. Be concise but thorough.'
|
|
37
|
+
}
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
// Interactive loop
|
|
41
|
+
let continueChat = true;
|
|
42
|
+
|
|
43
|
+
while (continueChat) {
|
|
44
|
+
// Get user input
|
|
45
|
+
const { userInput } = await inquirer.prompt([
|
|
46
|
+
{
|
|
47
|
+
type: 'input',
|
|
48
|
+
name: 'userInput',
|
|
49
|
+
message: chalk.cyan('You:'),
|
|
50
|
+
prefix: ''
|
|
51
|
+
}
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
// Check for exit
|
|
55
|
+
if (userInput.toLowerCase() === 'exit' || userInput.toLowerCase() === 'quit') {
|
|
56
|
+
console.log(chalk.yellow('\n👋 Ending development session. Happy coding!\n'));
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Skip empty input
|
|
61
|
+
if (!userInput.trim()) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Add user message to history
|
|
66
|
+
messages.push({ role: 'user', content: userInput });
|
|
67
|
+
|
|
68
|
+
// Show thinking indicator
|
|
69
|
+
spinner.start('Thinking...');
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
// Send request
|
|
73
|
+
const response = await client.chat({
|
|
74
|
+
messages,
|
|
75
|
+
model: options.model,
|
|
76
|
+
temperature: 0.3,
|
|
77
|
+
max_tokens: 8000,
|
|
78
|
+
stream: false,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
spinner.stop();
|
|
82
|
+
|
|
83
|
+
// Add assistant response to history
|
|
84
|
+
messages.push({ role: 'assistant', content: response });
|
|
85
|
+
|
|
86
|
+
// Display response
|
|
87
|
+
console.log(chalk.green('\nMATEXCodex:'));
|
|
88
|
+
console.log(chalk.white(response));
|
|
89
|
+
console.log();
|
|
90
|
+
|
|
91
|
+
// Execute commands if requested
|
|
92
|
+
if (options.execute) {
|
|
93
|
+
await executeWithPermission(response);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
} catch (error: any) {
|
|
97
|
+
spinner.fail('Request failed');
|
|
98
|
+
console.error(chalk.red(`Error: ${error.message}\n`));
|
|
99
|
+
|
|
100
|
+
// Remove the failed user message
|
|
101
|
+
messages.pop();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
} catch (error: any) {
|
|
106
|
+
console.error(chalk.red(`\n❌ Error: ${error.message}`));
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -6,13 +6,18 @@ import { configCommand } from './commands/config';
|
|
|
6
6
|
import { askCommand } from './commands/ask';
|
|
7
7
|
import { chatCommand } from './commands/chat';
|
|
8
8
|
import { modelsCommand } from './commands/models';
|
|
9
|
+
import { codeCommand } from './commands/code';
|
|
10
|
+
import { devCommand } from './commands/dev';
|
|
11
|
+
import { configManager } from './utils/config';
|
|
12
|
+
import { MatexAPIClient } from './api/client';
|
|
13
|
+
import { spinner } from './utils/spinner';
|
|
9
14
|
|
|
10
15
|
const program = new Command();
|
|
11
16
|
|
|
12
17
|
program
|
|
13
18
|
.name('matex')
|
|
14
19
|
.description('Official CLI tool for MATEX AI - Access powerful AI models from your terminal')
|
|
15
|
-
.version('1.0.
|
|
20
|
+
.version('1.0.2');
|
|
16
21
|
|
|
17
22
|
// ASCII Art Banner
|
|
18
23
|
const banner = `
|
|
@@ -26,9 +31,9 @@ program.on('--help', () => {
|
|
|
26
31
|
console.log(banner);
|
|
27
32
|
console.log(chalk.gray('\nExamples:'));
|
|
28
33
|
console.log(chalk.white(' $ matex config set-key sk-matex-xxxxx'));
|
|
29
|
-
console.log(chalk.white(' $ matex
|
|
30
|
-
console.log(chalk.white(' $ matex
|
|
31
|
-
console.log(chalk.white(' $ matex
|
|
34
|
+
console.log(chalk.white(' $ matex code "Create a React login component"'));
|
|
35
|
+
console.log(chalk.white(' $ matex dev'));
|
|
36
|
+
console.log(chalk.white(' $ matex "build a todo app" # Direct input'))
|
|
32
37
|
console.log();
|
|
33
38
|
console.log(chalk.gray('Get your API key from: ') + chalk.cyan('https://matexai.space/platform'));
|
|
34
39
|
console.log();
|
|
@@ -39,12 +44,61 @@ program.addCommand(configCommand);
|
|
|
39
44
|
program.addCommand(askCommand);
|
|
40
45
|
program.addCommand(chatCommand);
|
|
41
46
|
program.addCommand(modelsCommand);
|
|
47
|
+
program.addCommand(codeCommand);
|
|
48
|
+
program.addCommand(devCommand);
|
|
42
49
|
|
|
43
|
-
//
|
|
44
|
-
|
|
50
|
+
// Handle direct input (no subcommand)
|
|
51
|
+
const args = process.argv.slice(2);
|
|
52
|
+
const knownCommands = ['config', 'ask', 'chat', 'models', 'code', 'dev', 'help', '--help', '-h', '--version', '-V'];
|
|
45
53
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
54
|
+
if (args.length > 0 && !args[0].startsWith('-') && !knownCommands.includes(args[0])) {
|
|
55
|
+
// Direct input mode - treat as code generation
|
|
56
|
+
const prompt = args.join(' ');
|
|
57
|
+
|
|
58
|
+
(async () => {
|
|
59
|
+
try {
|
|
60
|
+
const apiKey = configManager.getAPIKey();
|
|
61
|
+
if (!apiKey) {
|
|
62
|
+
console.error(chalk.red('❌ No API key configured.'));
|
|
63
|
+
console.log(chalk.yellow('Run: matex config set-key <your-api-key>'));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const client = new MatexAPIClient(apiKey, configManager.getBaseURL());
|
|
68
|
+
spinner.start('Generating with MATEXCodex...');
|
|
69
|
+
|
|
70
|
+
const response = await client.chat({
|
|
71
|
+
messages: [
|
|
72
|
+
{ role: 'system', content: 'You are MATEXCodex, an expert coding assistant. Provide complete, production-ready code with explanations.' },
|
|
73
|
+
{ role: 'user', content: prompt }
|
|
74
|
+
],
|
|
75
|
+
model: 'matexcodex',
|
|
76
|
+
temperature: 0.3,
|
|
77
|
+
max_tokens: 8000,
|
|
78
|
+
stream: false,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
spinner.succeed('Done!');
|
|
82
|
+
console.log(chalk.cyan('\n💻 MATEXCodex:\n'));
|
|
83
|
+
console.log(chalk.white(response));
|
|
84
|
+
console.log();
|
|
85
|
+
|
|
86
|
+
// Auto-execute commands (Ollama-style)
|
|
87
|
+
const { executeWithPermission } = await import('./utils/command-executor');
|
|
88
|
+
await executeWithPermission(response);
|
|
89
|
+
} catch (error: any) {
|
|
90
|
+
spinner.fail('Failed');
|
|
91
|
+
console.error(chalk.red(`\n❌ ${error.message}`));
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
})();
|
|
95
|
+
} else {
|
|
96
|
+
// Parse arguments normally
|
|
97
|
+
program.parse(process.argv);
|
|
98
|
+
|
|
99
|
+
// Show help if no command provided
|
|
100
|
+
if (!args.length) {
|
|
101
|
+
console.log(banner);
|
|
102
|
+
program.outputHelp();
|
|
103
|
+
}
|
|
50
104
|
}
|
|
@@ -0,0 +1,176 @@
|
|
|
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 async function executeWithPermission(response: string): Promise<void> {
|
|
112
|
+
const commands = extractCommands(response);
|
|
113
|
+
|
|
114
|
+
if (commands.length === 0) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log(chalk.cyan(`\n\n🔧 Found ${commands.length} executable command(s)\n`));
|
|
119
|
+
|
|
120
|
+
for (let i = 0; i < commands.length; i++) {
|
|
121
|
+
const command = commands[i];
|
|
122
|
+
|
|
123
|
+
console.log(chalk.gray(`Command ${i + 1}/${commands.length}:`));
|
|
124
|
+
|
|
125
|
+
const shouldExecute = await askPermission(command);
|
|
126
|
+
|
|
127
|
+
if (shouldExecute) {
|
|
128
|
+
try {
|
|
129
|
+
console.log(chalk.blue('\n⏳ Executing...'));
|
|
130
|
+
|
|
131
|
+
const { stdout, stderr } = await executeCommand(command.code);
|
|
132
|
+
|
|
133
|
+
if (stdout) {
|
|
134
|
+
console.log(chalk.green('\n✓ Output:'));
|
|
135
|
+
console.log(chalk.white(stdout));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (stderr) {
|
|
139
|
+
console.log(chalk.yellow('\n⚠️ Warnings:'));
|
|
140
|
+
console.log(chalk.white(stderr));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
console.log(chalk.green('✓ Command completed successfully!\n'));
|
|
144
|
+
} catch (error: any) {
|
|
145
|
+
console.error(chalk.red(`\n✗ Error: ${error.message}\n`));
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
console.log(chalk.gray('Skipped.\n'));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Command history for undo/rollback
|
|
155
|
+
*/
|
|
156
|
+
export class CommandHistory {
|
|
157
|
+
private history: Array<{ command: string; timestamp: Date; success: boolean }> = [];
|
|
158
|
+
|
|
159
|
+
add(command: string, success: boolean) {
|
|
160
|
+
this.history.push({
|
|
161
|
+
command,
|
|
162
|
+
timestamp: new Date(),
|
|
163
|
+
success
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
getHistory() {
|
|
168
|
+
return this.history;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
clear() {
|
|
172
|
+
this.history = [];
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export const commandHistory = new CommandHistory();
|