matex-cli 1.2.9 → 1.2.11
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/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +60 -41
- package/dist/commands/dev.js.map +1 -1
- package/dist/index.js +26 -7
- package/dist/index.js.map +1 -1
- package/dist/utils/agent-orchestrator.d.ts +1 -1
- package/dist/utils/agent-orchestrator.d.ts.map +1 -1
- package/dist/utils/agent-orchestrator.js +27 -3
- package/dist/utils/agent-orchestrator.js.map +1 -1
- package/dist/utils/command-executor.d.ts +1 -1
- package/dist/utils/command-executor.d.ts.map +1 -1
- package/dist/utils/command-executor.js +27 -10
- package/dist/utils/command-executor.js.map +1 -1
- package/dist/utils/patcher.d.ts +30 -0
- package/dist/utils/patcher.d.ts.map +1 -0
- package/dist/utils/patcher.js +89 -0
- package/dist/utils/patcher.js.map +1 -0
- package/dist/utils/tui.d.ts +33 -0
- package/dist/utils/tui.d.ts.map +1 -0
- package/dist/utils/tui.js +97 -0
- package/dist/utils/tui.js.map +1 -0
- package/package.json +1 -1
- package/src/commands/dev.ts +67 -46
- package/src/index.ts +26 -7
- package/src/utils/agent-orchestrator.ts +28 -4
- package/src/utils/command-executor.ts +28 -14
- package/src/utils/patcher.ts +99 -0
- package/src/utils/tui.ts +108 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { TUI } from './tui';
|
|
5
|
+
|
|
6
|
+
export interface EditBlock {
|
|
7
|
+
filePath: string;
|
|
8
|
+
search: string;
|
|
9
|
+
replace: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class Patcher {
|
|
13
|
+
/**
|
|
14
|
+
* Parse surgical edit blocks from AI response
|
|
15
|
+
* Format:
|
|
16
|
+
* **filename**
|
|
17
|
+
* <<<< SEARCH
|
|
18
|
+
* content
|
|
19
|
+
* ====
|
|
20
|
+
* replacement
|
|
21
|
+
* >>>> REPLACE
|
|
22
|
+
*/
|
|
23
|
+
static parseEditBlocks(response: string): EditBlock[] {
|
|
24
|
+
const blocks: EditBlock[] = [];
|
|
25
|
+
// Match filename followed by search/replace block
|
|
26
|
+
const blockRegex = /\*\*([^*]+)\*\*\s*<<<< SEARCH\n([\s\S]*?)\n====\n([\s\S]*?)\n>>>> REPLACE/g;
|
|
27
|
+
|
|
28
|
+
let match;
|
|
29
|
+
while ((match = blockRegex.exec(response)) !== null) {
|
|
30
|
+
blocks.push({
|
|
31
|
+
filePath: match[1].trim(),
|
|
32
|
+
search: match[2],
|
|
33
|
+
replace: match[3]
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return blocks;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Apply a surgical patch to a file
|
|
42
|
+
*/
|
|
43
|
+
static applyPatch(block: EditBlock): { success: boolean; error?: string } {
|
|
44
|
+
TUI.drawStatusBar(`Applying Patch: ${block.filePath}...`);
|
|
45
|
+
try {
|
|
46
|
+
const fullPath = path.resolve(process.cwd(), block.filePath);
|
|
47
|
+
|
|
48
|
+
if (!fs.existsSync(fullPath)) {
|
|
49
|
+
TUI.drawStatusBar(`Error: File not found: ${block.filePath}`);
|
|
50
|
+
return { success: false, error: `File not found: ${block.filePath}` };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const content = fs.readFileSync(fullPath, 'utf8');
|
|
54
|
+
|
|
55
|
+
// Normalize line endings for comparison
|
|
56
|
+
const normalizedContent = content.replace(/\r\n/g, '\n');
|
|
57
|
+
const normalizedSearch = block.search.replace(/\r\n/g, '\n');
|
|
58
|
+
|
|
59
|
+
if (!normalizedContent.includes(normalizedSearch)) {
|
|
60
|
+
TUI.drawStatusBar(`Error: Search block not found in ${block.filePath}.`);
|
|
61
|
+
return {
|
|
62
|
+
success: false,
|
|
63
|
+
error: `Search block not found in ${block.filePath}.`
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const updatedContent = normalizedContent.replace(normalizedSearch, block.replace.replace(/\r\n/g, '\n'));
|
|
68
|
+
fs.writeFileSync(fullPath, updatedContent, 'utf8');
|
|
69
|
+
|
|
70
|
+
TUI.drawStatusBar(`Success: ${block.filePath} patched.`);
|
|
71
|
+
return { success: true };
|
|
72
|
+
} catch (err: any) {
|
|
73
|
+
TUI.drawStatusBar(`Error applying patch to ${block.filePath}: ${err.message}`);
|
|
74
|
+
return { success: false, error: err.message };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Visualize the diff in a premium "Bro" style
|
|
80
|
+
*/
|
|
81
|
+
static showDiff(block: EditBlock) {
|
|
82
|
+
process.stdout.write('\n');
|
|
83
|
+
console.log(chalk.bgCyan.black(` 💎 PROPOSED SURGICAL EDIT: ${block.filePath} `));
|
|
84
|
+
console.log(chalk.cyan('╒' + '═'.repeat(70) + '╕'));
|
|
85
|
+
|
|
86
|
+
const searchLines = block.search.split('\n');
|
|
87
|
+
const replaceLines = block.replace.split('\n');
|
|
88
|
+
|
|
89
|
+
searchLines.forEach(line => {
|
|
90
|
+
console.log(chalk.red('│ - ') + chalk.red(line));
|
|
91
|
+
});
|
|
92
|
+
console.log(chalk.gray('╞' + '┄'.repeat(70) + '╡'));
|
|
93
|
+
replaceLines.forEach(line => {
|
|
94
|
+
console.log(chalk.green('│ + ') + chalk.green(line));
|
|
95
|
+
});
|
|
96
|
+
console.log(chalk.cyan('╘' + '═'.repeat(70) + '╛'));
|
|
97
|
+
console.log();
|
|
98
|
+
}
|
|
99
|
+
}
|
package/src/utils/tui.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import readline from 'readline';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* TUI Management for MATEX CLI "God-Mode"
|
|
6
|
+
* Handles screen buffers, persistent headers, and real-time status updates.
|
|
7
|
+
*/
|
|
8
|
+
export class TUI {
|
|
9
|
+
private static isInitialized = false;
|
|
10
|
+
private static currentStatus = '';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Initialize the TUI Mode
|
|
14
|
+
*/
|
|
15
|
+
static init() {
|
|
16
|
+
if (this.isInitialized) return;
|
|
17
|
+
|
|
18
|
+
// Enter alternative screen buffer
|
|
19
|
+
process.stdout.write('\x1b[?1049h');
|
|
20
|
+
|
|
21
|
+
// Hide cursor
|
|
22
|
+
process.stdout.write('\x1b[?25l');
|
|
23
|
+
|
|
24
|
+
this.clear();
|
|
25
|
+
this.isInitialized = true;
|
|
26
|
+
|
|
27
|
+
// Ensure clean exit
|
|
28
|
+
process.on('SIGINT', () => this.exit());
|
|
29
|
+
process.on('exit', () => this.exit());
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Restore Terminal to normal state
|
|
34
|
+
*/
|
|
35
|
+
static exit() {
|
|
36
|
+
if (!this.isInitialized) return;
|
|
37
|
+
|
|
38
|
+
// Show cursor
|
|
39
|
+
process.stdout.write('\x1b[?25h');
|
|
40
|
+
|
|
41
|
+
// Exit alternative screen buffer
|
|
42
|
+
process.stdout.write('\x1b[?1049l');
|
|
43
|
+
|
|
44
|
+
this.isInitialized = false;
|
|
45
|
+
process.exit();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Clear the main viewport
|
|
50
|
+
*/
|
|
51
|
+
static clear() {
|
|
52
|
+
process.stdout.write('\x1b[2J\x1b[H');
|
|
53
|
+
this.drawHeader();
|
|
54
|
+
this.drawStatusBar(this.currentStatus);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Draw the persistent top header
|
|
59
|
+
*/
|
|
60
|
+
static drawHeader() {
|
|
61
|
+
const width = process.stdout.columns || 80;
|
|
62
|
+
const banner = ` MATEX AI :: GOD-MODE DASHBOARD `;
|
|
63
|
+
const padding = Math.max(0, Math.floor((width - banner.length) / 2));
|
|
64
|
+
|
|
65
|
+
// Move to top
|
|
66
|
+
process.stdout.write('\x1b[H');
|
|
67
|
+
console.log(chalk.bgCyan.black(' '.repeat(padding) + banner + ' '.repeat(width - banner.length - padding)));
|
|
68
|
+
console.log(chalk.gray('─'.repeat(width)));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Draw a real-time status bar at the bottom
|
|
73
|
+
*/
|
|
74
|
+
static drawStatusBar(status: string) {
|
|
75
|
+
this.currentStatus = status;
|
|
76
|
+
if (!this.isInitialized) return;
|
|
77
|
+
|
|
78
|
+
const width = process.stdout.columns || 80;
|
|
79
|
+
const height = process.stdout.rows || 24;
|
|
80
|
+
|
|
81
|
+
// Save cursor position
|
|
82
|
+
process.stdout.write('\x1b[s');
|
|
83
|
+
|
|
84
|
+
// Move to bottom line
|
|
85
|
+
process.stdout.write(`\x1b[${height};1H`);
|
|
86
|
+
|
|
87
|
+
const cleanStatus = status.substring(0, width - 10);
|
|
88
|
+
const bar = ` [⚡] ${cleanStatus} `.padEnd(width);
|
|
89
|
+
process.stdout.write(chalk.bgWhite.black(bar));
|
|
90
|
+
|
|
91
|
+
// Restore cursor position
|
|
92
|
+
process.stdout.write('\x1b[u');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Log content into the scrollable area
|
|
97
|
+
*/
|
|
98
|
+
static log(content: string) {
|
|
99
|
+
if (!this.isInitialized) {
|
|
100
|
+
console.log(content);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Since we are in an alternative buffer, standard console.log works
|
|
105
|
+
// within the viewport between header and footer.
|
|
106
|
+
console.log(content);
|
|
107
|
+
}
|
|
108
|
+
}
|