tmpa-cli 1.0.17 → 1.0.18
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 +106 -41
- 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,113 @@ 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`);
|
|
206
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)`);
|
|
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
|
|
276
|
+
`${C.bold}Perintah Instan Skill:${C.reset}`,
|
|
220
277
|
``
|
|
221
278
|
];
|
|
222
279
|
|
|
223
280
|
keys.forEach(name => {
|
|
224
|
-
lines.push(` ${C.yellow}/
|
|
281
|
+
lines.push(` ${C.yellow}/skill-${name}${C.reset} <prompt kamu>`);
|
|
225
282
|
});
|
|
226
283
|
|
|
227
|
-
drawBox("
|
|
284
|
+
drawBox("⚡ COMMAND INSTAN SKILL TERSEDIA", lines, C.c1);
|
|
228
285
|
console.log('');
|
|
229
286
|
}
|
|
230
287
|
|
|
@@ -589,8 +646,10 @@ function startPrompt() {
|
|
|
589
646
|
listSkills();
|
|
590
647
|
startPrompt();
|
|
591
648
|
} else if (cmd === '/mcp') {
|
|
592
|
-
|
|
649
|
+
showMCPHub();
|
|
593
650
|
startPrompt();
|
|
651
|
+
} else if (cmd === '/new-mcp') {
|
|
652
|
+
createNewMCPWizard(() => startPrompt());
|
|
594
653
|
} else if (cmd.startsWith('/connect')) {
|
|
595
654
|
connectResource(cmd.replace('/connect', ''));
|
|
596
655
|
startPrompt();
|
|
@@ -628,7 +687,13 @@ function startPrompt() {
|
|
|
628
687
|
}
|
|
629
688
|
|
|
630
689
|
if (registry.mcp && registry.mcp[mcpName]) {
|
|
631
|
-
handleChat(userPrompt, {
|
|
690
|
+
handleChat(userPrompt, {
|
|
691
|
+
type: 'mcp',
|
|
692
|
+
name: mcpName,
|
|
693
|
+
target: registry.mcp[mcpName].target,
|
|
694
|
+
mcpType: registry.mcp[mcpName].type,
|
|
695
|
+
authToken: registry.mcp[mcpName].authToken
|
|
696
|
+
});
|
|
632
697
|
} else {
|
|
633
698
|
console.log(`${C.red}[x] MCP "${mcpName}" tidak ditemukan di registry. Ketik /mcp untuk melihat daftar.${C.reset}\n`);
|
|
634
699
|
startPrompt();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tmpa-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.18",
|
|
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
|
}
|