matex-cli 1.1.13 ā 1.2.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/ask.js +1 -1
- package/dist/commands/ask.js.map +1 -1
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +77 -39
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/config.js +1 -1
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +65 -33
- package/dist/commands/dev.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/agent-orchestrator.d.ts +21 -0
- package/dist/utils/agent-orchestrator.d.ts.map +1 -0
- package/dist/utils/agent-orchestrator.js +64 -0
- package/dist/utils/agent-orchestrator.js.map +1 -0
- package/dist/utils/command-executor.d.ts +4 -0
- package/dist/utils/command-executor.d.ts.map +1 -1
- package/dist/utils/command-executor.js +16 -2
- package/dist/utils/command-executor.js.map +1 -1
- package/dist/utils/config.js +1 -1
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/repo-mapper.d.ts +29 -0
- package/dist/utils/repo-mapper.d.ts.map +1 -0
- package/dist/utils/repo-mapper.js +172 -0
- package/dist/utils/repo-mapper.js.map +1 -0
- package/package.json +1 -1
- package/src/commands/ask.ts +1 -1
- package/src/commands/chat.ts +73 -39
- package/src/commands/config.ts +1 -1
- package/src/commands/dev.ts +62 -35
- package/src/index.ts +1 -1
- package/src/utils/agent-orchestrator.ts +68 -0
- package/src/utils/command-executor.ts +18 -2
- package/src/utils/config.ts +1 -1
- package/src/utils/repo-mapper.ts +156 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
|
|
3
|
+
export type AgentRole = 'Architect' | 'Syntax' | 'Frontend' | 'Backend' | 'System' | 'Commander';
|
|
4
|
+
|
|
5
|
+
export interface AgentConfig {
|
|
6
|
+
name: string;
|
|
7
|
+
icon: string;
|
|
8
|
+
color: (text: string) => string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const AGENT_CONFIGS: Record<AgentRole, AgentConfig> = {
|
|
12
|
+
Architect: {
|
|
13
|
+
name: 'MatexCodeArchitect',
|
|
14
|
+
icon: 'š§¬',
|
|
15
|
+
color: chalk.blue,
|
|
16
|
+
},
|
|
17
|
+
Syntax: {
|
|
18
|
+
name: 'SyntaxGuard',
|
|
19
|
+
icon: 'š”ļø',
|
|
20
|
+
color: chalk.yellow,
|
|
21
|
+
},
|
|
22
|
+
Frontend: {
|
|
23
|
+
name: 'VisualAgent',
|
|
24
|
+
icon: 'šØ',
|
|
25
|
+
color: chalk.magenta,
|
|
26
|
+
},
|
|
27
|
+
Backend: {
|
|
28
|
+
name: 'CoreAgent',
|
|
29
|
+
icon: 'āļø',
|
|
30
|
+
color: chalk.cyan,
|
|
31
|
+
},
|
|
32
|
+
System: {
|
|
33
|
+
name: 'Matex_Orchestrator',
|
|
34
|
+
icon: 'š§ ',
|
|
35
|
+
color: chalk.white,
|
|
36
|
+
},
|
|
37
|
+
Commander: {
|
|
38
|
+
name: 'MatexResearchCommander',
|
|
39
|
+
icon: 'š',
|
|
40
|
+
color: chalk.green,
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export class AgentOrchestrator {
|
|
45
|
+
/**
|
|
46
|
+
* Display an agent's "thought" or action
|
|
47
|
+
*/
|
|
48
|
+
static speak(role: AgentRole, message: string) {
|
|
49
|
+
const config = AGENT_CONFIGS[role];
|
|
50
|
+
console.log(`\n${config.icon} ${config.color(`${config.name}:`)} ${chalk.white(message)}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Display a collaboration transition
|
|
55
|
+
*/
|
|
56
|
+
static transition(from: AgentRole, to: AgentRole) {
|
|
57
|
+
const fromCfg = AGENT_CONFIGS[from];
|
|
58
|
+
const toCfg = AGENT_CONFIGS[to];
|
|
59
|
+
console.log(chalk.gray(` āā ${fromCfg.icon} ā ${toCfg.icon} Handover to ${toCfg.name}...`));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Clean system message
|
|
64
|
+
*/
|
|
65
|
+
static announce(message: string) {
|
|
66
|
+
console.log(chalk.bold.white(`\n⨠${message}`));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -63,13 +63,29 @@ function isDangerousCommand(command: string): boolean {
|
|
|
63
63
|
return dangerousPatterns.some(pattern => pattern.test(command));
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Check if command is safe to auto-execute
|
|
68
|
+
*/
|
|
69
|
+
export function isSafeAutoCommand(command: string): boolean {
|
|
70
|
+
const safePrefixes = ['cat ', 'ls ', 'grep ', 'find ', 'pwd', 'echo ', 'read '];
|
|
71
|
+
const trimmed = command.trim();
|
|
72
|
+
return safePrefixes.some(prefix => trimmed.startsWith(prefix));
|
|
73
|
+
}
|
|
74
|
+
|
|
66
75
|
/**
|
|
67
76
|
* Ask user for permission to execute command
|
|
68
77
|
*/
|
|
69
78
|
export async function askPermission(command: CommandBlock): Promise<boolean> {
|
|
70
|
-
// Clean Codex-style Prompt
|
|
71
|
-
// > ls -R
|
|
79
|
+
// Clean Codex-style Prompt with Multi-Agent Iconography
|
|
72
80
|
console.log();
|
|
81
|
+
|
|
82
|
+
// Check for Safe Auto-Execution
|
|
83
|
+
if (isSafeAutoCommand(command.code)) {
|
|
84
|
+
console.log(chalk.cyan('ā” Auto-Executing Safe Command: ') + chalk.white(command.code));
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.log(chalk.yellow('š”ļø SyntaxGuard ') + chalk.white('Analysis:'));
|
|
73
89
|
console.log(chalk.gray('> ') + chalk.white(command.code));
|
|
74
90
|
console.log();
|
|
75
91
|
|
package/src/utils/config.ts
CHANGED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { AgentOrchestrator } from './agent-orchestrator';
|
|
4
|
+
|
|
5
|
+
export interface RepoNode {
|
|
6
|
+
path: string;
|
|
7
|
+
type: 'file' | 'directory';
|
|
8
|
+
children?: RepoNode[];
|
|
9
|
+
summary?: string; // e.g., "Class: AuthManager, Func: login"
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class RepoMapper {
|
|
13
|
+
private rootPath: string;
|
|
14
|
+
private ignoreList: string[] = [
|
|
15
|
+
'.git', 'node_modules', 'dist', 'build', '.next', '.DS_Store',
|
|
16
|
+
'coverage', '.vercel', '.firebase', 'out', 'public'
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
constructor(rootPath: string) {
|
|
20
|
+
this.rootPath = rootPath;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Generate a hierarchical map of the repository with deep entry-point analysis
|
|
25
|
+
*/
|
|
26
|
+
public async generateMap(): Promise<string> {
|
|
27
|
+
AgentOrchestrator.speak('System', `God-Mode Research: Indexing ${this.rootPath}...`);
|
|
28
|
+
|
|
29
|
+
// 1. Identify Entry Points
|
|
30
|
+
const entryPoints = ['README.md', 'package.json', 'index.ts', 'App.tsx', 'main.go', 'requirements.txt'];
|
|
31
|
+
let entryPointContext = '\n--- CRITICAL PROJECT CONTEXT ---\n';
|
|
32
|
+
|
|
33
|
+
for (const file of entryPoints) {
|
|
34
|
+
const fullPath = path.join(this.rootPath, file);
|
|
35
|
+
if (fs.existsSync(fullPath)) {
|
|
36
|
+
const content = fs.readFileSync(fullPath, 'utf-8').slice(0, 5000); // 5KB limit for entry points
|
|
37
|
+
entryPointContext += `\nFILE: ${file}\n${content}\n----------------\n`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const tree = this.scanDirectory(this.rootPath, 0);
|
|
42
|
+
return entryPointContext + '\n--- DIRECTORY STRUCTURE ---\n' + this.formatTree(tree);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Recursive directory scan
|
|
47
|
+
*/
|
|
48
|
+
private scanDirectory(currentPath: string, depth: number): RepoNode {
|
|
49
|
+
const stats = fs.statSync(currentPath);
|
|
50
|
+
const name = path.basename(currentPath);
|
|
51
|
+
|
|
52
|
+
if (stats.isFile()) {
|
|
53
|
+
let summary = this.extractSummary(currentPath);
|
|
54
|
+
|
|
55
|
+
// Auto-read small files (< 10KB) for "Crawler" capability
|
|
56
|
+
if (stats.size < 10240) {
|
|
57
|
+
try {
|
|
58
|
+
const content = fs.readFileSync(currentPath, 'utf-8');
|
|
59
|
+
// Add content preview to summary
|
|
60
|
+
summary += `\n--- CONTENT START ---\n${content}\n--- CONTENT END ---`;
|
|
61
|
+
} catch (e) {
|
|
62
|
+
// Ignore read errors
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
path: currentPath,
|
|
68
|
+
type: 'file',
|
|
69
|
+
summary: summary
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// It's a directory
|
|
74
|
+
if (depth > 5) return { path: currentPath, type: 'directory', children: [] }; // Max depth safety
|
|
75
|
+
|
|
76
|
+
const children: RepoNode[] = [];
|
|
77
|
+
try {
|
|
78
|
+
const items = fs.readdirSync(currentPath);
|
|
79
|
+
for (const item of items) {
|
|
80
|
+
if (this.ignoreList.includes(item)) continue;
|
|
81
|
+
|
|
82
|
+
const fullPath = path.join(currentPath, item);
|
|
83
|
+
// Simple ignore check for hidden files
|
|
84
|
+
if (item.startsWith('.') && item !== '.gitignore') continue;
|
|
85
|
+
|
|
86
|
+
children.push(this.scanDirectory(fullPath, depth + 1));
|
|
87
|
+
}
|
|
88
|
+
} catch (error) {
|
|
89
|
+
// Permission denied or other error
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
path: currentPath,
|
|
94
|
+
type: 'directory',
|
|
95
|
+
children: children
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Extract key definitions (Classes, Functions) from file content
|
|
101
|
+
* A lightweight "ctags" style summary
|
|
102
|
+
*/
|
|
103
|
+
private extractSummary(filePath: string): string {
|
|
104
|
+
const ext = path.extname(filePath);
|
|
105
|
+
if (!['.ts', '.tsx', '.js', '.jsx', '.py', '.go', '.rs'].includes(ext)) return '';
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
109
|
+
const lines = content.split('\n');
|
|
110
|
+
const definitions: string[] = [];
|
|
111
|
+
|
|
112
|
+
// Very header-heavy regex matching for speed
|
|
113
|
+
for (const line of lines) {
|
|
114
|
+
const trimmed = line.trim();
|
|
115
|
+
if (trimmed.startsWith('export class ')) {
|
|
116
|
+
definitions.push(`Class: ${trimmed.split(' ')[2]}`);
|
|
117
|
+
} else if (trimmed.startsWith('function ') || trimmed.startsWith('export function ')) {
|
|
118
|
+
const funcName = trimmed.split('(')[0].split(' ').pop();
|
|
119
|
+
definitions.push(`Func: ${funcName}`);
|
|
120
|
+
} else if (trimmed.includes('const ') && trimmed.includes(' = (') && trimmed.includes('=>')) {
|
|
121
|
+
// Arrow functions
|
|
122
|
+
const parts = trimmed.split(' = ');
|
|
123
|
+
const name = parts[0].split(' ').pop();
|
|
124
|
+
if (name && /^[A-Z]/.test(name)) {
|
|
125
|
+
definitions.push(`Component: ${name}`); // React component guess
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return definitions.slice(0, 5).join(', '); // Limit to top 5
|
|
131
|
+
} catch (e) {
|
|
132
|
+
return '';
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Format the tree into a compressed string for the LLM
|
|
138
|
+
*/
|
|
139
|
+
private formatTree(node: RepoNode, indent: string = ''): string {
|
|
140
|
+
const name = path.basename(node.path);
|
|
141
|
+
let output = `${indent}${name}`;
|
|
142
|
+
|
|
143
|
+
if (node.type === 'file' && node.summary) {
|
|
144
|
+
output += ` [${node.summary}]`;
|
|
145
|
+
}
|
|
146
|
+
output += '\n';
|
|
147
|
+
|
|
148
|
+
if (node.children) {
|
|
149
|
+
for (const child of node.children) {
|
|
150
|
+
output += this.formatTree(child, indent + ' ');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return output;
|
|
155
|
+
}
|
|
156
|
+
}
|