tmpa-cli 1.0.15 → 1.0.16

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.
Files changed (2) hide show
  1. package/bin/index.js +98 -52
  2. package/package.json +1 -1
package/bin/index.js CHANGED
@@ -68,12 +68,11 @@ function saveRegistry(registry) {
68
68
 
69
69
  // UI Popup Card Helper
70
70
  function drawBox(title, contentLines, borderColor = C.cyan) {
71
- const width = 60;
71
+ const width = 64;
72
72
  console.log(`${borderColor}┌${'─'.repeat(width - 2)}┐${C.reset}`);
73
73
  console.log(`${borderColor}│ ${C.bold}${title.padEnd(width - 4)}${C.reset}${borderColor} │${C.reset}`);
74
74
  console.log(`${borderColor}├${'─'.repeat(width - 2)}┤${C.reset}`);
75
75
  contentLines.forEach(line => {
76
- // Basic text padding layout
77
76
  console.log(`${borderColor}│${C.reset} ${line.padEnd(width - 4)} ${borderColor}│${C.reset}`);
78
77
  });
79
78
  console.log(`${borderColor}└${'─'.repeat(width - 2)}┘${C.reset}`);
@@ -93,22 +92,29 @@ ${C.c3} ██║ ██║╚██╔╝██║██╔═══╝ █
93
92
  ${C.c4} ██║ ██║ ╚═╝ ██║██║ ██║ ██║${C.reset}
94
93
  ${C.c4} ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝${C.reset}
95
94
  ${C.darkGray}────────────────────────────────────────────────────────────${C.reset}
96
- ${C.reset}The Multi Platform AI ${C.green}[Interactive Popup UI Engine]${C.reset}
95
+ ${C.reset}The Multi Platform AI ${C.green}[Dynamic Tool Slash Engine]${C.reset}
97
96
  ${C.gray}/config | /models | /skill | /mcp | /connect | /scan | /exit${C.reset}
98
97
  ${C.darkGray}────────────────────────────────────────────────────────────${C.reset}
99
98
  `);
100
99
  }
101
100
 
102
- // System Context Builder
103
- function getActiveToolsContext() {
101
+ // Dynamic System Context Builder
102
+ function getActiveToolsContext(forcedTool = null) {
104
103
  let contextParts = [];
104
+
105
+ if (forcedTool) {
106
+ contextParts.push(`[CRITICAL INSTRUCTION: FORCED TOOL EXECUTION]`);
107
+ contextParts.push(`User explicitly called tool command: /${forcedTool.type}-${forcedTool.name}`);
108
+ contextParts.push(`Target Path/URL: ${forcedTool.target}`);
109
+ contextParts.push(`You MUST use and invoke this ${forcedTool.type.toUpperCase()} tool to handle user prompt below.\n`);
110
+ }
105
111
 
106
112
  const activeSkills = Object.keys(registry.skills || {});
107
113
  if (activeSkills.length > 0) {
108
114
  contextParts.push("AVAILABLE SKILLS:");
109
115
  activeSkills.forEach(name => {
110
116
  const s = registry.skills[name];
111
- contextParts.push(`- Skill: ${name} (Path: ${s.path})`);
117
+ contextParts.push(`- /skill-${name} -> Path: ${s.path}`);
112
118
  });
113
119
  }
114
120
 
@@ -117,17 +123,16 @@ function getActiveToolsContext() {
117
123
  contextParts.push("AVAILABLE MCP SERVERS:");
118
124
  activeMCP.forEach(name => {
119
125
  const m = registry.mcp[name];
120
- contextParts.push(`- MCP Server: ${name} (Target: ${m.target}, Type: ${m.type})`);
126
+ contextParts.push(`- /mcp-${name} -> Target: ${m.target} (${m.type})`);
121
127
  });
122
128
  }
123
129
 
124
130
  if (contextParts.length === 0) return "";
125
131
 
126
- return "\n\n[SYSTEM CONTEXT: ACTIVE TOOLS & PROTOCOLS]\n" + contextParts.join("\n") +
127
- "\nIf user wants to execute a skill/MCP, assist them using available tools.\n";
132
+ return "\n\n[SYSTEM CONTEXT: REGISTERED TOOLS & PROTOCOLS]\n" + contextParts.join("\n") + "\n";
128
133
  }
129
134
 
130
- // Handlers for Skills with Popup Helper
135
+ // Handlers for Skills with Dynamic Command Helper
131
136
  function listSkills() {
132
137
  console.log(`\n${C.cyan}=== Registered Skills ===${C.reset}`);
133
138
  const keys = Object.keys(registry.skills || {});
@@ -143,21 +148,24 @@ function listSkills() {
143
148
  });
144
149
  console.log('');
145
150
 
146
- // Interactive Action Helper Popup
147
- const sampleSkill = keys[0] || 'nama_skill';
148
- drawBox("💡 CARA MENGGUNAKAN SKILL TERDAFTAR", [
149
- `${C.bold}Perintah yang Bisa Kamu Ketik di Chat:${C.reset}`,
150
- ` 1. Langsung minta AI panggil skill:`,
151
- ` ${C.yellow}TMPA > "Jalankan skill ${sampleSkill}"${C.reset}`,
152
- ` 2. Tanya fungsi skill:`,
153
- ` ${C.yellow}TMPA > "Apa kegunaan dari skill ${sampleSkill}?"${C.reset}`,
154
- ` 3. Hubungkan file JS baru:`,
155
- ` ${C.yellow}TMPA > /connect skill ./path/ke/file.js${C.reset}`
156
- ], C.c1);
151
+ // Interactive Action Helper Popup with dynamic slash commands
152
+ const lines = [
153
+ `${C.bold}Perintah Instan yang Bisa Kamu Ketik Langsung:${C.reset}`,
154
+ ``
155
+ ];
156
+
157
+ keys.forEach(name => {
158
+ lines.push(` ${C.yellow}/skill-${name}${C.reset} <prompt kamu>`);
159
+ });
160
+
161
+ lines.push(``);
162
+ lines.push(`${C.gray}Contoh: ${C.yellow}/skill-${keys[0]} buatkan animasi intro${C.reset}`);
163
+
164
+ drawBox("⚡ COMMAND INSTAN SKILL TERSEDIA", lines, C.c1);
157
165
  console.log('');
158
166
  }
159
167
 
160
- // Handlers for MCP with Popup Helper
168
+ // Handlers for MCP with Dynamic Command Helper
161
169
  function listMCP() {
162
170
  console.log(`\n${C.cyan}=== Registered MCP (Model Context Protocol) Servers ===${C.reset}`);
163
171
  const keys = Object.keys(registry.mcp || {});
@@ -173,17 +181,20 @@ function listMCP() {
173
181
  });
174
182
  console.log('');
175
183
 
176
- // Interactive Action Helper Popup
177
- const sampleMcp = keys[0] || 'filesystem';
178
- drawBox("⚡ CARA MENGGUNAKAN MCP SERVER", [
179
- `${C.bold}Perintah & Integrasi yang Bisa Kamu Gunakan:${C.reset}`,
180
- ` 1. Minta AI akses fitur MCP:`,
181
- ` ${C.yellow}TMPA > "Gunakan MCP ${sampleMcp} untuk analisis data"${C.reset}`,
182
- ` 2. Hubungkan MCP via URL / HTTP SSE:`,
183
- ` ${C.yellow}TMPA > /connect mcp http://localhost:3000/sse${C.reset}`,
184
- ` 3. Pindai server MCP otomatis:`,
185
- ` ${C.yellow}TMPA > /scan${C.reset}`
186
- ], C.c4);
184
+ // Interactive Action Helper Popup with dynamic slash commands
185
+ const lines = [
186
+ `${C.bold}Perintah Instan MCP yang Bisa Kamu Ketik Langsung:${C.reset}`,
187
+ ``
188
+ ];
189
+
190
+ keys.forEach(name => {
191
+ lines.push(` ${C.yellow}/mcp-${name}${C.reset} <prompt kamu>`);
192
+ });
193
+
194
+ lines.push(``);
195
+ lines.push(`${C.gray}Contoh: ${C.yellow}/mcp-${keys[0]} sinkronkan file terbaru${C.reset}`);
196
+
197
+ drawBox("🔌 COMMAND INSTAN MCP TERSEDIA", lines, C.c4);
187
198
  console.log('');
188
199
  }
189
200
 
@@ -210,7 +221,7 @@ function connectResource(inputArgs) {
210
221
  status: 'Active'
211
222
  };
212
223
  saveRegistry(registry);
213
- console.log(`${C.green}[+] Skill "${skillName}" berhasil terhubung!${C.reset}\n`);
224
+ console.log(`${C.green}[+] Skill "${skillName}" terhubung! Akses instan: /skill-${skillName}${C.reset}\n`);
214
225
  } else if (type === 'mcp') {
215
226
  const mcpName = path.basename(resolvedPath, path.extname(resolvedPath));
216
227
  registry.mcp = registry.mcp || {};
@@ -221,13 +232,12 @@ function connectResource(inputArgs) {
221
232
  status: 'Connected'
222
233
  };
223
234
  saveRegistry(registry);
224
- console.log(`${C.green}[+] MCP Server "${mcpName}" berhasil terhubung!${C.reset}\n`);
235
+ console.log(`${C.green}[+] MCP "${mcpName}" terhubung! Akses instan: /mcp-${mcpName}${C.reset}\n`);
225
236
  } else {
226
237
  console.log(`${C.red}[x] Tipe tidak dikenal. Gunakan "skill" atau "mcp".${C.reset}\n`);
227
238
  }
228
239
  }
229
240
 
230
- // Deep Multi-Location Scanner Function with Result Popup Card
231
241
  function scanResources() {
232
242
  console.log(`\n${C.yellow}[...] Memindai lokasi internal, home user, Gemini CLI & Claude Desktop...${C.reset}`);
233
243
  registry = loadRegistry();
@@ -261,10 +271,10 @@ function scanResources() {
261
271
 
262
272
  if (type === 'skill' && !registry.skills[name]) {
263
273
  registry.skills[name] = { path: fullPath, connectedAt: new Date().toISOString(), status: 'Active' };
264
- newDetected.push(`[Skill] ${name}`);
274
+ newDetected.push(`/skill-${name}`);
265
275
  } else if (type === 'mcp' && !registry.mcp[name]) {
266
276
  registry.mcp[name] = { target: fullPath, type: 'local', connectedAt: new Date().toISOString(), status: 'Connected' };
267
- newDetected.push(`[MCP] ${name}`);
277
+ newDetected.push(`/mcp-${name}`);
268
278
  }
269
279
  });
270
280
  } catch (e) {}
@@ -272,24 +282,20 @@ function scanResources() {
272
282
  });
273
283
 
274
284
  saveRegistry(registry);
275
-
276
285
  console.log(`${C.green}[+] Pemindaian selesai.${C.reset}\n`);
277
286
 
278
- // POPUP CARD SUMMARY FOR SCAN RESULTS
279
287
  if (newDetected.length > 0) {
280
- drawBox("🎉 ITEM BARU BERHASIL DITEMUKAN!", [
281
- `${C.green}Berhasil menambahkan ${newDetected.length} resource baru:${C.reset}`,
282
- ...newDetected.slice(0, 4).map(item => ` • ${item}`),
283
- newDetected.length > 4 ? ` ...dan ${newDetected.length - 4} item lainnya.` : '',
288
+ drawBox("🎉 COMMAND INSTAN BARU TERDETEKSI!", [
289
+ `${C.green}Kamu sekarang bisa langsung menggunakan perintah ini:${C.reset}`,
290
+ ...newDetected.slice(0, 5).map(cmd => ` • ${C.yellow}${cmd}${C.reset} <prompt>`),
291
+ newDetected.length > 5 ? ` ...dan ${newDetected.length - 5} command lainnya.` : '',
284
292
  ``,
285
- `${C.yellow}Ketik /skill atau /mcp untuk melihat daftar lengkap!${C.reset}`
293
+ `${C.cyan}Ketik /skill atau /mcp untuk melihat semua command.${C.reset}`
286
294
  ], C.green);
287
295
  } else {
288
296
  drawBox("ℹ️ HASIL PEMINDAIAN", [
289
- `Tidak ada file Skill atau MCP baru yang terdeteksi.`,
290
- `Semua resource sudah terhubung di registry.`,
291
- ``,
292
- `Gunakan ${C.yellow}/skill${C.reset} atau ${C.yellow}/mcp${C.reset} untuk melihat item aktif.`
297
+ `Tidak ada Skill atau MCP baru yang terdeteksi.`,
298
+ `Ketik ${C.yellow}/skill${C.reset} atau ${C.yellow}/mcp${C.reset} untuk melihat command instan yang aktif.`
293
299
  ], C.gray);
294
300
  }
295
301
  console.log('');
@@ -448,12 +454,16 @@ async function fetchAvailableModels() {
448
454
  }
449
455
  }
450
456
 
451
- async function handleChat(prompt) {
457
+ async function handleChat(prompt, forcedTool = null) {
452
458
  if (!config.apiKey) {
453
459
  console.log(`${C.yellow}[!] API Key is not set.${C.reset}`);
454
460
  return askConfig(() => startPrompt());
455
461
  }
456
462
 
463
+ if (forcedTool) {
464
+ console.log(`${C.cyan}[🚀 Executing via ${forcedTool.type.toUpperCase()}: ${forcedTool.name}]${C.reset}`);
465
+ }
466
+
457
467
  console.log(`${C.yellow}TMPA CLI processing...${C.reset}`);
458
468
 
459
469
  try {
@@ -461,8 +471,8 @@ async function handleChat(prompt) {
461
471
  let headers = { 'Content-Type': 'application/json' };
462
472
  let bodyData = {};
463
473
 
464
- const toolsContext = getActiveToolsContext();
465
- const fullPrompt = prompt + toolsContext;
474
+ const toolsContext = getActiveToolsContext(forcedTool);
475
+ const fullPrompt = (prompt || "Jalankan instruksi tool ini.") + toolsContext;
466
476
 
467
477
  if (url.includes('googleapis.com')) {
468
478
  url = `${url}?key=${config.apiKey}`;
@@ -559,6 +569,42 @@ function startPrompt() {
559
569
  startPrompt();
560
570
  } else if (cmd === '/uninstall') {
561
571
  handleUninstall();
572
+ } else if (cmd.startsWith('/skill-')) {
573
+ // Dynamic Slash Command for Skill: /skill-remotion-vidio <prompt>
574
+ const fullCmd = cmd.slice(7).trim(); // remove '/skill-'
575
+ const spaceIdx = fullCmd.indexOf(' ');
576
+ let skillName = fullCmd;
577
+ let userPrompt = '';
578
+
579
+ if (spaceIdx !== -1) {
580
+ skillName = fullCmd.slice(0, spaceIdx);
581
+ userPrompt = fullCmd.slice(spaceIdx + 1).trim();
582
+ }
583
+
584
+ if (registry.skills && registry.skills[skillName]) {
585
+ handleChat(userPrompt, { type: 'skill', name: skillName, target: registry.skills[skillName].path });
586
+ } else {
587
+ console.log(`${C.red}[x] Skill "${skillName}" tidak ditemukan di registry. Ketik /skill untuk melihat daftar.${C.reset}\n`);
588
+ startPrompt();
589
+ }
590
+ } else if (cmd.startsWith('/mcp-')) {
591
+ // Dynamic Slash Command for MCP: /mcp-stitch <prompt>
592
+ const fullCmd = cmd.slice(5).trim(); // remove '/mcp-'
593
+ const spaceIdx = fullCmd.indexOf(' ');
594
+ let mcpName = fullCmd;
595
+ let userPrompt = '';
596
+
597
+ if (spaceIdx !== -1) {
598
+ mcpName = fullCmd.slice(0, spaceIdx);
599
+ userPrompt = fullCmd.slice(spaceIdx + 1).trim();
600
+ }
601
+
602
+ if (registry.mcp && registry.mcp[mcpName]) {
603
+ handleChat(userPrompt, { type: 'mcp', name: mcpName, target: registry.mcp[mcpName].target });
604
+ } else {
605
+ console.log(`${C.red}[x] MCP "${mcpName}" tidak ditemukan di registry. Ketik /mcp untuk melihat daftar.${C.reset}\n`);
606
+ startPrompt();
607
+ }
562
608
  } else if (cmd === '') {
563
609
  startPrompt();
564
610
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tmpa-cli",
3
- "version": "1.0.15",
3
+ "version": "1.0.16",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "bin": {