tmpa-cli 1.0.16 → 1.0.17
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/bin/index.js +70 -42
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -4,7 +4,7 @@ const readline = require('readline');
|
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const os = require('os');
|
|
7
|
-
const { execSync
|
|
7
|
+
const { execSync } = require('child_process');
|
|
8
8
|
|
|
9
9
|
// Base Paths
|
|
10
10
|
const TMPA_DIR = path.join(os.homedir(), '.tmpa');
|
|
@@ -43,7 +43,6 @@ const PROVIDERS = {
|
|
|
43
43
|
'7': { name: 'Custom / Auto-Detect', endpoint: '', defaultModel: '' }
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
-
// Config & Registry Helpers
|
|
47
46
|
function loadConfig() {
|
|
48
47
|
if (fs.existsSync(CONFIG_FILE)) {
|
|
49
48
|
try { return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')); } catch (e) { return {}; }
|
|
@@ -66,7 +65,6 @@ function saveRegistry(registry) {
|
|
|
66
65
|
fs.writeFileSync(REGISTRY_FILE, JSON.stringify(registry, null, 2));
|
|
67
66
|
}
|
|
68
67
|
|
|
69
|
-
// UI Popup Card Helper
|
|
70
68
|
function drawBox(title, contentLines, borderColor = C.cyan) {
|
|
71
69
|
const width = 64;
|
|
72
70
|
console.log(`${borderColor}┌${'─'.repeat(width - 2)}┐${C.reset}`);
|
|
@@ -92,47 +90,88 @@ ${C.c3} ██║ ██║╚██╔╝██║██╔═══╝ █
|
|
|
92
90
|
${C.c4} ██║ ██║ ╚═╝ ██║██║ ██║ ██║${C.reset}
|
|
93
91
|
${C.c4} ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝${C.reset}
|
|
94
92
|
${C.darkGray}────────────────────────────────────────────────────────────${C.reset}
|
|
95
|
-
${C.reset}The Multi Platform AI ${C.green}[
|
|
93
|
+
${C.reset}The Multi Platform AI ${C.green}[Isolated Tool Execution Engine]${C.reset}
|
|
96
94
|
${C.gray}/config | /models | /skill | /mcp | /connect | /scan | /exit${C.reset}
|
|
97
95
|
${C.darkGray}────────────────────────────────────────────────────────────${C.reset}
|
|
98
96
|
`);
|
|
99
97
|
}
|
|
100
98
|
|
|
101
|
-
//
|
|
102
|
-
function
|
|
103
|
-
|
|
99
|
+
// Helper untuk membaca isi file skill/MCP secara otomatis
|
|
100
|
+
function readResourceContent(targetPath) {
|
|
101
|
+
if (!fs.existsSync(targetPath)) return "[Resource file/directory not found on local system]";
|
|
102
|
+
|
|
103
|
+
const stat = fs.statSync(targetPath);
|
|
104
|
+
if (stat.isFile()) {
|
|
105
|
+
try {
|
|
106
|
+
return fs.readFileSync(targetPath, 'utf8');
|
|
107
|
+
} catch (e) {
|
|
108
|
+
return `[Error reading file: ${e.message}]`;
|
|
109
|
+
}
|
|
110
|
+
} else if (stat.isDirectory()) {
|
|
111
|
+
// Cari file instruksi utama seperti SKILL.md, README.md, index.js, prompt.txt
|
|
112
|
+
const candidateFiles = ['SKILL.md', 'skill.md', 'PROMPT.md', 'README.md', 'index.js', 'index.ts', 'main.py'];
|
|
113
|
+
for (const file of candidateFiles) {
|
|
114
|
+
const full = path.join(targetPath, file);
|
|
115
|
+
if (fs.existsSync(full)) {
|
|
116
|
+
try {
|
|
117
|
+
return `--- Content from ${file} ---\n` + fs.readFileSync(full, 'utf8');
|
|
118
|
+
} catch (e) {}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Jika tidak ada file markdown/skrip khusus, baca beberapa file pertama
|
|
123
|
+
try {
|
|
124
|
+
const files = fs.readdirSync(targetPath);
|
|
125
|
+
let combinedText = `Directory Contents for ${path.basename(targetPath)}:\n`;
|
|
126
|
+
files.slice(0, 5).forEach(f => {
|
|
127
|
+
const fp = path.join(targetPath, f);
|
|
128
|
+
if (fs.statSync(fp).isFile()) {
|
|
129
|
+
combinedText += `\n--- File: ${f} ---\n` + fs.readFileSync(fp, 'utf8').slice(0, 2000);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
return combinedText;
|
|
133
|
+
} catch (e) {
|
|
134
|
+
return `[Directory found at ${targetPath}, but unable to parse files]`;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return "[Unknown resource format]";
|
|
138
|
+
}
|
|
104
139
|
|
|
140
|
+
// System Context Builder dengan ISOLASI KETAT
|
|
141
|
+
function getActiveToolsContext(forcedTool = null) {
|
|
142
|
+
// 1. Jika User Memanggil Tool Khusus (Misal: /skill-remotion-video)
|
|
105
143
|
if (forcedTool) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
144
|
+
const rawContent = readResourceContent(forcedTool.target);
|
|
145
|
+
|
|
146
|
+
return `\n\n[STRICT TOOL EXECUTION SYSTEM DIRECTIVE]
|
|
147
|
+
YOU ARE NOW STRICTLY ACTING AS THE FOLLOWING ${forcedTool.type.toUpperCase()} TOOL: "${forcedTool.name}".
|
|
148
|
+
DO NOT REFER TO OTHER TOOLS OR GENERAL ASSISTANT CAPABILITIES. FOCUS 100% ON EXECUTING THIS TOOL INSTRUCTION.
|
|
149
|
+
|
|
150
|
+
--- TOOL INSTRUCTION & CODE CONTENT ---
|
|
151
|
+
${rawContent}
|
|
152
|
+
--- END TOOL INSTRUCTION ---
|
|
153
|
+
|
|
154
|
+
Executing User Prompt under this tool context only:\n`;
|
|
110
155
|
}
|
|
111
|
-
|
|
156
|
+
|
|
157
|
+
// 2. Jika Chat Biasa (Tanpa Slash Specific Tool), tampilkan ringkasan umum
|
|
158
|
+
let contextParts = [];
|
|
112
159
|
const activeSkills = Object.keys(registry.skills || {});
|
|
113
160
|
if (activeSkills.length > 0) {
|
|
114
|
-
contextParts.push("AVAILABLE SKILLS:");
|
|
115
|
-
activeSkills.forEach(name => {
|
|
116
|
-
const s = registry.skills[name];
|
|
117
|
-
contextParts.push(`- /skill-${name} -> Path: ${s.path}`);
|
|
118
|
-
});
|
|
161
|
+
contextParts.push("AVAILABLE SKILLS (Use /skill-<name> to invoke directly):");
|
|
162
|
+
activeSkills.forEach(name => contextParts.push(`- /skill-${name}`));
|
|
119
163
|
}
|
|
120
164
|
|
|
121
165
|
const activeMCP = Object.keys(registry.mcp || {});
|
|
122
166
|
if (activeMCP.length > 0) {
|
|
123
|
-
contextParts.push("AVAILABLE MCP SERVERS:");
|
|
124
|
-
activeMCP.forEach(name => {
|
|
125
|
-
const m = registry.mcp[name];
|
|
126
|
-
contextParts.push(`- /mcp-${name} -> Target: ${m.target} (${m.type})`);
|
|
127
|
-
});
|
|
167
|
+
contextParts.push("AVAILABLE MCP SERVERS (Use /mcp-<name> to invoke directly):");
|
|
168
|
+
activeMCP.forEach(name => contextParts.push(`- /mcp-${name}`));
|
|
128
169
|
}
|
|
129
170
|
|
|
130
171
|
if (contextParts.length === 0) return "";
|
|
131
|
-
|
|
132
|
-
return "\n\n[SYSTEM CONTEXT: REGISTERED TOOLS & PROTOCOLS]\n" + contextParts.join("\n") + "\n";
|
|
172
|
+
return "\n\n[SYSTEM ENVIRONMENT SUMMARY]\n" + contextParts.join("\n") + "\n";
|
|
133
173
|
}
|
|
134
174
|
|
|
135
|
-
// Handlers for Skills with Dynamic Command Helper
|
|
136
175
|
function listSkills() {
|
|
137
176
|
console.log(`\n${C.cyan}=== Registered Skills ===${C.reset}`);
|
|
138
177
|
const keys = Object.keys(registry.skills || {});
|
|
@@ -148,9 +187,8 @@ function listSkills() {
|
|
|
148
187
|
});
|
|
149
188
|
console.log('');
|
|
150
189
|
|
|
151
|
-
// Interactive Action Helper Popup with dynamic slash commands
|
|
152
190
|
const lines = [
|
|
153
|
-
`${C.bold}Perintah Instan
|
|
191
|
+
`${C.bold}Perintah Instan (Fokus 100% Khusus Tool Tersebut):${C.reset}`,
|
|
154
192
|
``
|
|
155
193
|
];
|
|
156
194
|
|
|
@@ -158,16 +196,12 @@ function listSkills() {
|
|
|
158
196
|
lines.push(` ${C.yellow}/skill-${name}${C.reset} <prompt kamu>`);
|
|
159
197
|
});
|
|
160
198
|
|
|
161
|
-
lines.push(``);
|
|
162
|
-
lines.push(`${C.gray}Contoh: ${C.yellow}/skill-${keys[0]} buatkan animasi intro${C.reset}`);
|
|
163
|
-
|
|
164
199
|
drawBox("⚡ COMMAND INSTAN SKILL TERSEDIA", lines, C.c1);
|
|
165
200
|
console.log('');
|
|
166
201
|
}
|
|
167
202
|
|
|
168
|
-
// Handlers for MCP with Dynamic Command Helper
|
|
169
203
|
function listMCP() {
|
|
170
|
-
console.log(`\n${C.cyan}=== Registered MCP
|
|
204
|
+
console.log(`\n${C.cyan}=== Registered MCP Servers ===${C.reset}`);
|
|
171
205
|
const keys = Object.keys(registry.mcp || {});
|
|
172
206
|
|
|
173
207
|
if (keys.length === 0) {
|
|
@@ -181,9 +215,8 @@ function listMCP() {
|
|
|
181
215
|
});
|
|
182
216
|
console.log('');
|
|
183
217
|
|
|
184
|
-
// Interactive Action Helper Popup with dynamic slash commands
|
|
185
218
|
const lines = [
|
|
186
|
-
`${C.bold}Perintah Instan MCP
|
|
219
|
+
`${C.bold}Perintah Instan MCP (Fokus Khusus Tool MCP):${C.reset}`,
|
|
187
220
|
``
|
|
188
221
|
];
|
|
189
222
|
|
|
@@ -191,9 +224,6 @@ function listMCP() {
|
|
|
191
224
|
lines.push(` ${C.yellow}/mcp-${name}${C.reset} <prompt kamu>`);
|
|
192
225
|
});
|
|
193
226
|
|
|
194
|
-
lines.push(``);
|
|
195
|
-
lines.push(`${C.gray}Contoh: ${C.yellow}/mcp-${keys[0]} sinkronkan file terbaru${C.reset}`);
|
|
196
|
-
|
|
197
227
|
drawBox("🔌 COMMAND INSTAN MCP TERSEDIA", lines, C.c4);
|
|
198
228
|
console.log('');
|
|
199
229
|
}
|
|
@@ -509,7 +539,7 @@ async function handleChat(prompt, forcedTool = null) {
|
|
|
509
539
|
return startPrompt();
|
|
510
540
|
}
|
|
511
541
|
|
|
512
|
-
console.log(`\n${C.c1}TMPA CLI (${config.model || 'AI'}) :${C.reset}
|
|
542
|
+
console.log(`\n${C.c1}TMPA CLI (${config.model || 'AI'}) :${C.reset}\n${aiResponse}\n`);
|
|
513
543
|
|
|
514
544
|
} catch (error) {
|
|
515
545
|
console.log(`\n${C.red}[x] Fetch Error: ${error.message}${C.reset}\n`);
|
|
@@ -570,8 +600,7 @@ function startPrompt() {
|
|
|
570
600
|
} else if (cmd === '/uninstall') {
|
|
571
601
|
handleUninstall();
|
|
572
602
|
} else if (cmd.startsWith('/skill-')) {
|
|
573
|
-
|
|
574
|
-
const fullCmd = cmd.slice(7).trim(); // remove '/skill-'
|
|
603
|
+
const fullCmd = cmd.slice(7).trim();
|
|
575
604
|
const spaceIdx = fullCmd.indexOf(' ');
|
|
576
605
|
let skillName = fullCmd;
|
|
577
606
|
let userPrompt = '';
|
|
@@ -588,8 +617,7 @@ function startPrompt() {
|
|
|
588
617
|
startPrompt();
|
|
589
618
|
}
|
|
590
619
|
} else if (cmd.startsWith('/mcp-')) {
|
|
591
|
-
|
|
592
|
-
const fullCmd = cmd.slice(5).trim(); // remove '/mcp-'
|
|
620
|
+
const fullCmd = cmd.slice(5).trim();
|
|
593
621
|
const spaceIdx = fullCmd.indexOf(' ');
|
|
594
622
|
let mcpName = fullCmd;
|
|
595
623
|
let userPrompt = '';
|