tmpa-cli 1.0.6 β 1.0.8
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/README.md +48 -4
- package/bin/index.js +137 -45
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,18 +25,21 @@ Make sure you have **Node.js** (v18+) installed in your terminal. Run the follow
|
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
27
|
npm install -g tmpa-cli
|
|
28
|
+
```
|
|
28
29
|
|
|
29
30
|
2. Installation via GitHub
|
|
30
31
|
βYou can also install directly from the GitHub repository:
|
|
31
32
|
|
|
33
|
+
```bash
|
|
32
34
|
npm install -g git+[https://github.com/zayyanathariz63-pixel/TMPA-CLI.git](https://github.com/zayyanathariz63-pixel/TMPA-CLI.git)
|
|
35
|
+
```
|
|
33
36
|
|
|
34
37
|
π Usage
|
|
35
38
|
βOnce installed, simply open your terminal and type:
|
|
36
39
|
|
|
37
|
-
bash
|
|
40
|
+
```bash
|
|
38
41
|
tmpa
|
|
39
|
-
|
|
42
|
+
```
|
|
40
43
|
π First-Time Setup
|
|
41
44
|
βWhen you run the application for the first time, you will be prompted to enter:
|
|
42
45
|
|
|
@@ -49,10 +52,11 @@ tmpa
|
|
|
49
52
|
βWhile inside the TMPA > chat session, you can use the following control commands:
|
|
50
53
|
|
|
51
54
|
Command Description
|
|
52
|
-
/config
|
|
53
|
-
/clear
|
|
55
|
+
/config--> Update or change stored API Key and API Endpoint
|
|
56
|
+
/clear--> Clear the terminal screen and display the main banner
|
|
54
57
|
/exit --> Exit the TMPA CLI application
|
|
55
58
|
|
|
59
|
+
|
|
56
60
|
Preview Example :
|
|
57
61
|
βββββββββββββ βββββββββββ ββββββ
|
|
58
62
|
ββββββββββββββ βββββββββββββββββββββ
|
|
@@ -65,6 +69,46 @@ Preview Example :
|
|
|
65
69
|
/config : Change API | /clear : Clear Screen | /exit : Exit
|
|
66
70
|
βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
67
71
|
|
|
72
|
+
|
|
73
|
+
## π¦ Prerequisites
|
|
74
|
+
|
|
75
|
+
Make sure you have **Node.js** (`v18.0.0` or higher) installed in your system:
|
|
76
|
+
|
|
77
|
+
windows :
|
|
78
|
+
```bash
|
|
79
|
+
winget install OpenJS.NodeJS
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Linux :
|
|
83
|
+
```bash
|
|
84
|
+
sudo apt update
|
|
85
|
+
sudo apt install nodejs npm
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
3. macOS :
|
|
89
|
+
```bash
|
|
90
|
+
brew install node
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
π How to Check the Installation Results: Once the process is complete, close and reopen your terminal, then type the following command to verify that npm is installed:
|
|
94
|
+
|
|
95
|
+
node.js :
|
|
96
|
+
```bash
|
|
97
|
+
node -v
|
|
98
|
+
```
|
|
99
|
+
npm :
|
|
100
|
+
```bash
|
|
101
|
+
npm -v
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
If you are using Termux (Android), you can install or update Node.js v18+ using:
|
|
106
|
+
|
|
107
|
+
```Bash
|
|
108
|
+
pkg update && pkg install nodejs-lts -y
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
|
|
68
112
|
TMPA > hello, who are you?
|
|
69
113
|
TMPA CLI processing...
|
|
70
114
|
TMPA CLI : I am an AI assistant ready to help you!
|
package/bin/index.js
CHANGED
|
@@ -8,13 +8,12 @@ const { execSync } = require('child_process');
|
|
|
8
8
|
|
|
9
9
|
const CONFIG_FILE = path.join(os.homedir(), '.tmpa_config.json');
|
|
10
10
|
|
|
11
|
-
// Exact RGB Gradient Colors (Cyan -> Light Blue -> Deep Blue -> Purple)
|
|
12
11
|
const C = {
|
|
13
12
|
reset: '\x1b[0m',
|
|
14
|
-
c1: '\x1b[38;2;0;210;255m',
|
|
15
|
-
c2: '\x1b[38;2;30;144;255m',
|
|
16
|
-
c3: '\x1b[38;2;99;102;241m',
|
|
17
|
-
c4: '\x1b[38;2;168;85;247m',
|
|
13
|
+
c1: '\x1b[38;2;0;210;255m',
|
|
14
|
+
c2: '\x1b[38;2;30;144;255m',
|
|
15
|
+
c3: '\x1b[38;2;99;102;241m',
|
|
16
|
+
c4: '\x1b[38;2;168;85;247m',
|
|
18
17
|
green: '\x1b[38;2;34;197;94m',
|
|
19
18
|
cyan: '\x1b[38;2;6x;182;212m',
|
|
20
19
|
yellow: '\x1b[38;2;234;179;8m',
|
|
@@ -23,14 +22,20 @@ const C = {
|
|
|
23
22
|
darkGray: '\x1b[38;2;71;85;105m'
|
|
24
23
|
};
|
|
25
24
|
|
|
25
|
+
const PROVIDERS = {
|
|
26
|
+
'1': { name: 'OpenRouter', endpoint: 'https://openrouter.ai/api/v1', defaultModel: 'google/gemini-2.5-flash' },
|
|
27
|
+
'2': { name: 'Groq', endpoint: 'https://api.groq.com/openai/v1', defaultModel: 'llama-3.3-70b-versatile' },
|
|
28
|
+
'3': { name: 'NVIDIA NIM', endpoint: 'https://integrate.api.nvidia.com/v1', defaultModel: 'meta/llama-3.1-70b-instruct' },
|
|
29
|
+
'4': { name: 'OpenAI', endpoint: 'https://api.openai.com/v1', defaultModel: 'gpt-4o-mini' },
|
|
30
|
+
'5': { name: 'Anthropic', endpoint: 'https://api.anthropic.com/v1', defaultModel: 'claude-3-5-haiku-20241022' },
|
|
31
|
+
'6': { name: 'Google Gemini', endpoint: 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent', defaultModel: 'gemini-2.5-flash' },
|
|
32
|
+
'7': { name: 'Custom / Auto-Detect', endpoint: '', defaultModel: '' }
|
|
33
|
+
};
|
|
34
|
+
|
|
26
35
|
function loadConfig() {
|
|
27
36
|
if (fs.existsSync(CONFIG_FILE)) {
|
|
28
37
|
try {
|
|
29
|
-
|
|
30
|
-
if (!data.endpoint) {
|
|
31
|
-
data.endpoint = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent';
|
|
32
|
-
}
|
|
33
|
-
return data;
|
|
38
|
+
return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
|
|
34
39
|
} catch (e) {
|
|
35
40
|
return {};
|
|
36
41
|
}
|
|
@@ -44,8 +49,6 @@ function saveConfig(config) {
|
|
|
44
49
|
|
|
45
50
|
function showBanner() {
|
|
46
51
|
console.clear();
|
|
47
|
-
|
|
48
|
-
// Exact Banner matching the image structure
|
|
49
52
|
console.log(`
|
|
50
53
|
${C.c1}βββββββββββββ βββββββββββ ββββββ ${C.reset}
|
|
51
54
|
${C.c2}ββββββββββββββ βββββββββββββββββββββ${C.reset}
|
|
@@ -55,7 +58,7 @@ ${C.c4} βββ βββ βββ ββββββ βββ β
|
|
|
55
58
|
${C.c4} βββ βββ ββββββ βββ βββ${C.reset}
|
|
56
59
|
${C.darkGray}ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ${C.reset}
|
|
57
60
|
${C.reset}The Multi Platform AI ${C.green}[Interactive Mode]${C.reset}
|
|
58
|
-
${C.gray}/config : Set API | /
|
|
61
|
+
${C.gray}/config : Set API | /models : View Models | /uninstall : Remove | /exit : Exit${C.reset}
|
|
59
62
|
${C.darkGray}ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ${C.reset}
|
|
60
63
|
`);
|
|
61
64
|
}
|
|
@@ -68,58 +71,148 @@ const rl = readline.createInterface({
|
|
|
68
71
|
let config = loadConfig();
|
|
69
72
|
|
|
70
73
|
function askConfig(callback) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
console.log(`\n${C.cyan}[+] Choose AI Provider:${C.reset}`);
|
|
75
|
+
console.log(` ${C.yellow}1.${C.reset} OpenRouter`);
|
|
76
|
+
console.log(` ${C.yellow}2.${C.reset} Groq`);
|
|
77
|
+
console.log(` ${C.yellow}3.${C.reset} NVIDIA NIM`);
|
|
78
|
+
console.log(` ${C.yellow}4.${C.reset} OpenAI`);
|
|
79
|
+
console.log(` ${C.yellow}5.${C.reset} Anthropic`);
|
|
80
|
+
console.log(` ${C.yellow}6.${C.reset} Google Gemini (Default)`);
|
|
81
|
+
console.log(` ${C.yellow}7.${C.reset} Custom / Auto-Detect Endpoint\n`);
|
|
82
|
+
|
|
83
|
+
rl.question(`${C.yellow}[>] Select Provider (1-7):${C.reset} `, (choice) => {
|
|
84
|
+
const selected = PROVIDERS[choice.trim()] || PROVIDERS['6'];
|
|
85
|
+
|
|
86
|
+
rl.question(`${C.yellow}[>] Enter API Key for ${selected.name}:${C.reset} `, (apiKey) => {
|
|
87
|
+
if (choice.trim() === '7') {
|
|
88
|
+
rl.question(`${C.yellow}[>] Enter Custom Base URL / Endpoint:${C.reset} `, (customUrl) => {
|
|
89
|
+
rl.question(`${C.yellow}[>] Enter Model Name:${C.reset} `, (customModel) => {
|
|
90
|
+
config.provider = 'Custom';
|
|
91
|
+
config.apiKey = apiKey.trim();
|
|
92
|
+
config.endpoint = customUrl.trim();
|
|
93
|
+
config.model = customModel.trim();
|
|
94
|
+
saveConfig(config);
|
|
95
|
+
console.log(`${C.green}[+] Configuration saved successfully!${C.reset}\n`);
|
|
96
|
+
if (callback) callback();
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
} else {
|
|
100
|
+
config.provider = selected.name;
|
|
101
|
+
config.apiKey = apiKey.trim();
|
|
102
|
+
config.endpoint = selected.endpoint;
|
|
103
|
+
config.model = selected.defaultModel;
|
|
104
|
+
saveConfig(config);
|
|
105
|
+
console.log(`${C.green}[+] Connected to ${selected.name} (${selected.defaultModel})${C.reset}\n`);
|
|
106
|
+
if (callback) callback();
|
|
107
|
+
}
|
|
78
108
|
});
|
|
79
109
|
});
|
|
80
110
|
}
|
|
81
111
|
|
|
112
|
+
async function fetchAvailableModels() {
|
|
113
|
+
if (!config.apiKey) {
|
|
114
|
+
console.log(`${C.red}[x] API Key is not set. Use /config first.${C.reset}\n`);
|
|
115
|
+
return startPrompt();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log(`${C.yellow}[...] Fetching models for ${config.provider || 'Provider'}...${C.reset}`);
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
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`);
|
|
124
|
+
return startPrompt();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Auto-detect /models endpoint
|
|
128
|
+
let modelsUrl = url.endsWith('/models') ? url : `${url.replace(/\/chat\/completions$/, '')}/models`;
|
|
129
|
+
|
|
130
|
+
const response = await fetch(modelsUrl, {
|
|
131
|
+
method: 'GET',
|
|
132
|
+
headers: {
|
|
133
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
134
|
+
'Content-Type': 'application/json'
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const data = await response.json();
|
|
139
|
+
|
|
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}`);
|
|
145
|
+
});
|
|
146
|
+
console.log(`${C.darkGray}------------------------------------------------------------${C.reset}`);
|
|
147
|
+
|
|
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();
|
|
151
|
+
saveConfig(config);
|
|
152
|
+
console.log(`${C.green}[+] Active model updated to: ${config.model}${C.reset}\n`);
|
|
153
|
+
} else {
|
|
154
|
+
console.log(`${C.gray}Keeping current model: ${config.model}${C.reset}\n`);
|
|
155
|
+
}
|
|
156
|
+
startPrompt();
|
|
157
|
+
});
|
|
158
|
+
} else {
|
|
159
|
+
console.log(`${C.red}[x] Unable to fetch models automatically from this provider.${C.reset}\n`);
|
|
160
|
+
startPrompt();
|
|
161
|
+
}
|
|
162
|
+
} catch (err) {
|
|
163
|
+
console.log(`${C.red}[x] Error fetching models: ${err.message}${C.reset}\n`);
|
|
164
|
+
startPrompt();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
82
168
|
async function handleChat(prompt) {
|
|
83
169
|
if (!config.apiKey) {
|
|
84
170
|
console.log(`${C.yellow}[!] API Key is not set.${C.reset}`);
|
|
85
171
|
return askConfig(() => startPrompt());
|
|
86
172
|
}
|
|
87
173
|
|
|
88
|
-
if (!config.endpoint) {
|
|
89
|
-
config.endpoint = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent';
|
|
90
|
-
}
|
|
91
|
-
|
|
92
174
|
console.log(`${C.yellow}TMPA CLI processing...${C.reset}`);
|
|
93
175
|
|
|
94
176
|
try {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
177
|
+
let url = config.endpoint;
|
|
178
|
+
let headers = { 'Content-Type': 'application/json' };
|
|
179
|
+
let bodyData = {};
|
|
98
180
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
181
|
+
// Auto-Detect Request Format (Google Gemini vs OpenAI Compatible)
|
|
182
|
+
if (url.includes('googleapis.com')) {
|
|
183
|
+
url = `${url}?key=${config.apiKey}`;
|
|
184
|
+
bodyData = { contents: [{ parts: [{ text: prompt }] }] };
|
|
185
|
+
} else {
|
|
186
|
+
// OpenAI Compatible (OpenRouter, Groq, NVIDIA, OpenAI, dll)
|
|
187
|
+
if (!url.endsWith('/chat/completions')) {
|
|
188
|
+
url = `${url.replace(/\/$/, '')}/chat/completions`;
|
|
189
|
+
}
|
|
190
|
+
headers['Authorization'] = `Bearer ${config.apiKey}`;
|
|
191
|
+
bodyData = {
|
|
192
|
+
model: config.model || 'gpt-3.5-turbo',
|
|
193
|
+
messages: [{ role: 'user', content: prompt }]
|
|
194
|
+
};
|
|
195
|
+
}
|
|
102
196
|
|
|
103
197
|
const response = await fetch(url, {
|
|
104
198
|
method: 'POST',
|
|
105
|
-
headers:
|
|
199
|
+
headers: headers,
|
|
106
200
|
body: JSON.stringify(bodyData)
|
|
107
201
|
});
|
|
108
202
|
|
|
109
203
|
const data = await response.json();
|
|
110
|
-
let reply = 'No response from server.';
|
|
111
|
-
|
|
112
|
-
if (data.candidates && data.candidates[0]?.content?.parts[0]?.text) {
|
|
113
|
-
reply = data.candidates[0].content.parts[0].text;
|
|
114
|
-
} else if (data.reply) {
|
|
115
|
-
reply = data.reply;
|
|
116
|
-
} else if (data.message) {
|
|
117
|
-
reply = data.message;
|
|
118
|
-
}
|
|
119
204
|
|
|
120
|
-
|
|
205
|
+
if (data.choices && data.choices[0]?.message?.content) {
|
|
206
|
+
console.log(`\n${C.c1}TMPA CLI (${config.model || 'AI'}) :${C.reset} ${data.choices[0].message.content}\n`);
|
|
207
|
+
} else if (data.candidates && data.candidates[0]?.content?.parts[0]?.text) {
|
|
208
|
+
console.log(`\n${C.c1}TMPA CLI :${C.reset} ${data.candidates[0].content.parts[0].text}\n`);
|
|
209
|
+
} else if (data.error) {
|
|
210
|
+
console.log(`\n${C.red}[x] API Error: ${data.error.message || JSON.stringify(data.error)}${C.reset}\n`);
|
|
211
|
+
} else {
|
|
212
|
+
console.log(`\n${C.red}[x] Response: ${JSON.stringify(data)}${C.reset}\n`);
|
|
213
|
+
}
|
|
121
214
|
} catch (error) {
|
|
122
|
-
console.log(`\n${C.red}[x] Error: ${error.message}${C.reset}\n`);
|
|
215
|
+
console.log(`\n${C.red}[x] Fetch Error: ${error.message}${C.reset}\n`);
|
|
123
216
|
}
|
|
124
217
|
|
|
125
218
|
startPrompt();
|
|
@@ -160,9 +253,8 @@ function startPrompt() {
|
|
|
160
253
|
startPrompt();
|
|
161
254
|
} else if (cmd === '/config') {
|
|
162
255
|
askConfig(() => startPrompt());
|
|
163
|
-
} else if (cmd === '/
|
|
164
|
-
|
|
165
|
-
startPrompt();
|
|
256
|
+
} else if (cmd === '/models') {
|
|
257
|
+
fetchAvailableModels();
|
|
166
258
|
} else if (cmd === '/uninstall') {
|
|
167
259
|
handleUninstall();
|
|
168
260
|
} else if (cmd === '') {
|