tmpa-cli 1.0.8 → 1.0.9

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 +42 -21
  2. package/package.json +1 -1
package/bin/index.js CHANGED
@@ -15,7 +15,7 @@ const C = {
15
15
  c3: '\x1b[38;2;99;102;241m',
16
16
  c4: '\x1b[38;2;168;85;247m',
17
17
  green: '\x1b[38;2;34;197;94m',
18
- cyan: '\x1b[38;2;6x;182;212m',
18
+ cyan: '\x1b[38;2;6;182;212m',
19
19
  yellow: '\x1b[38;2;234;179;8m',
20
20
  red: '\x1b[38;2;239;68;68m',
21
21
  gray: '\x1b[38;2;148;163;184m',
@@ -58,7 +58,7 @@ ${C.c4} ██║ ██║ ╚═╝ ██║██║ ██║ █
58
58
  ${C.c4} ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝${C.reset}
59
59
  ${C.darkGray}────────────────────────────────────────────────────────────${C.reset}
60
60
  ${C.reset}The Multi Platform AI ${C.green}[Interactive Mode]${C.reset}
61
- ${C.gray}/config : Set API | /models : View Models | /uninstall : Remove | /exit : Exit${C.reset}
61
+ ${C.gray}/config : Set API | /models : View & Select Models | /uninstall : Remove | /exit : Exit${C.reset}
62
62
  ${C.darkGray}────────────────────────────────────────────────────────────${C.reset}
63
63
  `);
64
64
  }
@@ -86,7 +86,7 @@ function askConfig(callback) {
86
86
  rl.question(`${C.yellow}[>] Enter API Key for ${selected.name}:${C.reset} `, (apiKey) => {
87
87
  if (choice.trim() === '7') {
88
88
  rl.question(`${C.yellow}[>] Enter Custom Base URL / Endpoint:${C.reset} `, (customUrl) => {
89
- rl.question(`${C.yellow}[>] Enter Model Name:${C.reset} `, (customModel) => {
89
+ rl.question(`${C.yellow}[>] Enter Specific Model Name:${C.reset} `, (customModel) => {
90
90
  config.provider = 'Custom';
91
91
  config.apiKey = apiKey.trim();
92
92
  config.endpoint = customUrl.trim();
@@ -102,7 +102,8 @@ function askConfig(callback) {
102
102
  config.endpoint = selected.endpoint;
103
103
  config.model = selected.defaultModel;
104
104
  saveConfig(config);
105
- console.log(`${C.green}[+] Connected to ${selected.name} (${selected.defaultModel})${C.reset}\n`);
105
+ console.log(`${C.green}[+] Connected to ${selected.name}. Default model: ${selected.defaultModel}${C.reset}`);
106
+ console.log(`${C.gray}(Tip: Run /models anytime to see all available models or type a custom model ID)${C.reset}\n`);
106
107
  if (callback) callback();
107
108
  }
108
109
  });
@@ -115,16 +116,15 @@ async function fetchAvailableModels() {
115
116
  return startPrompt();
116
117
  }
117
118
 
118
- console.log(`${C.yellow}[...] Fetching models for ${config.provider || 'Provider'}...${C.reset}`);
119
+ console.log(`${C.yellow}[...] Fetching full model list from ${config.provider || 'Provider'}...${C.reset}`);
119
120
 
120
121
  try {
121
122
  let url = config.endpoint;
122
- if (url.endsWith('/generateContent')) {
123
- console.log(`${C.yellow}[!] Google Gemini default endpoint uses fixed model: ${config.model}${C.reset}\n`);
123
+ if (url.includes('googleapis.com')) {
124
+ console.log(`${C.yellow}[!] Gemini Default REST API uses endpoint-defined model: ${config.model}${C.reset}\n`);
124
125
  return startPrompt();
125
126
  }
126
127
 
127
- // Auto-detect /models endpoint
128
128
  let modelsUrl = url.endsWith('/models') ? url : `${url.replace(/\/chat\/completions$/, '')}/models`;
129
129
 
130
130
  const response = await fetch(modelsUrl, {
@@ -138,26 +138,49 @@ async function fetchAvailableModels() {
138
138
  const data = await response.json();
139
139
 
140
140
  if (data.data && Array.isArray(data.data)) {
141
- console.log(`\n${C.cyan}=== Available Models ===${C.reset}`);
142
- const modelList = data.data.slice(0, 20); // Limit top 20 models
143
- modelList.forEach((m, idx) => {
144
- console.log(` ${C.yellow}${idx + 1}.${C.reset} ${m.id}`);
141
+ console.log(`\n${C.cyan}=== Available Models for ${config.provider} (${data.data.length} total) ===${C.reset}`);
142
+
143
+ // Ambil hingga 50 model populer/teratas untuk tampilan cepat
144
+ const displayedModels = data.data.slice(0, 50);
145
+ displayedModels.forEach((m, idx) => {
146
+ const num = (idx + 1).toString().padStart(2, ' ');
147
+ console.log(` ${C.yellow}${num}.${C.reset} ${m.id}`);
145
148
  });
149
+
150
+ if (data.data.length > 50) {
151
+ console.log(`${C.gray}... and ${data.data.length - 50} more models available on ${config.provider}.${C.reset}`);
152
+ }
153
+
146
154
  console.log(`${C.darkGray}------------------------------------------------------------${C.reset}`);
155
+ console.log(`${C.gray}Current active model: ${C.green}${config.model}${C.reset}`);
147
156
 
148
- rl.question(`\n${C.yellow}[>] Enter Model Name to use (or press Enter to keep current: ${config.model}):${C.reset} `, (newModel) => {
149
- if (newModel.trim()) {
150
- config.model = newModel.trim();
157
+ rl.question(`\n${C.yellow}[>] Enter number (1-${displayedModels.length}) OR type specific Model ID (e.g. meta/llama-3.1-70b-instruct):${C.reset} `, (input) => {
158
+ const val = input.trim();
159
+ if (!val) {
160
+ console.log(`${C.gray}Keeping current model: ${config.model}${C.reset}\n`);
161
+ } else if (!isNaN(val) && parseInt(val) >= 1 && parseInt(val) <= displayedModels.length) {
162
+ const selectedModel = displayedModels[parseInt(val) - 1].id;
163
+ config.model = selectedModel;
151
164
  saveConfig(config);
152
- console.log(`${C.green}[+] Active model updated to: ${config.model}${C.reset}\n`);
165
+ console.log(`${C.green}[+] Model updated to: ${config.model}${C.reset}\n`);
153
166
  } else {
154
- console.log(`${C.gray}Keeping current model: ${config.model}${C.reset}\n`);
167
+ // User memasukkan ID kustom/spesifik sendiri
168
+ config.model = val;
169
+ saveConfig(config);
170
+ console.log(`${C.green}[+] Custom Model ID saved: ${config.model}${C.reset}\n`);
155
171
  }
156
172
  startPrompt();
157
173
  });
158
174
  } else {
159
- console.log(`${C.red}[x] Unable to fetch models automatically from this provider.${C.reset}\n`);
160
- startPrompt();
175
+ console.log(`${C.red}[x] Could not retrieve models list automatically from ${config.provider}.${C.reset}`);
176
+ rl.question(`${C.yellow}[>] Enter specific Model ID manually:${C.reset} `, (manualModel) => {
177
+ if (manualModel.trim()) {
178
+ config.model = manualModel.trim();
179
+ saveConfig(config);
180
+ console.log(`${C.green}[+] Model updated to: ${config.model}${C.reset}\n`);
181
+ }
182
+ startPrompt();
183
+ });
161
184
  }
162
185
  } catch (err) {
163
186
  console.log(`${C.red}[x] Error fetching models: ${err.message}${C.reset}\n`);
@@ -178,12 +201,10 @@ async function handleChat(prompt) {
178
201
  let headers = { 'Content-Type': 'application/json' };
179
202
  let bodyData = {};
180
203
 
181
- // Auto-Detect Request Format (Google Gemini vs OpenAI Compatible)
182
204
  if (url.includes('googleapis.com')) {
183
205
  url = `${url}?key=${config.apiKey}`;
184
206
  bodyData = { contents: [{ parts: [{ text: prompt }] }] };
185
207
  } else {
186
- // OpenAI Compatible (OpenRouter, Groq, NVIDIA, OpenAI, dll)
187
208
  if (!url.endsWith('/chat/completions')) {
188
209
  url = `${url.replace(/\/$/, '')}/chat/completions`;
189
210
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tmpa-cli",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "bin": {