tmpa-cli 1.0.23 → 1.0.24
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 +175 -173
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -43,38 +43,38 @@ const PROVIDERS = {
|
|
|
43
43
|
'7': { name: 'Custom / Auto-Detect', endpoint: '', defaultModel: '' }
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
-
// 100+
|
|
46
|
+
// 100+ PRESETS LIST
|
|
47
47
|
const MCP_PRESETS = [
|
|
48
|
-
{ id: 'custom', name: '
|
|
49
|
-
{ id: 'google-stitch', name: '
|
|
50
|
-
{ id: 'supabase', name: '
|
|
51
|
-
{ id: 'cloudflare-workers', name: '
|
|
52
|
-
{ id: 'vercel', name: '
|
|
53
|
-
{ id: 'railway', name: '
|
|
54
|
-
{ id: 'firebase', name: '
|
|
55
|
-
{ id: 'huggingface', name: '
|
|
56
|
-
{ id: 'replicate', name: '
|
|
57
|
-
{ id: 'github', name: '
|
|
58
|
-
{ id: 'gitlab', name: '
|
|
59
|
-
{ id: 'postman', name: '
|
|
60
|
-
{ id: 'sentry', name: '
|
|
61
|
-
{ id: 'docker', name: '
|
|
62
|
-
{ id: 'postgresql', name: '
|
|
63
|
-
{ id: 'mysql', name: '
|
|
64
|
-
{ id: 'sqlite', name: '
|
|
65
|
-
{ id: 'mongodb', name: '
|
|
66
|
-
{ id: 'redis', name: '
|
|
67
|
-
{ id: 'pinecone', name: '
|
|
68
|
-
{ id: 'brave-search', name: '
|
|
69
|
-
{ id: 'tavily', name: '
|
|
70
|
-
{ id: 'puppeteer', name: '
|
|
71
|
-
{ id: 'firecrawl', name: '
|
|
72
|
-
{ id: 'fetch', name: '
|
|
73
|
-
{ id: 'notion', name: '
|
|
74
|
-
{ id: 'slack', name: '
|
|
75
|
-
{ id: 'discord', name: '
|
|
76
|
-
{ id: 'linear', name: '
|
|
77
|
-
{ id: 'google-drive', name: '
|
|
48
|
+
{ id: 'custom', name: '[+] Custom / Manual Input', category: 'General', type: 'custom', desc: 'Manual Name, Target, & Key' },
|
|
49
|
+
{ id: 'google-stitch', name: '[+] Google Stitch', category: 'Cloud & AI', type: 'direct-api', endpoint: 'https://stitch.googleapis.com/v1', reqAuth: 'GOOGLE_STITCH_API_KEY', desc: 'UI & App Prototyping MCP by Google' },
|
|
50
|
+
{ id: 'supabase', name: '[+] Supabase MCP', category: 'Cloud & AI', type: 'direct-api', endpoint: 'https://api.supabase.com/mcp', reqAuth: 'SUPABASE_ACCESS_TOKEN', desc: 'Database, Auth & Storage Management' },
|
|
51
|
+
{ id: 'cloudflare-workers', name: '[+] Cloudflare Workers', category: 'Cloud & AI', type: 'stdio', command: 'npx -y @cloudflare/mcp-server-cloudflare', reqAuth: 'CLOUDFLARE_API_TOKEN', desc: 'Deploy & manage edge functions' },
|
|
52
|
+
{ id: 'vercel', name: '[+] Vercel MCP', category: 'Cloud & AI', type: 'direct-api', endpoint: 'https://api.vercel.com/v1/mcp', reqAuth: 'VERCEL_TOKEN', desc: 'Manage projects & deployments' },
|
|
53
|
+
{ id: 'railway', name: '[+] Railway MCP', category: 'Cloud & AI', type: 'direct-api', endpoint: 'https://backboard.railway.app/mcp', reqAuth: 'RAILWAY_API_TOKEN', desc: 'Cloud infrastructure & DB runner' },
|
|
54
|
+
{ id: 'firebase', name: '[+] Firebase MCP', category: 'Cloud & AI', type: 'stdio', command: 'npx -y firebase-mcp-server', reqAuth: 'FIREBASE_TOKEN', desc: 'Firestore, Auth & Realtime DB' },
|
|
55
|
+
{ id: 'huggingface', name: '[+] HuggingFace Spaces', category: 'Cloud & AI', type: 'direct-api', endpoint: 'https://huggingface.co/api/mcp', reqAuth: 'HF_TOKEN', desc: 'Run open-source AI models & spaces' },
|
|
56
|
+
{ id: 'replicate', name: '[+] Replicate MCP', category: 'Cloud & AI', type: 'stdio', command: 'npx -y @replicate/mcp-server', reqAuth: 'REPLICATE_API_TOKEN', desc: 'Run image/video AI generation models' },
|
|
57
|
+
{ id: 'github', name: '[+] GitHub Official', category: 'Developer Tools', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-github', reqAuth: 'GITHUB_PERSONAL_ACCESS_TOKEN', desc: 'Repository, Issues, PRs & Gists' },
|
|
58
|
+
{ id: 'gitlab', name: '[+] GitLab MCP', category: 'Developer Tools', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-gitlab', reqAuth: 'GITLAB_PERSONAL_ACCESS_TOKEN', desc: 'GitLab projects & CI/CD pipelines' },
|
|
59
|
+
{ id: 'postman', name: '[+] Postman MCP', category: 'Developer Tools', type: 'stdio', command: 'npx -y @postman/mcp-server', reqAuth: 'POSTMAN_API_KEY', desc: 'API Collection testing & documentation' },
|
|
60
|
+
{ id: 'sentry', name: '[+] Sentry Error Tracker', category: 'Developer Tools', type: 'stdio', command: 'npx -y @sentry/mcp-server', reqAuth: 'SENTRY_AUTH_TOKEN', desc: 'Inspect application bugs & stacktraces' },
|
|
61
|
+
{ id: 'docker', name: '[+] Docker Local MCP', category: 'Developer Tools', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-docker', desc: 'Manage local containers & images' },
|
|
62
|
+
{ id: 'postgresql', name: '[+] PostgreSQL', category: 'Databases', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-postgres', reqAuth: 'DATABASE_URL', desc: 'Direct SQL query execution' },
|
|
63
|
+
{ id: 'mysql', name: '[+] MySQL MCP', category: 'Databases', type: 'stdio', command: 'npx -y mysql-mcp-server', reqAuth: 'MYSQL_CONNECTION_STRING', desc: 'MySQL relational database runner' },
|
|
64
|
+
{ id: 'sqlite', name: '[+] SQLite Local', category: 'Databases', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-sqlite', desc: 'Lightweight local database query tool' },
|
|
65
|
+
{ id: 'mongodb', name: '[+] MongoDB MCP', category: 'Databases', type: 'stdio', command: 'npx -y mongodb-mcp-server', reqAuth: 'MONGODB_URI', desc: 'NoSQL collection queries & aggregation' },
|
|
66
|
+
{ id: 'redis', name: '[+] Redis Cache', category: 'Databases', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-redis', reqAuth: 'REDIS_URL', desc: 'Key-value data structure store' },
|
|
67
|
+
{ id: 'pinecone', name: '[+] Pinecone Vector DB', category: 'Databases', type: 'direct-api', endpoint: 'https://api.pinecone.io/mcp', reqAuth: 'PINECONE_API_KEY', desc: 'Vector database for AI embeddings' },
|
|
68
|
+
{ id: 'brave-search', name: '[+] Brave Search', category: 'Search & Scraping', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-brave-search', reqAuth: 'BRAVE_API_KEY', desc: 'Real-time global web search engine' },
|
|
69
|
+
{ id: 'tavily', name: '[+] Tavily AI Search', category: 'Search & Scraping', type: 'stdio', command: 'npx -y tavily-mcp', reqAuth: 'TAVILY_API_KEY', desc: 'Optimized search engine for LLMs' },
|
|
70
|
+
{ id: 'puppeteer', name: '[+] Puppeteer Scraper', category: 'Search & Scraping', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-puppeteer', desc: 'Headless browser web automation & screenshot' },
|
|
71
|
+
{ id: 'firecrawl', name: '[+] Firecrawl Scraper', category: 'Search & Scraping', type: 'direct-api', endpoint: 'https://api.firecrawl.dev/v1/mcp', reqAuth: 'FIRECRAWL_API_KEY', desc: 'Convert entire websites to clean Markdown' },
|
|
72
|
+
{ id: 'fetch', name: '[+] Fetch HTTP Utility', category: 'Search & Scraping', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-fetch', desc: 'HTTP request & web page parser' },
|
|
73
|
+
{ id: 'notion', name: '[+] Notion Workspace', category: 'Productivity', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-notion', reqAuth: 'NOTION_API_TOKEN', desc: 'Read & edit Notion pages and databases' },
|
|
74
|
+
{ id: 'slack', name: '[+] Slack Channel', category: 'Productivity', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-slack', reqAuth: 'SLACK_BOT_TOKEN', desc: 'Send messages & read channels' },
|
|
75
|
+
{ id: 'discord', name: '[+] Discord Bot MCP', category: 'Productivity', type: 'stdio', command: 'npx -y discord-mcp-server', reqAuth: 'DISCORD_BOT_TOKEN', desc: 'Interact with Discord servers & channels' },
|
|
76
|
+
{ id: 'linear', name: '[+] Linear Issue Tracker', category: 'Productivity', type: 'stdio', command: 'npx -y @linear/mcp-server', reqAuth: 'LINEAR_API_KEY', desc: 'Manage project issues & sprint cycles' },
|
|
77
|
+
{ id: 'google-drive', name: '[+] Google Drive', category: 'Productivity', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-gdrive', reqAuth: 'GDRIVE_CLIENT_ID', desc: 'Access Drive documents & sheets' }
|
|
78
78
|
];
|
|
79
79
|
|
|
80
80
|
function loadConfig() {
|
|
@@ -84,8 +84,8 @@ function loadConfig() {
|
|
|
84
84
|
return {};
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
function saveConfig(
|
|
88
|
-
fs.writeFileSync(CONFIG_FILE, JSON.stringify(
|
|
87
|
+
function saveConfig(cfg) {
|
|
88
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2));
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
function loadRegistry() {
|
|
@@ -95,19 +95,30 @@ function loadRegistry() {
|
|
|
95
95
|
return { skills: {}, mcp: {} };
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
function saveRegistry(
|
|
99
|
-
fs.writeFileSync(REGISTRY_FILE, JSON.stringify(
|
|
98
|
+
function saveRegistry(reg) {
|
|
99
|
+
fs.writeFileSync(REGISTRY_FILE, JSON.stringify(reg, null, 2));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function clearScreenFull() {
|
|
103
|
+
process.stdout.write('\x1B[2J\x1B[0;0H');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function getTermWidth() {
|
|
107
|
+
return Math.min(process.stdout.columns || 60, 64);
|
|
100
108
|
}
|
|
101
109
|
|
|
102
110
|
function drawBox(title, contentLines, borderColor = C.cyan) {
|
|
103
|
-
const width =
|
|
104
|
-
|
|
105
|
-
console.log(`${borderColor}
|
|
106
|
-
console.log(`${borderColor}
|
|
111
|
+
const width = getTermWidth();
|
|
112
|
+
const innerWidth = width - 4;
|
|
113
|
+
console.log(`${borderColor}+${'-'.repeat(width - 2)}+${C.reset}`);
|
|
114
|
+
console.log(`${borderColor}| ${C.bold}${title.padEnd(innerWidth)}${C.reset}${borderColor} |${C.reset}`);
|
|
115
|
+
console.log(`${borderColor}+${'-'.repeat(width - 2)}+${C.reset}`);
|
|
107
116
|
contentLines.forEach(line => {
|
|
108
|
-
|
|
117
|
+
const cleanLine = line.replace(/\x1b\[[0-9;]*m/g, '');
|
|
118
|
+
const padding = Math.max(0, innerWidth - cleanLine.length);
|
|
119
|
+
console.log(`${borderColor}|${C.reset} ${line}${' '.repeat(padding)} ${borderColor}|${C.reset}`);
|
|
109
120
|
});
|
|
110
|
-
console.log(`${borderColor}
|
|
121
|
+
console.log(`${borderColor}+${'-'.repeat(width - 2)}+${C.reset}`);
|
|
111
122
|
}
|
|
112
123
|
|
|
113
124
|
let rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -115,18 +126,13 @@ let config = loadConfig();
|
|
|
115
126
|
let registry = loadRegistry();
|
|
116
127
|
|
|
117
128
|
function showBanner() {
|
|
118
|
-
|
|
129
|
+
clearScreenFull();
|
|
130
|
+
const width = getTermWidth();
|
|
119
131
|
console.log(`
|
|
120
|
-
${C.c1}
|
|
121
|
-
${C.
|
|
122
|
-
|
|
123
|
-
${C.
|
|
124
|
-
${C.c4} ██║ ██║ ╚═╝ ██║██║ ██║ ██║${C.reset}
|
|
125
|
-
${C.c4} ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝${C.reset}
|
|
126
|
-
${C.darkGray}────────────────────────────────────────────────────────────${C.reset}
|
|
127
|
-
${C.reset}The Multi Platform AI ${C.green}[MCP Hub & Interactive Provider Engine]${C.reset}
|
|
128
|
-
${C.gray}/config | /models | /custom-models | /skill | /mcp | /new-mcp | /scan | /uninstall${C.reset}
|
|
129
|
-
${C.darkGray}────────────────────────────────────────────────────────────${C.reset}
|
|
132
|
+
${C.c1}TMPA CLI Engine - Multi-Platform AI${C.reset}
|
|
133
|
+
${C.darkGray}${'-'.repeat(width)}${C.reset}
|
|
134
|
+
Commands: /config | /models | /custom-models | /skill | /mcp | /new-mcp | /scan | /uninstall
|
|
135
|
+
${C.darkGray}${'-'.repeat(width)}${C.reset}
|
|
130
136
|
`);
|
|
131
137
|
}
|
|
132
138
|
|
|
@@ -209,41 +215,42 @@ Executing User Prompt under this tool context only:\n`;
|
|
|
209
215
|
return "\n\n[SYSTEM ENVIRONMENT SUMMARY]\n" + contextParts.join("\n") + "\n";
|
|
210
216
|
}
|
|
211
217
|
|
|
212
|
-
//
|
|
218
|
+
// MCP CENTER
|
|
213
219
|
function showMCPHub() {
|
|
214
|
-
|
|
215
|
-
console.log(
|
|
216
|
-
console.log(`${C.c4}
|
|
220
|
+
const width = getTermWidth();
|
|
221
|
+
console.log(`\n${C.c4}${'-'.repeat(width)}${C.reset}`);
|
|
222
|
+
console.log(`${C.c4} [MCP] MODEL CONTEXT PROTOCOL CENTER ${C.reset}`);
|
|
223
|
+
console.log(`${C.c4}${'-'.repeat(width)}${C.reset}\n`);
|
|
217
224
|
|
|
218
225
|
const keys = Object.keys(registry.mcp || {});
|
|
219
226
|
|
|
220
227
|
if (keys.length === 0) {
|
|
221
|
-
console.log(`${C.yellow} [!]
|
|
222
|
-
console.log(`${C.gray}
|
|
228
|
+
console.log(`${C.yellow} [!] No MCP Servers currently connected.${C.reset}`);
|
|
229
|
+
console.log(`${C.gray} Use ${C.green}/new-mcp${C.gray} to add a new server.${C.reset}\n`);
|
|
223
230
|
} else {
|
|
224
|
-
console.log(`${C.bold}
|
|
231
|
+
console.log(`${C.bold}Active MCP Servers:${C.reset}`);
|
|
225
232
|
keys.forEach((name, i) => {
|
|
226
233
|
const m = registry.mcp[name];
|
|
227
|
-
const typeBadge = m.type === 'remote' || m.type === 'direct-api' ? `${C.cyan}[
|
|
234
|
+
const typeBadge = m.type === 'remote' || m.type === 'direct-api' ? `${C.cyan}[api]${C.reset}` : `${C.green}[stdio]${C.reset}`;
|
|
228
235
|
console.log(` ${C.yellow}${i + 1}.${C.reset} ${C.bold}${name}${C.reset} ${typeBadge}`);
|
|
229
|
-
console.log(`
|
|
230
|
-
if (m.authToken) console.log(`
|
|
236
|
+
console.log(` -> Target: ${C.gray}${m.target}${C.reset}`);
|
|
237
|
+
if (m.authToken) console.log(` -> Auth : ${C.green}Encrypted/Token set${C.reset}`);
|
|
231
238
|
});
|
|
232
239
|
console.log('');
|
|
233
240
|
}
|
|
234
241
|
|
|
235
242
|
const lines = [
|
|
236
|
-
`${C.bold}
|
|
237
|
-
`${C.yellow}/new-mcp${C.reset}
|
|
238
|
-
`${C.yellow}/mcp-<
|
|
239
|
-
`${C.yellow}/scan${C.reset}
|
|
243
|
+
`${C.bold}Instant MCP Commands:${C.reset}`,
|
|
244
|
+
`${C.yellow}/new-mcp${C.reset} -> Add MCP Server (Interactive Wizard)`,
|
|
245
|
+
`${C.yellow}/mcp-<name>${C.reset} <prompt> -> Execute specific MCP server`,
|
|
246
|
+
`${C.yellow}/scan${C.reset} -> Scan .mcp directory automatically`
|
|
240
247
|
];
|
|
241
248
|
|
|
242
|
-
drawBox("
|
|
249
|
+
drawBox("[i] MCP CENTER HELP", lines, C.c4);
|
|
243
250
|
console.log('');
|
|
244
251
|
}
|
|
245
252
|
|
|
246
|
-
// INTERACTIVE
|
|
253
|
+
// INTERACTIVE PROVIDER SELECTOR
|
|
247
254
|
function interactiveProviderSelector(allItems, onSelect, onCancel) {
|
|
248
255
|
let filteredItems = [...allItems];
|
|
249
256
|
let selectedIndex = 0;
|
|
@@ -258,7 +265,8 @@ function interactiveProviderSelector(allItems, onSelect, onCancel) {
|
|
|
258
265
|
}
|
|
259
266
|
|
|
260
267
|
function renderMenu() {
|
|
261
|
-
|
|
268
|
+
clearScreenFull();
|
|
269
|
+
const width = getTermWidth();
|
|
262
270
|
const totalPages = Math.ceil(filteredItems.length / pageSize) || 1;
|
|
263
271
|
if (currentPage >= totalPages) currentPage = totalPages - 1;
|
|
264
272
|
if (currentPage < 0) currentPage = 0;
|
|
@@ -268,31 +276,31 @@ function interactiveProviderSelector(allItems, onSelect, onCancel) {
|
|
|
268
276
|
|
|
269
277
|
if (selectedIndex >= pageItems.length) selectedIndex = Math.max(0, pageItems.length - 1);
|
|
270
278
|
|
|
271
|
-
console.log(`${C.c4}
|
|
272
|
-
console.log(`${C.c4}
|
|
273
|
-
console.log(`${C.c4}
|
|
279
|
+
console.log(`${C.c4}${'-'.repeat(width)}${C.reset}`);
|
|
280
|
+
console.log(`${C.c4} [+] SETUP MCP SERVER PROVIDER ${C.reset}`);
|
|
281
|
+
console.log(`${C.c4}${'-'.repeat(width)}${C.reset}\n`);
|
|
274
282
|
|
|
275
283
|
if (pageItems.length === 0) {
|
|
276
|
-
console.log(`${C.red}
|
|
284
|
+
console.log(`${C.red} No provider matched your search.${C.reset}\n`);
|
|
277
285
|
} else {
|
|
278
286
|
pageItems.forEach((item, idx) => {
|
|
279
287
|
const globalNum = startIdx + idx;
|
|
280
288
|
const isFocused = idx === selectedIndex;
|
|
281
|
-
const pointer = isFocused ? `${C.cyan}
|
|
289
|
+
const pointer = isFocused ? `${C.cyan}>${C.reset}` : ' ';
|
|
282
290
|
const numStr = globalNum.toString().padStart(2, ' ');
|
|
283
291
|
const badge = item.type ? `${C.gray}[${item.type}]${C.reset}` : '';
|
|
284
292
|
const nameStyled = isFocused ? `${C.bold}${C.green}${item.name}${C.reset}` : item.name;
|
|
285
293
|
|
|
286
|
-
console.log(`${pointer} ${C.yellow}${numStr}.${C.reset}
|
|
294
|
+
console.log(`${pointer} ${C.yellow}${numStr}.${C.reset} ${nameStyled} ${badge}`);
|
|
287
295
|
console.log(` ${C.darkGray}${item.desc || item.category}${C.reset}`);
|
|
288
296
|
});
|
|
289
297
|
}
|
|
290
298
|
|
|
291
|
-
console.log(`\n${C.darkGray}
|
|
292
|
-
console.log(`${C.cyan}
|
|
293
|
-
console.log(`${C.gray}
|
|
294
|
-
console.log(`${C.gray}
|
|
295
|
-
console.log(`${C.darkGray}
|
|
299
|
+
console.log(`\n${C.darkGray}${'-'.repeat(width)}${C.reset}`);
|
|
300
|
+
console.log(`${C.cyan}Page ${currentPage + 1}/${totalPages}${C.reset} | Total: ${filteredItems.length} Providers`);
|
|
301
|
+
console.log(`${C.gray}Controls: [Up/Down] Arrow Keys | [ENTER] Select${C.reset}`);
|
|
302
|
+
console.log(`${C.gray}Keys: [f] Search | [n] Next | [p] Prev | [q] Cancel${C.reset}`);
|
|
303
|
+
console.log(`${C.darkGray}${'-'.repeat(width)}${C.reset}\n`);
|
|
296
304
|
}
|
|
297
305
|
|
|
298
306
|
readline.emitKeypressEvents(process.stdin);
|
|
@@ -336,7 +344,7 @@ function interactiveProviderSelector(allItems, onSelect, onCancel) {
|
|
|
336
344
|
renderMenu();
|
|
337
345
|
} else if (str === 'f' || str === 'F') {
|
|
338
346
|
cleanup();
|
|
339
|
-
rl.question(`\n${C.yellow}[>]
|
|
347
|
+
rl.question(`\n${C.yellow}[>] Enter provider search query:${C.reset} `, (query) => {
|
|
340
348
|
const q = query.trim().toLowerCase();
|
|
341
349
|
filteredItems = allItems.filter(item => item.name.toLowerCase().includes(q) || (item.desc && item.desc.toLowerCase().includes(q)));
|
|
342
350
|
currentPage = 0;
|
|
@@ -349,7 +357,7 @@ function interactiveProviderSelector(allItems, onSelect, onCancel) {
|
|
|
349
357
|
if (num >= 0 && num < allItems.length) {
|
|
350
358
|
onSelect(allItems[num]);
|
|
351
359
|
} else {
|
|
352
|
-
console.log(`${C.red}
|
|
360
|
+
console.log(`${C.red}Invalid index.${C.reset}`);
|
|
353
361
|
setTimeout(() => interactiveProviderSelector(allItems, onSelect, onCancel), 800);
|
|
354
362
|
}
|
|
355
363
|
}
|
|
@@ -359,9 +367,8 @@ function interactiveProviderSelector(allItems, onSelect, onCancel) {
|
|
|
359
367
|
renderMenu();
|
|
360
368
|
}
|
|
361
369
|
|
|
362
|
-
// INTERACTIVE
|
|
370
|
+
// INTERACTIVE MODEL SELECTOR (/models) - ANTI-SPAM & CLEAN REDRAW
|
|
363
371
|
function interactiveModelSelector(allModels, onSelect, onCancel) {
|
|
364
|
-
// Cap pada 600 model untuk mencegah lag ekstrem di memori Termux
|
|
365
372
|
let filteredModels = allModels.slice(0, 600);
|
|
366
373
|
let selectedIndex = 0;
|
|
367
374
|
let currentPage = 0;
|
|
@@ -375,7 +382,8 @@ function interactiveModelSelector(allModels, onSelect, onCancel) {
|
|
|
375
382
|
}
|
|
376
383
|
|
|
377
384
|
function renderMenu() {
|
|
378
|
-
|
|
385
|
+
clearScreenFull();
|
|
386
|
+
const width = getTermWidth();
|
|
379
387
|
const totalPages = Math.ceil(filteredModels.length / pageSize) || 1;
|
|
380
388
|
if (currentPage >= totalPages) currentPage = totalPages - 1;
|
|
381
389
|
if (currentPage < 0) currentPage = 0;
|
|
@@ -385,33 +393,33 @@ function interactiveModelSelector(allModels, onSelect, onCancel) {
|
|
|
385
393
|
|
|
386
394
|
if (selectedIndex >= pageItems.length) selectedIndex = Math.max(0, pageItems.length - 1);
|
|
387
395
|
|
|
388
|
-
console.log(`${C.c1}
|
|
389
|
-
console.log(`${C.c1}
|
|
390
|
-
console.log(`${C.c1}
|
|
391
|
-
console.log(
|
|
396
|
+
console.log(`${C.c1}${'-'.repeat(width)}${C.reset}`);
|
|
397
|
+
console.log(`${C.c1} [AI] CHOOSE AI MODEL (${config.provider || 'Provider'}) ${C.reset}`);
|
|
398
|
+
console.log(`${C.c1}${'-'.repeat(width)}${C.reset}`);
|
|
399
|
+
console.log(` Active Model: ${C.green}${config.model || 'None'}${C.reset}\n`);
|
|
392
400
|
|
|
393
401
|
if (pageItems.length === 0) {
|
|
394
|
-
console.log(`${C.red}
|
|
402
|
+
console.log(`${C.red} No model matched your query.${C.reset}\n`);
|
|
395
403
|
} else {
|
|
396
404
|
pageItems.forEach((m, idx) => {
|
|
397
405
|
const globalNum = startIdx + idx;
|
|
398
406
|
const isFocused = idx === selectedIndex;
|
|
399
407
|
const isCurrentActive = m.id === config.model;
|
|
400
408
|
|
|
401
|
-
const pointer = isFocused ? `${C.cyan}
|
|
402
|
-
const activeBadge = isCurrentActive ? `${C.green}
|
|
403
|
-
const numStr = globalNum.toString().padStart(3, ' ');
|
|
409
|
+
const pointer = isFocused ? `${C.cyan}>${C.reset}` : ' ';
|
|
410
|
+
const activeBadge = isCurrentActive ? `${C.green}[Active]${C.reset}` : '';
|
|
411
|
+
const numStr = (globalNum + 1).toString().padStart(3, ' ');
|
|
404
412
|
const modelNameStyled = isFocused ? `${C.bold}${C.yellow}${m.id}${C.reset}` : m.id;
|
|
405
413
|
|
|
406
|
-
console.log(`${pointer} ${C.gray}${numStr}.${C.reset}
|
|
414
|
+
console.log(`${pointer} ${C.gray}${numStr}.${C.reset} ${modelNameStyled} ${activeBadge}`);
|
|
407
415
|
});
|
|
408
416
|
}
|
|
409
417
|
|
|
410
|
-
console.log(`\n${C.darkGray}
|
|
411
|
-
console.log(`${C.cyan}
|
|
412
|
-
console.log(`${C.gray}
|
|
413
|
-
console.log(`${C.gray}
|
|
414
|
-
console.log(`${C.darkGray}
|
|
418
|
+
console.log(`\n${C.darkGray}${'-'.repeat(width)}${C.reset}`);
|
|
419
|
+
console.log(`${C.cyan}Page ${currentPage + 1}/${totalPages}${C.reset} | Total Models Loaded: ${filteredModels.length}`);
|
|
420
|
+
console.log(`${C.gray}Controls: [Up/Down] Arrow Keys | [ENTER] Select${C.reset}`);
|
|
421
|
+
console.log(`${C.gray}Keys: [f] Filter Model | [n] Next | [p] Prev | [q] Cancel${C.reset}`);
|
|
422
|
+
console.log(`${C.darkGray}${'-'.repeat(width)}${C.reset}\n`);
|
|
415
423
|
}
|
|
416
424
|
|
|
417
425
|
readline.emitKeypressEvents(process.stdin);
|
|
@@ -455,7 +463,7 @@ function interactiveModelSelector(allModels, onSelect, onCancel) {
|
|
|
455
463
|
renderMenu();
|
|
456
464
|
} else if (str === 'f' || str === 'F') {
|
|
457
465
|
cleanup();
|
|
458
|
-
rl.question(`\n${C.yellow}[>]
|
|
466
|
+
rl.question(`\n${C.yellow}[>] Enter model filter (e.g. llama, gemini, claude, qwen):${C.reset} `, (query) => {
|
|
459
467
|
const q = query.trim().toLowerCase();
|
|
460
468
|
filteredModels = allModels.filter(m => m.id.toLowerCase().includes(q)).slice(0, 600);
|
|
461
469
|
currentPage = 0;
|
|
@@ -469,37 +477,37 @@ function interactiveModelSelector(allModels, onSelect, onCancel) {
|
|
|
469
477
|
renderMenu();
|
|
470
478
|
}
|
|
471
479
|
|
|
472
|
-
//
|
|
480
|
+
// SETUP NEW MCP SERVER WIZARD (/new-mcp)
|
|
473
481
|
function createNewMCPWizard(callback) {
|
|
474
482
|
interactiveProviderSelector(
|
|
475
483
|
MCP_PRESETS,
|
|
476
484
|
(selectedProvider) => {
|
|
477
|
-
|
|
485
|
+
clearScreenFull();
|
|
478
486
|
|
|
479
487
|
if (selectedProvider.id === 'custom') {
|
|
480
|
-
console.log(`\n${C.cyan}===
|
|
481
|
-
rl.question(`${C.yellow}[1/4]
|
|
488
|
+
console.log(`\n${C.cyan}=== [+] MANUAL MCP SETUP (CUSTOM) ===${C.reset}\n`);
|
|
489
|
+
rl.question(`${C.yellow}[1/4] Enter MCP Server Name (e.g. my-mcp):${C.reset} `, (nameInput) => {
|
|
482
490
|
const mcpName = nameInput.trim().toLowerCase().replace(/\s+/g, '-');
|
|
483
491
|
if (!mcpName) {
|
|
484
|
-
console.log(`${C.red}[x]
|
|
492
|
+
console.log(`${C.red}[x] MCP name cannot be empty.${C.reset}\n`);
|
|
485
493
|
return callback();
|
|
486
494
|
}
|
|
487
495
|
|
|
488
|
-
console.log(`\n${C.cyan}
|
|
496
|
+
console.log(`\n${C.cyan}Select MCP Connection Type:${C.reset}`);
|
|
489
497
|
console.log(` ${C.yellow}1.${C.reset} Direct REST API / Endpoint`);
|
|
490
498
|
console.log(` ${C.yellow}2.${C.reset} Local Stdio Command / Path`);
|
|
491
499
|
|
|
492
|
-
rl.question(`\n${C.yellow}[2/4]
|
|
500
|
+
rl.question(`\n${C.yellow}[2/4] Select Type (1/2):${C.reset} `, (typeChoice) => {
|
|
493
501
|
const isApi = typeChoice.trim() === '1';
|
|
494
502
|
|
|
495
|
-
rl.question(`${C.yellow}[3/4]
|
|
503
|
+
rl.question(`${C.yellow}[3/4] Enter Target URL / Command Executable:${C.reset} `, (targetInput) => {
|
|
496
504
|
const target = targetInput.trim();
|
|
497
505
|
if (!target) {
|
|
498
|
-
console.log(`${C.red}[x] Target
|
|
506
|
+
console.log(`${C.red}[x] Target cannot be empty.${C.reset}\n`);
|
|
499
507
|
return callback();
|
|
500
508
|
}
|
|
501
509
|
|
|
502
|
-
rl.question(`${C.yellow}[4/4]
|
|
510
|
+
rl.question(`${C.yellow}[4/4] Enter Auth Token / API Key (Optional - Press Enter to skip):${C.reset} `, (tokenInput) => {
|
|
503
511
|
const authToken = tokenInput.trim();
|
|
504
512
|
|
|
505
513
|
registry.mcp = registry.mcp || {};
|
|
@@ -513,21 +521,21 @@ function createNewMCPWizard(callback) {
|
|
|
513
521
|
|
|
514
522
|
saveRegistry(registry);
|
|
515
523
|
|
|
516
|
-
console.log(`\n${C.green}[
|
|
517
|
-
console.log(`${C.gray}
|
|
524
|
+
console.log(`\n${C.green}[+] MCP Server "${mcpName}" successfully added!${C.reset}`);
|
|
525
|
+
console.log(`${C.gray}Execute via: ${C.yellow}/mcp-${mcpName} <your prompt>${C.reset}\n`);
|
|
518
526
|
callback();
|
|
519
527
|
});
|
|
520
528
|
});
|
|
521
529
|
});
|
|
522
530
|
});
|
|
523
531
|
} else {
|
|
524
|
-
console.log(`\n${C.cyan}===
|
|
532
|
+
console.log(`\n${C.cyan}=== [+] SETUP PROVIDER: ${selectedProvider.name} ===${C.reset}`);
|
|
525
533
|
console.log(`${C.gray}${selectedProvider.desc}${C.reset}\n`);
|
|
526
534
|
|
|
527
535
|
const mcpName = selectedProvider.id;
|
|
528
536
|
|
|
529
537
|
if (selectedProvider.reqAuth) {
|
|
530
|
-
rl.question(`${C.yellow}[>]
|
|
538
|
+
rl.question(`${C.yellow}[>] Enter ${selectedProvider.reqAuth}: ${C.reset}`, (authVal) => {
|
|
531
539
|
const token = authVal.trim();
|
|
532
540
|
|
|
533
541
|
registry.mcp = registry.mcp || {};
|
|
@@ -541,8 +549,8 @@ function createNewMCPWizard(callback) {
|
|
|
541
549
|
|
|
542
550
|
saveRegistry(registry);
|
|
543
551
|
|
|
544
|
-
console.log(`\n${C.green}[
|
|
545
|
-
console.log(`${C.gray}
|
|
552
|
+
console.log(`\n${C.green}[+] MCP Preset "${selectedProvider.name}" successfully connected!${C.reset}`);
|
|
553
|
+
console.log(`${C.gray}Access via: ${C.yellow}/mcp-${mcpName} <your prompt>${C.reset}\n`);
|
|
546
554
|
callback();
|
|
547
555
|
});
|
|
548
556
|
} else {
|
|
@@ -557,14 +565,14 @@ function createNewMCPWizard(callback) {
|
|
|
557
565
|
|
|
558
566
|
saveRegistry(registry);
|
|
559
567
|
|
|
560
|
-
console.log(`\n${C.green}[
|
|
561
|
-
console.log(`${C.gray}
|
|
568
|
+
console.log(`\n${C.green}[+] MCP Preset "${selectedProvider.name}" successfully connected!${C.reset}`);
|
|
569
|
+
console.log(`${C.gray}Access via: ${C.yellow}/mcp-${mcpName} <your prompt>${C.reset}\n`);
|
|
562
570
|
callback();
|
|
563
571
|
}
|
|
564
572
|
}
|
|
565
573
|
},
|
|
566
574
|
() => {
|
|
567
|
-
console.log(`\n${C.gray}
|
|
575
|
+
console.log(`\n${C.gray}MCP setup cancelled.${C.reset}\n`);
|
|
568
576
|
callback();
|
|
569
577
|
}
|
|
570
578
|
);
|
|
@@ -575,7 +583,7 @@ function listSkills() {
|
|
|
575
583
|
const keys = Object.keys(registry.skills || {});
|
|
576
584
|
|
|
577
585
|
if (keys.length === 0) {
|
|
578
|
-
console.log(`${C.gray}
|
|
586
|
+
console.log(`${C.gray}No skills connected yet. Type ${C.yellow}/scan${C.gray} or ${C.yellow}/connect skill <path>${C.reset}\n`);
|
|
579
587
|
return;
|
|
580
588
|
}
|
|
581
589
|
|
|
@@ -586,14 +594,14 @@ function listSkills() {
|
|
|
586
594
|
console.log('');
|
|
587
595
|
|
|
588
596
|
const lines = [
|
|
589
|
-
`${C.bold}
|
|
597
|
+
`${C.bold}Instant Skill Commands:${C.reset}`
|
|
590
598
|
];
|
|
591
599
|
|
|
592
600
|
keys.forEach(name => {
|
|
593
|
-
lines.push(` ${C.yellow}/skill-${name}${C.reset} <prompt
|
|
601
|
+
lines.push(` ${C.yellow}/skill-${name}${C.reset} <your prompt>`);
|
|
594
602
|
});
|
|
595
603
|
|
|
596
|
-
drawBox("
|
|
604
|
+
drawBox("[+] AVAILABLE SKILL COMMANDS", lines, C.c1);
|
|
597
605
|
console.log('');
|
|
598
606
|
}
|
|
599
607
|
|
|
@@ -603,9 +611,9 @@ function connectResource(inputArgs) {
|
|
|
603
611
|
const targetPath = parts.slice(1).join(' ');
|
|
604
612
|
|
|
605
613
|
if (!type || !targetPath) {
|
|
606
|
-
console.log(`${C.red}[x]
|
|
607
|
-
console.log(` ${C.yellow}/connect skill <
|
|
608
|
-
console.log(` ${C.yellow}/connect mcp <
|
|
614
|
+
console.log(`${C.red}[x] Invalid format! Use:${C.reset}`);
|
|
615
|
+
console.log(` ${C.yellow}/connect skill <filepath_or_folder>${C.reset}`);
|
|
616
|
+
console.log(` ${C.yellow}/connect mcp <filepath_or_url>${C.reset}\n`);
|
|
609
617
|
return;
|
|
610
618
|
}
|
|
611
619
|
|
|
@@ -620,7 +628,7 @@ function connectResource(inputArgs) {
|
|
|
620
628
|
status: 'Active'
|
|
621
629
|
};
|
|
622
630
|
saveRegistry(registry);
|
|
623
|
-
console.log(`${C.green}[+] Skill "${skillName}"
|
|
631
|
+
console.log(`${C.green}[+] Skill "${skillName}" connected! Access via: /skill-${skillName}${C.reset}\n`);
|
|
624
632
|
} else if (type === 'mcp') {
|
|
625
633
|
const mcpName = path.basename(resolvedPath, path.extname(resolvedPath));
|
|
626
634
|
registry.mcp = registry.mcp || {};
|
|
@@ -631,14 +639,14 @@ function connectResource(inputArgs) {
|
|
|
631
639
|
status: 'Connected'
|
|
632
640
|
};
|
|
633
641
|
saveRegistry(registry);
|
|
634
|
-
console.log(`${C.green}[+] MCP "${mcpName}"
|
|
642
|
+
console.log(`${C.green}[+] MCP "${mcpName}" connected! Access via: /mcp-${mcpName}${C.reset}\n`);
|
|
635
643
|
} else {
|
|
636
|
-
console.log(`${C.red}[x]
|
|
644
|
+
console.log(`${C.red}[x] Unknown resource type. Use "skill" or "mcp".${C.reset}\n`);
|
|
637
645
|
}
|
|
638
646
|
}
|
|
639
647
|
|
|
640
648
|
function scanResources() {
|
|
641
|
-
console.log(`\n${C.yellow}[...]
|
|
649
|
+
console.log(`\n${C.yellow}[...] Scanning internal directories, home user, Gemini CLI & Claude Desktop...${C.reset}`);
|
|
642
650
|
registry = loadRegistry();
|
|
643
651
|
registry.skills = registry.skills || {};
|
|
644
652
|
registry.mcp = registry.mcp || {};
|
|
@@ -681,27 +689,27 @@ function scanResources() {
|
|
|
681
689
|
});
|
|
682
690
|
|
|
683
691
|
saveRegistry(registry);
|
|
684
|
-
console.log(`${C.green}[+]
|
|
692
|
+
console.log(`${C.green}[+] Scan completed.${C.reset}\n`);
|
|
685
693
|
|
|
686
694
|
if (newDetected.length > 0) {
|
|
687
|
-
drawBox("
|
|
688
|
-
`${C.green}
|
|
689
|
-
...newDetected.slice(0, 5).map(cmd => `
|
|
690
|
-
newDetected.length > 5 ? ` ...
|
|
695
|
+
drawBox("[+] NEW COMMANDS DETECTED!", [
|
|
696
|
+
`${C.green}You can now use the following commands:${C.reset}`,
|
|
697
|
+
...newDetected.slice(0, 5).map(cmd => ` * ${C.yellow}${cmd}${C.reset} <prompt>`),
|
|
698
|
+
newDetected.length > 5 ? ` ...and ${newDetected.length - 5} more commands.` : '',
|
|
691
699
|
``,
|
|
692
|
-
`${C.cyan}
|
|
700
|
+
`${C.cyan}Type /skill or /mcp to view all available commands.${C.reset}`
|
|
693
701
|
], C.green);
|
|
694
702
|
} else {
|
|
695
|
-
drawBox("
|
|
696
|
-
`
|
|
697
|
-
`
|
|
703
|
+
drawBox("[i] SCAN RESULTS", [
|
|
704
|
+
`No new Skills or MCP servers detected.`,
|
|
705
|
+
`Type ${C.yellow}/skill${C.reset} or ${C.yellow}/mcp${C.reset} to view active commands.`
|
|
698
706
|
], C.gray);
|
|
699
707
|
}
|
|
700
708
|
console.log('');
|
|
701
709
|
}
|
|
702
710
|
|
|
703
711
|
function askConfig(callback) {
|
|
704
|
-
console.log(`\n${C.cyan}[+]
|
|
712
|
+
console.log(`\n${C.cyan}[+] Select AI Provider:${C.reset}`);
|
|
705
713
|
console.log(` ${C.yellow}1.${C.reset} OpenRouter`);
|
|
706
714
|
console.log(` ${C.yellow}2.${C.reset} Groq`);
|
|
707
715
|
console.log(` ${C.yellow}3.${C.reset} NVIDIA NIM`);
|
|
@@ -739,7 +747,7 @@ function askConfig(callback) {
|
|
|
739
747
|
});
|
|
740
748
|
}
|
|
741
749
|
|
|
742
|
-
//
|
|
750
|
+
// FETCH MODELS UNIVERSAL FOR ALL PROVIDERS
|
|
743
751
|
async function fetchAvailableModels() {
|
|
744
752
|
if (!config.apiKey) {
|
|
745
753
|
console.log(`${C.red}[x] API Key is not set. Use /config first.${C.reset}\n`);
|
|
@@ -753,20 +761,15 @@ async function fetchAvailableModels() {
|
|
|
753
761
|
let fetchUrl = '';
|
|
754
762
|
let headers = {};
|
|
755
763
|
|
|
756
|
-
// 1. Google Gemini Native Models Fetch
|
|
757
764
|
if (url.includes('googleapis.com')) {
|
|
758
765
|
fetchUrl = `https://generativelanguage.googleapis.com/v1beta/models?key=${config.apiKey}`;
|
|
759
|
-
}
|
|
760
|
-
// 2. Anthropic Direct Fetch (jika endpoint anthropic)
|
|
761
|
-
else if (url.includes('anthropic.com')) {
|
|
766
|
+
} else if (url.includes('anthropic.com')) {
|
|
762
767
|
fetchUrl = 'https://api.anthropic.com/v1/models';
|
|
763
768
|
headers = {
|
|
764
769
|
'x-api-key': config.apiKey,
|
|
765
770
|
'anthropic-version': '2023-06-01'
|
|
766
771
|
};
|
|
767
|
-
}
|
|
768
|
-
// 3. OpenRouter, Groq, NVIDIA, OpenAI & Custom Universal OpenAI Standard
|
|
769
|
-
else {
|
|
772
|
+
} else {
|
|
770
773
|
let baseUrl = url.replace(/\/chat\/completions$/, '').replace(/\/$/, '');
|
|
771
774
|
fetchUrl = baseUrl.endsWith('/models') ? baseUrl : `${baseUrl}/models`;
|
|
772
775
|
headers = {
|
|
@@ -780,7 +783,6 @@ async function fetchAvailableModels() {
|
|
|
780
783
|
|
|
781
784
|
let extractedModels = [];
|
|
782
785
|
|
|
783
|
-
// Parsing fleksibel dari berbagai bentuk JSON provider
|
|
784
786
|
if (data.data && Array.isArray(data.data)) {
|
|
785
787
|
extractedModels = data.data.map(m => ({ id: typeof m === 'string' ? m : (m.id || m.name) }));
|
|
786
788
|
} else if (data.models && Array.isArray(data.models)) {
|
|
@@ -793,44 +795,44 @@ async function fetchAvailableModels() {
|
|
|
793
795
|
(selectedModelId) => {
|
|
794
796
|
config.model = selectedModelId;
|
|
795
797
|
saveConfig(config);
|
|
796
|
-
|
|
797
|
-
console.log(`${C.green}[
|
|
798
|
+
clearScreenFull();
|
|
799
|
+
console.log(`${C.green}[+] Model successfully updated to: ${config.model}${C.reset}\n`);
|
|
798
800
|
startPrompt();
|
|
799
801
|
},
|
|
800
802
|
() => {
|
|
801
|
-
|
|
802
|
-
console.log(`${C.gray}
|
|
803
|
+
clearScreenFull();
|
|
804
|
+
console.log(`${C.gray}Model selection cancelled.${C.reset}\n`);
|
|
803
805
|
startPrompt();
|
|
804
806
|
}
|
|
805
807
|
);
|
|
806
808
|
} else {
|
|
807
|
-
console.log(`${C.red}[x]
|
|
808
|
-
console.log(`${C.yellow}
|
|
809
|
+
console.log(`${C.red}[x] Failed to auto-fetch models from ${config.provider}.${C.reset}`);
|
|
810
|
+
console.log(`${C.yellow}[i] Tip: Use ${C.bold}/custom-models${C.reset}${C.yellow} to manually set the exact model ID.${C.reset}\n`);
|
|
809
811
|
startPrompt();
|
|
810
812
|
}
|
|
811
813
|
} catch (err) {
|
|
812
814
|
console.log(`${C.red}[x] Error fetching models: ${err.message}${C.reset}`);
|
|
813
|
-
console.log(`${C.yellow}
|
|
815
|
+
console.log(`${C.yellow}[i] Tip: Use ${C.bold}/custom-models${C.reset}${C.yellow} to set model ID manually.${C.reset}\n`);
|
|
814
816
|
startPrompt();
|
|
815
817
|
}
|
|
816
818
|
}
|
|
817
819
|
|
|
818
|
-
//
|
|
820
|
+
// /custom-models HANDLER
|
|
819
821
|
function handleCustomModels() {
|
|
820
|
-
console.log(`\n${C.cyan}===
|
|
821
|
-
console.log(`${C.gray}Provider
|
|
822
|
-
console.log(`${C.gray}Model
|
|
822
|
+
console.log(`\n${C.cyan}=== [>] SET CUSTOM MODEL (HIGH-PRECISION) ===${C.reset}`);
|
|
823
|
+
console.log(`${C.gray}Active Provider : ${C.yellow}${config.provider || 'Not configured'}${C.reset}`);
|
|
824
|
+
console.log(`${C.gray}Current Model : ${C.green}${config.model || 'Not configured'}${C.reset}\n`);
|
|
823
825
|
|
|
824
|
-
rl.question(`${C.yellow}[>]
|
|
826
|
+
rl.question(`${C.yellow}[>] Enter exact Model ID/Name:${C.reset} `, (inputModel) => {
|
|
825
827
|
const cleanModel = inputModel.trim();
|
|
826
828
|
if (!cleanModel) {
|
|
827
|
-
console.log(`${C.red}[x]
|
|
829
|
+
console.log(`${C.red}[x] Model name cannot be empty.${C.reset}\n`);
|
|
828
830
|
return startPrompt();
|
|
829
831
|
}
|
|
830
832
|
|
|
831
833
|
config.model = cleanModel;
|
|
832
834
|
saveConfig(config);
|
|
833
|
-
console.log(`\n${C.green}[
|
|
835
|
+
console.log(`\n${C.green}[+] Model successfully updated to: ${C.bold}${config.model}${C.reset}\n`);
|
|
834
836
|
startPrompt();
|
|
835
837
|
});
|
|
836
838
|
}
|
|
@@ -842,7 +844,7 @@ async function handleChat(prompt, forcedTool = null) {
|
|
|
842
844
|
}
|
|
843
845
|
|
|
844
846
|
if (forcedTool) {
|
|
845
|
-
console.log(`${C.cyan}[
|
|
847
|
+
console.log(`${C.cyan}[+] Executing via ${forcedTool.type.toUpperCase()}: ${forcedTool.name}${C.reset}`);
|
|
846
848
|
}
|
|
847
849
|
|
|
848
850
|
console.log(`${C.yellow}TMPA CLI processing...${C.reset}`);
|
|
@@ -853,7 +855,7 @@ async function handleChat(prompt, forcedTool = null) {
|
|
|
853
855
|
let bodyData = {};
|
|
854
856
|
|
|
855
857
|
const toolsContext = getActiveToolsContext(forcedTool);
|
|
856
|
-
const fullPrompt = (prompt || "
|
|
858
|
+
const fullPrompt = (prompt || "Execute this tool context.") + toolsContext;
|
|
857
859
|
|
|
858
860
|
if (url.includes('googleapis.com')) {
|
|
859
861
|
const activeModel = config.model || 'gemini-2.5-flash';
|
|
@@ -903,23 +905,23 @@ async function handleChat(prompt, forcedTool = null) {
|
|
|
903
905
|
}
|
|
904
906
|
|
|
905
907
|
function handleUninstall() {
|
|
906
|
-
rl.question(`${C.red}[!]
|
|
908
|
+
rl.question(`${C.red}[!] Are you sure you want to uninstall TMPA CLI? (y/N):${C.reset} `, (answer) => {
|
|
907
909
|
if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
|
|
908
|
-
console.log(`\n${C.yellow}[...]
|
|
910
|
+
console.log(`\n${C.yellow}[...] Cleaning configurations and uninstalling TMPA CLI...${C.reset}`);
|
|
909
911
|
try {
|
|
910
912
|
if (fs.existsSync(CONFIG_FILE)) {
|
|
911
913
|
fs.unlinkSync(CONFIG_FILE);
|
|
912
914
|
}
|
|
913
|
-
console.log(`${C.green}[+]
|
|
915
|
+
console.log(`${C.green}[+] Local configuration cleaned.${C.reset}`);
|
|
914
916
|
execSync('npm uninstall -g tmpa-cli', { stdio: 'inherit' });
|
|
915
|
-
console.log(`\n${C.green}[+] TMPA CLI
|
|
917
|
+
console.log(`\n${C.green}[+] TMPA CLI successfully uninstalled. Goodbye!${C.reset}\n`);
|
|
916
918
|
process.exit(0);
|
|
917
919
|
} catch (err) {
|
|
918
|
-
console.log(`\n${C.red}[x]
|
|
920
|
+
console.log(`\n${C.red}[x] Uninstall failed automatically. Please run: npm uninstall -g tmpa-cli manually.${C.reset}\n`);
|
|
919
921
|
process.exit(0);
|
|
920
922
|
}
|
|
921
923
|
} else {
|
|
922
|
-
console.log(`${C.gray}
|
|
924
|
+
console.log(`${C.gray}Uninstall cancelled.${C.reset}\n`);
|
|
923
925
|
startPrompt();
|
|
924
926
|
}
|
|
925
927
|
});
|
|
@@ -971,7 +973,7 @@ function startPrompt() {
|
|
|
971
973
|
if (registry.skills && registry.skills[skillName]) {
|
|
972
974
|
handleChat(userPrompt, { type: 'skill', name: skillName, target: registry.skills[skillName].path });
|
|
973
975
|
} else {
|
|
974
|
-
console.log(`${C.red}[x] Skill "${skillName}"
|
|
976
|
+
console.log(`${C.red}[x] Skill "${skillName}" not found. Type /skill to list available skills.${C.reset}\n`);
|
|
975
977
|
startPrompt();
|
|
976
978
|
}
|
|
977
979
|
} else if (cmd.startsWith('/mcp-')) {
|
|
@@ -994,7 +996,7 @@ function startPrompt() {
|
|
|
994
996
|
authToken: registry.mcp[mcpName].authToken
|
|
995
997
|
});
|
|
996
998
|
} else {
|
|
997
|
-
console.log(`${C.red}[x] MCP "${mcpName}"
|
|
999
|
+
console.log(`${C.red}[x] MCP "${mcpName}" not found. Type /mcp to list active MCP servers.${C.reset}\n`);
|
|
998
1000
|
startPrompt();
|
|
999
1001
|
}
|
|
1000
1002
|
} else if (cmd === '') {
|