tmpa-cli 1.0.17 → 1.0.19
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 +116 -49
- package/package.json +6 -2
package/bin/index.js
CHANGED
|
@@ -90,13 +90,12 @@ ${C.c3} ██║ ██║╚██╔╝██║██╔═══╝ █
|
|
|
90
90
|
${C.c4} ██║ ██║ ╚═╝ ██║██║ ██║ ██║${C.reset}
|
|
91
91
|
${C.c4} ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝${C.reset}
|
|
92
92
|
${C.darkGray}────────────────────────────────────────────────────────────${C.reset}
|
|
93
|
-
${C.reset}The Multi Platform AI ${C.green}[
|
|
94
|
-
${C.gray}/config | /models | /skill | /mcp | /
|
|
93
|
+
${C.reset}The Multi Platform AI ${C.green}[MCP Hub & Tool Engine]${C.reset}
|
|
94
|
+
${C.gray}/config | /models | /skill | /mcp | /new-mcp | /scan | /exit${C.reset}
|
|
95
95
|
${C.darkGray}────────────────────────────────────────────────────────────${C.reset}
|
|
96
96
|
`);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
// Helper untuk membaca isi file skill/MCP secara otomatis
|
|
100
99
|
function readResourceContent(targetPath) {
|
|
101
100
|
if (!fs.existsSync(targetPath)) return "[Resource file/directory not found on local system]";
|
|
102
101
|
|
|
@@ -108,7 +107,6 @@ function readResourceContent(targetPath) {
|
|
|
108
107
|
return `[Error reading file: ${e.message}]`;
|
|
109
108
|
}
|
|
110
109
|
} else if (stat.isDirectory()) {
|
|
111
|
-
// Cari file instruksi utama seperti SKILL.md, README.md, index.js, prompt.txt
|
|
112
110
|
const candidateFiles = ['SKILL.md', 'skill.md', 'PROMPT.md', 'README.md', 'index.js', 'index.ts', 'main.py'];
|
|
113
111
|
for (const file of candidateFiles) {
|
|
114
112
|
const full = path.join(targetPath, file);
|
|
@@ -119,7 +117,6 @@ function readResourceContent(targetPath) {
|
|
|
119
117
|
}
|
|
120
118
|
}
|
|
121
119
|
|
|
122
|
-
// Jika tidak ada file markdown/skrip khusus, baca beberapa file pertama
|
|
123
120
|
try {
|
|
124
121
|
const files = fs.readdirSync(targetPath);
|
|
125
122
|
let combinedText = `Directory Contents for ${path.basename(targetPath)}:\n`;
|
|
@@ -137,11 +134,18 @@ function readResourceContent(targetPath) {
|
|
|
137
134
|
return "[Unknown resource format]";
|
|
138
135
|
}
|
|
139
136
|
|
|
140
|
-
// System Context Builder dengan ISOLASI KETAT
|
|
141
137
|
function getActiveToolsContext(forcedTool = null) {
|
|
142
|
-
// 1. Jika User Memanggil Tool Khusus (Misal: /skill-remotion-video)
|
|
143
138
|
if (forcedTool) {
|
|
144
|
-
|
|
139
|
+
let rawContent = "";
|
|
140
|
+
if (forcedTool.type === 'mcp') {
|
|
141
|
+
rawContent = `MCP Server Info:
|
|
142
|
+
Name: ${forcedTool.name}
|
|
143
|
+
Target/Endpoint: ${forcedTool.target}
|
|
144
|
+
Type: ${forcedTool.mcpType || 'HTTP/SSE'}
|
|
145
|
+
Auth Token: ${forcedTool.authToken ? 'Provided' : 'None'}`;
|
|
146
|
+
} else {
|
|
147
|
+
rawContent = readResourceContent(forcedTool.target);
|
|
148
|
+
}
|
|
145
149
|
|
|
146
150
|
return `\n\n[STRICT TOOL EXECUTION SYSTEM DIRECTIVE]
|
|
147
151
|
YOU ARE NOW STRICTLY ACTING AS THE FOLLOWING ${forcedTool.type.toUpperCase()} TOOL: "${forcedTool.name}".
|
|
@@ -154,17 +158,16 @@ ${rawContent}
|
|
|
154
158
|
Executing User Prompt under this tool context only:\n`;
|
|
155
159
|
}
|
|
156
160
|
|
|
157
|
-
// 2. Jika Chat Biasa (Tanpa Slash Specific Tool), tampilkan ringkasan umum
|
|
158
161
|
let contextParts = [];
|
|
159
162
|
const activeSkills = Object.keys(registry.skills || {});
|
|
160
163
|
if (activeSkills.length > 0) {
|
|
161
|
-
contextParts.push("AVAILABLE SKILLS
|
|
164
|
+
contextParts.push("AVAILABLE SKILLS:");
|
|
162
165
|
activeSkills.forEach(name => contextParts.push(`- /skill-${name}`));
|
|
163
166
|
}
|
|
164
167
|
|
|
165
168
|
const activeMCP = Object.keys(registry.mcp || {});
|
|
166
169
|
if (activeMCP.length > 0) {
|
|
167
|
-
contextParts.push("AVAILABLE MCP SERVERS
|
|
170
|
+
contextParts.push("AVAILABLE MCP SERVERS:");
|
|
168
171
|
activeMCP.forEach(name => contextParts.push(`- /mcp-${name}`));
|
|
169
172
|
}
|
|
170
173
|
|
|
@@ -172,59 +175,112 @@ Executing User Prompt under this tool context only:\n`;
|
|
|
172
175
|
return "\n\n[SYSTEM ENVIRONMENT SUMMARY]\n" + contextParts.join("\n") + "\n";
|
|
173
176
|
}
|
|
174
177
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
// RUANGAN KHUSUS MCP CENTER
|
|
179
|
+
function showMCPHub() {
|
|
180
|
+
console.log(`\n${C.c4}============================================================${C.reset}`);
|
|
181
|
+
console.log(`${C.c4} 🔌 MCP (MODEL CONTEXT PROTOCOL) CENTER ${C.reset}`);
|
|
182
|
+
console.log(`${C.c4}============================================================${C.reset}\n`);
|
|
183
|
+
|
|
184
|
+
const keys = Object.keys(registry.mcp || {});
|
|
185
|
+
|
|
179
186
|
if (keys.length === 0) {
|
|
180
|
-
console.log(`${C.
|
|
181
|
-
|
|
187
|
+
console.log(`${C.yellow} [!] Belum ada MCP Server yang terhubung saat ini.${C.reset}`);
|
|
188
|
+
console.log(`${C.gray} Gunakan perintah ${C.green}/new-mcp${C.gray} untuk mendaftarkan MCP baru.${C.reset}\n`);
|
|
189
|
+
} else {
|
|
190
|
+
console.log(`${C.bold}Daftar MCP Server Aktif:${C.reset}`);
|
|
191
|
+
keys.forEach((name, i) => {
|
|
192
|
+
const m = registry.mcp[name];
|
|
193
|
+
const typeBadge = m.type === 'remote' ? `${C.cyan}[Remote SSE/HTTP]${C.reset}` : `${C.green}[Local Stdio]${C.reset}`;
|
|
194
|
+
console.log(` ${C.yellow}${i + 1}.${C.reset} ${C.bold}${name}${C.reset} ${typeBadge}`);
|
|
195
|
+
console.log(` ↳ Target: ${C.gray}${m.target}${C.reset}`);
|
|
196
|
+
if (m.authToken) console.log(` ↳ Auth : ${C.green}Encrypted/Token set${C.reset}`);
|
|
197
|
+
});
|
|
198
|
+
console.log('');
|
|
182
199
|
}
|
|
183
200
|
|
|
184
|
-
keys.forEach((name, i) => {
|
|
185
|
-
const item = registry.skills[name];
|
|
186
|
-
console.log(` ${C.yellow}${i + 1}.${C.reset} ${C.green}${name}${C.reset} -> ${C.gray}${item.path}${C.reset}`);
|
|
187
|
-
});
|
|
188
|
-
console.log('');
|
|
189
|
-
|
|
190
201
|
const lines = [
|
|
191
|
-
`${C.bold}
|
|
192
|
-
|
|
202
|
+
`${C.bold}Command Instan MCP:${C.reset}`,
|
|
203
|
+
`${C.yellow}/new-mcp${C.reset} 👉 Tambah MCP Server Baru (Wizard)`,
|
|
204
|
+
`${C.yellow}/mcp-<nama>${C.reset} <prompt> 👉 Eksekusi MCP secara spesifik`,
|
|
205
|
+
`${C.yellow}/scan${C.reset} 👉 Pindai folder .mcp otomatis`
|
|
193
206
|
];
|
|
194
207
|
|
|
195
|
-
|
|
196
|
-
lines.push(` ${C.yellow}/skill-${name}${C.reset} <prompt kamu>`);
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
drawBox("⚡ COMMAND INSTAN SKILL TERSEDIA", lines, C.c1);
|
|
208
|
+
drawBox("💡 PETUNJUK RUANG MCP", lines, C.c4);
|
|
200
209
|
console.log('');
|
|
201
210
|
}
|
|
202
211
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
212
|
+
// WIZARD KONFIGURASI MCP BARU (/new-mcp)
|
|
213
|
+
function createNewMCPWizard(callback) {
|
|
214
|
+
console.log(`\n${C.cyan}=== 🛠️ SETUP MCP (MODEL CONTEXT PROTOCOL) BARU ===${C.reset}\n`);
|
|
215
|
+
|
|
216
|
+
rl.question(`${C.yellow}[1/4] Masukkan Nama MCP Server (misal: stitch, github, filesystem):${C.reset} `, (nameInput) => {
|
|
217
|
+
const mcpName = nameInput.trim().toLowerCase().replace(/\s+/g, '-');
|
|
218
|
+
if (!mcpName) {
|
|
219
|
+
console.log(`${C.red}[x] Nama MCP tidak boleh kosong.${C.reset}\n`);
|
|
220
|
+
return callback();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
console.log(`\n${C.cyan}Pilih Tipe Koneksi MCP:${C.reset}`);
|
|
224
|
+
console.log(` ${C.yellow}1.${C.reset} Remote URL / SSE Endpoint (misal: https://mcp.example.com/sse)`);
|
|
225
|
+
console.log(` ${C.yellow}2.${C.reset} Local Command / File Path (misal: npx -y @modelcontextprotocol/server-filesystem)`);
|
|
206
226
|
|
|
227
|
+
rl.question(`\n${C.yellow}[2/4] Pilih Tipe (1/2):${C.reset} `, (typeChoice) => {
|
|
228
|
+
const isRemote = typeChoice.trim() === '1';
|
|
229
|
+
|
|
230
|
+
rl.question(`${C.yellow}[3/4] Masukkan Target URL / Command Path:${C.reset} `, (targetInput) => {
|
|
231
|
+
const target = targetInput.trim();
|
|
232
|
+
if (!target) {
|
|
233
|
+
console.log(`${C.red}[x] Target tidak boleh kosong.${C.reset}\n`);
|
|
234
|
+
return callback();
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
rl.question(`${C.yellow}[4/4] Masukkan Auth Token / API Key (Tekan Enter jika tidak ada):${C.reset} `, (tokenInput) => {
|
|
238
|
+
const authToken = tokenInput.trim();
|
|
239
|
+
|
|
240
|
+
registry.mcp = registry.mcp || {};
|
|
241
|
+
registry.mcp[mcpName] = {
|
|
242
|
+
target: target,
|
|
243
|
+
type: isRemote ? 'remote' : 'local',
|
|
244
|
+
authToken: authToken || null,
|
|
245
|
+
connectedAt: new Date().toISOString(),
|
|
246
|
+
status: 'Connected'
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
saveRegistry(registry);
|
|
250
|
+
|
|
251
|
+
console.log(`\n${C.green}[✔] MCP Server "${mcpName}" berhasil ditambahkan!${C.reset}`);
|
|
252
|
+
console.log(`${C.gray}Gunakan perintah instan: ${C.yellow}/mcp-${mcpName} <prompt kamu>${C.reset}\n`);
|
|
253
|
+
callback();
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function listSkills() {
|
|
261
|
+
console.log(`\n${C.cyan}=== Registered Skills ===${C.reset}`);
|
|
262
|
+
const keys = Object.keys(registry.skills || {});
|
|
263
|
+
|
|
207
264
|
if (keys.length === 0) {
|
|
208
|
-
console.log(`${C.gray}Belum ada
|
|
265
|
+
console.log(`${C.gray}Belum ada skill terhubung. Ketik ${C.yellow}/scan${C.gray} atau ${C.yellow}/connect skill <path>${C.reset}\n`);
|
|
209
266
|
return;
|
|
210
267
|
}
|
|
211
268
|
|
|
212
269
|
keys.forEach((name, i) => {
|
|
213
|
-
const item = registry.
|
|
214
|
-
console.log(` ${C.yellow}${i + 1}.${C.reset} ${C.green}${name}${C.reset} -> ${C.gray}${item.
|
|
270
|
+
const item = registry.skills[name];
|
|
271
|
+
console.log(` ${C.yellow}${i + 1}.${C.reset} ${C.green}${name}${C.reset} -> ${C.gray}${item.path}${C.reset}`);
|
|
215
272
|
});
|
|
216
273
|
console.log('');
|
|
217
274
|
|
|
218
275
|
const lines = [
|
|
219
|
-
`${C.bold}Perintah Instan
|
|
220
|
-
``
|
|
276
|
+
`${C.bold}Perintah Instan Skill:${C.reset}`
|
|
221
277
|
];
|
|
222
278
|
|
|
223
279
|
keys.forEach(name => {
|
|
224
|
-
lines.push(` ${C.yellow}/
|
|
280
|
+
lines.push(` ${C.yellow}/skill-${name}${C.reset} <prompt kamu>`);
|
|
225
281
|
});
|
|
226
282
|
|
|
227
|
-
drawBox("
|
|
283
|
+
drawBox("⚡ COMMAND INSTAN SKILL TERSEDIA", lines, C.c1);
|
|
228
284
|
console.log('');
|
|
229
285
|
}
|
|
230
286
|
|
|
@@ -527,20 +583,23 @@ async function handleChat(prompt, forcedTool = null) {
|
|
|
527
583
|
const data = await response.json();
|
|
528
584
|
|
|
529
585
|
let aiResponse = "";
|
|
530
|
-
|
|
531
|
-
|
|
586
|
+
|
|
587
|
+
// DUKUNGAN UNTUK REASONING MODELS & STANDAR OPENAI/GEMINI
|
|
588
|
+
if (data.choices && data.choices[0] && data.choices[0].message) {
|
|
589
|
+
const msg = data.choices[0].message;
|
|
590
|
+
aiResponse = msg.content || msg.reasoning || msg.reasoning_content || "";
|
|
532
591
|
} else if (data.candidates && data.candidates[0]?.content?.parts[0]?.text) {
|
|
533
592
|
aiResponse = data.candidates[0].content.parts[0].text;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
if (aiResponse) {
|
|
596
|
+
console.log(`\n${C.c1}TMPA CLI (${config.model || 'AI'}) :${C.reset}\n${aiResponse}\n`);
|
|
534
597
|
} else if (data.error) {
|
|
535
598
|
console.log(`\n${C.red}[x] API Error: ${data.error.message || JSON.stringify(data.error)}${C.reset}\n`);
|
|
536
|
-
return startPrompt();
|
|
537
599
|
} else {
|
|
538
|
-
console.log(`\n${C.red}[x] Response: ${JSON.stringify(data)}${C.reset}\n`);
|
|
539
|
-
return startPrompt();
|
|
600
|
+
console.log(`\n${C.red}[x] Response Unrecognized: ${JSON.stringify(data)}${C.reset}\n`);
|
|
540
601
|
}
|
|
541
602
|
|
|
542
|
-
console.log(`\n${C.c1}TMPA CLI (${config.model || 'AI'}) :${C.reset}\n${aiResponse}\n`);
|
|
543
|
-
|
|
544
603
|
} catch (error) {
|
|
545
604
|
console.log(`\n${C.red}[x] Fetch Error: ${error.message}${C.reset}\n`);
|
|
546
605
|
}
|
|
@@ -589,8 +648,10 @@ function startPrompt() {
|
|
|
589
648
|
listSkills();
|
|
590
649
|
startPrompt();
|
|
591
650
|
} else if (cmd === '/mcp') {
|
|
592
|
-
|
|
651
|
+
showMCPHub();
|
|
593
652
|
startPrompt();
|
|
653
|
+
} else if (cmd === '/new-mcp') {
|
|
654
|
+
createNewMCPWizard(() => startPrompt());
|
|
594
655
|
} else if (cmd.startsWith('/connect')) {
|
|
595
656
|
connectResource(cmd.replace('/connect', ''));
|
|
596
657
|
startPrompt();
|
|
@@ -628,7 +689,13 @@ function startPrompt() {
|
|
|
628
689
|
}
|
|
629
690
|
|
|
630
691
|
if (registry.mcp && registry.mcp[mcpName]) {
|
|
631
|
-
handleChat(userPrompt, {
|
|
692
|
+
handleChat(userPrompt, {
|
|
693
|
+
type: 'mcp',
|
|
694
|
+
name: mcpName,
|
|
695
|
+
target: registry.mcp[mcpName].target,
|
|
696
|
+
mcpType: registry.mcp[mcpName].type,
|
|
697
|
+
authToken: registry.mcp[mcpName].authToken
|
|
698
|
+
});
|
|
632
699
|
} else {
|
|
633
700
|
console.log(`${C.red}[x] MCP "${mcpName}" tidak ditemukan di registry. Ketik /mcp untuk melihat daftar.${C.reset}\n`);
|
|
634
701
|
startPrompt();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tmpa-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.19",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "bin/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -14,8 +14,12 @@
|
|
|
14
14
|
"author": "",
|
|
15
15
|
"license": "ISC",
|
|
16
16
|
"dependencies": {
|
|
17
|
+
"@remotion/cli": "^4.0.506",
|
|
17
18
|
"chalk": "^4.1.2",
|
|
18
19
|
"commander": "^11.0.0",
|
|
19
|
-
"ora": "^5.4.1"
|
|
20
|
+
"ora": "^5.4.1",
|
|
21
|
+
"react": "^19.2.8",
|
|
22
|
+
"react-dom": "^19.2.8",
|
|
23
|
+
"remotion": "^4.0.506"
|
|
20
24
|
}
|
|
21
25
|
}
|