slek-ai-cli 1.1.5 → 1.1.7

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 (3) hide show
  1. package/auth.js +59 -84
  2. package/cli.js +89 -163
  3. package/package.json +3 -2
package/auth.js CHANGED
@@ -10,23 +10,9 @@ const axios = require('axios');
10
10
  const chalk = require('chalk');
11
11
  const boxen = require('boxen');
12
12
 
13
- // ─── Firebase / Google config (hardcoded — safe for CLI tools) ────────────────
14
- // FIREBASE_API_KEY and GOOGLE_CLIENT_ID are public-safe values.
15
- // We use Firebase's signInWithIdp flow, so GOOGLE_CLIENT_SECRET is NOT needed.
16
- const FIREBASE_API_KEY = 'AIzaSyBoQHn_adTTj1ZaYZBMHCMSAblCGCIbQG4';
17
- const GOOGLE_CLIENT_ID = '763614479011-32ci230ubh0kuvg1g1ie3jtoeir9orap.apps.googleusercontent.com
18
- '; // e.g. 123456.apps.googleusercontent.com
19
-
20
- // Additional Firebase config (for future SDK use if needed)
21
- const FIREBASE_CONFIG = {
22
- apiKey: 'AIzaSyBoQHn_adTTj1ZaYZBMHCMSAblCGCIbQG4',
23
- authDomain: 'charm-f004f.firebaseapp.com',
24
- projectId: 'charm-f004f',
25
- storageBucket: 'charm-f004f.firebasestorage.app',
26
- messagingSenderId: '763614479011',
27
- appId: '1:763614479011:web:5cd0082b14b78b9c5eb516',
28
- measurementId: 'G-0G0F5DT6PC',
29
- };
13
+ // ─── Firebase config (hardcoded — all values from Firebase Console) ───────────
14
+ const FIREBASE_API_KEY = 'AIzaSyBoQHn_adTTj1ZaYZBMHCMSAblCGCIbQG4';
15
+ const FIREBASE_AUTH_DOMAIN = 'charm-f004f.firebaseapp.com';
30
16
 
31
17
  const REDIRECT_URI = 'http://localhost:9876/callback';
32
18
  const AUTH_PORT = 9876;
@@ -66,7 +52,7 @@ function getUser() {
66
52
  return loadToken();
67
53
  }
68
54
 
69
- // ─── Open browser cross-platform ──────────────────────────────────────────────
55
+ // ─── Open browser cross-platform ─────────────────────────────────────────────
70
56
  function openBrowser(targetUrl) {
71
57
  try {
72
58
  const platform = process.platform;
@@ -84,73 +70,72 @@ function openBrowser(targetUrl) {
84
70
  }
85
71
  }
86
72
 
87
- // ─── Exchange Google auth code → Firebase ID token ────────────────────────────
88
- // Uses Firebase's signInWithIdp endpoint — no CLIENT_SECRET required.
89
- async function exchangeCodeForToken(code) {
90
- // Step 1: Exchange code for Google ID token using Google's token endpoint.
91
- // We use PKCE / implicit flow via Firebase — client secret not needed here.
92
- // Instead, we use Firebase's direct Google OAuth token exchange.
93
- const tokenRes = await axios.post(
94
- 'https://oauth2.googleapis.com/token',
95
- new URLSearchParams({
96
- code,
97
- client_id: GOOGLE_CLIENT_ID,
98
- redirect_uri: REDIRECT_URI,
99
- grant_type: 'authorization_code',
100
- }),
101
- { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
102
- );
73
+ // ─── Firebase Google Sign-In URL ──────────────────────────────────────────────
74
+ // Uses Firebase's own OAuth redirect — no separate Google Client ID needed.
75
+ function buildFirebaseAuthUrl() {
76
+ const base = `https://${FIREBASE_AUTH_DOMAIN}/__/auth/handler`;
77
+ const params = new URLSearchParams({
78
+ apiKey: FIREBASE_API_KEY,
79
+ appName: '[DEFAULT]',
80
+ authType: 'signInViaRedirect',
81
+ redirectUrl: REDIRECT_URI,
82
+ providerId: 'google.com',
83
+ scopes: 'profile,email',
84
+ v: '10',
85
+ });
86
+ return `${base}?${params.toString()}`;
87
+ }
103
88
 
104
- const { id_token } = tokenRes.data;
89
+ // ─── Exchange Firebase redirect token ────────────────────────────────────────
90
+ // After Firebase redirect, we get an id_token in the callback URL fragment/query.
91
+ async function handleFirebaseCallback(queryParams) {
92
+ // Firebase returns id_token directly in the callback
93
+ const idToken = queryParams.id_token || queryParams.idToken;
94
+
95
+ if (idToken) {
96
+ // Verify and get user info from Firebase
97
+ const res = await axios.post(
98
+ `https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=${FIREBASE_API_KEY}`,
99
+ { idToken }
100
+ );
101
+ const user = res.data.users?.[0];
102
+ if (!user) throw new Error('User not found');
103
+ return {
104
+ name: user.displayName || user.email,
105
+ email: user.email,
106
+ photo: user.photoUrl || '',
107
+ idToken,
108
+ expiresAt: Date.now() + 3600 * 1000, // 1 hour
109
+ };
110
+ }
111
+
112
+ // Fallback: if Firebase sends an auth code instead
113
+ const code = queryParams.code;
114
+ if (!code) throw new Error('No token or code received from Firebase');
105
115
 
106
- // Step 2: Sign in to Firebase using the Google ID token.
107
116
  const firebaseRes = await axios.post(
108
117
  `https://identitytoolkit.googleapis.com/v1/accounts:signInWithIdp?key=${FIREBASE_API_KEY}`,
109
118
  {
110
- postBody: `id_token=${id_token}&providerId=google.com`,
119
+ postBody: `id_token=${code}&providerId=google.com`,
111
120
  requestUri: REDIRECT_URI,
112
121
  returnIdpCredential: true,
113
122
  returnSecureToken: true,
114
123
  }
115
124
  );
116
125
 
117
- const { displayName, email, idToken, expiresIn, photoUrl } = firebaseRes.data;
118
-
126
+ const { displayName, email, idToken: token, expiresIn, photoUrl } = firebaseRes.data;
119
127
  return {
120
128
  name: displayName,
121
129
  email,
122
- photo: photoUrl,
123
- idToken,
130
+ photo: photoUrl || '',
131
+ idToken: token,
124
132
  expiresAt: Date.now() + parseInt(expiresIn) * 1000,
125
133
  };
126
134
  }
127
135
 
128
136
  // ─── Login ────────────────────────────────────────────────────────────────────
129
137
  async function login() {
130
- // Validate config is filled in
131
- if (
132
- !GOOGLE_CLIENT_ID || GOOGLE_CLIENT_ID === 'YOUR_GOOGLE_CLIENT_ID'
133
- ) {
134
- console.log(
135
- boxen(
136
- chalk.red('✗ Google Client ID not set!\n\n') +
137
- chalk.white('Open ') + chalk.yellow('auth.js') + chalk.white(' and replace:\n\n') +
138
- chalk.cyan('YOUR_GOOGLE_CLIENT_ID') +
139
- chalk.white('\n\nwith your OAuth Client ID from Google Cloud Console.'),
140
- { padding: 1, margin: { left: 2 }, borderStyle: 'round', borderColor: 'red' }
141
- )
142
- );
143
- process.exit(1);
144
- }
145
-
146
- // Build Google OAuth URL
147
- const authUrl = new URL('https://accounts.google.com/o/oauth2/v2/auth');
148
- authUrl.searchParams.set('client_id', GOOGLE_CLIENT_ID);
149
- authUrl.searchParams.set('redirect_uri', REDIRECT_URI);
150
- authUrl.searchParams.set('response_type', 'code');
151
- authUrl.searchParams.set('scope', 'openid email profile');
152
- authUrl.searchParams.set('access_type', 'offline');
153
- authUrl.searchParams.set('prompt', 'select_account');
138
+ const authUrl = buildFirebaseAuthUrl();
154
139
 
155
140
  return new Promise((resolve, reject) => {
156
141
  const server = http.createServer(async (req, res) => {
@@ -163,26 +148,17 @@ async function login() {
163
148
  return;
164
149
  }
165
150
 
166
- const code = parsed.query.code;
167
- const error = parsed.query.error;
168
-
169
151
  // Send success page to browser immediately
170
152
  res.writeHead(200, { 'Content-Type': 'text/html' });
171
153
  res.end(`
172
154
  <html>
173
155
  <body style="
174
- background: #0a0a0a;
175
- color: #fff;
176
- font-family: monospace;
177
- display: flex;
178
- align-items: center;
179
- justify-content: center;
180
- height: 100vh;
181
- margin: 0;
182
- ">
183
- <div style="text-align: center;">
184
- <h1 style="color: #76b900;">✓ Login Successful!</h1>
185
- <p style="color: #aaa;">You can close this tab and return to the terminal.</p>
156
+ background:#0a0a0a;color:#fff;font-family:monospace;
157
+ display:flex;align-items:center;justify-content:center;
158
+ height:100vh;margin:0;">
159
+ <div style="text-align:center;">
160
+ <h1 style="color:#76b900;">✓ Login Successful!</h1>
161
+ <p style="color:#aaa;">You can close this tab and return to the terminal.</p>
186
162
  </div>
187
163
  </body>
188
164
  </html>
@@ -190,6 +166,7 @@ async function login() {
190
166
 
191
167
  server.close();
192
168
 
169
+ const error = parsed.query.error;
193
170
  if (error) {
194
171
  console.log(chalk.red('\n ✗ Login cancelled.\n'));
195
172
  reject(new Error(error));
@@ -198,7 +175,7 @@ async function login() {
198
175
 
199
176
  try {
200
177
  process.stdout.write(chalk.cyan('\n ⏳ Verifying with Firebase...\n'));
201
- const userData = await exchangeCodeForToken(code);
178
+ const userData = await handleFirebaseCallback(parsed.query);
202
179
  saveToken(userData);
203
180
 
204
181
  console.log(
@@ -236,12 +213,10 @@ async function login() {
236
213
  { padding: 1, margin: { left: 2 }, borderStyle: 'double', borderColor: 'green' }
237
214
  )
238
215
  );
239
-
240
- // Small delay to ensure server is ready before opening browser
241
216
  setTimeout(() => openBrowser(authUrl.toString()), 500);
242
217
  });
243
218
 
244
- // Auto-cancel login after 2 minutes
219
+ // Auto-cancel after 2 minutes
245
220
  setTimeout(() => {
246
221
  server.close();
247
222
  console.log(chalk.red('\n ✗ Login timed out (2 min). Please try again.\n'));
package/cli.js CHANGED
@@ -1,28 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- require('dotenv').config({
5
- path: require('path').join(__dirname, '.env')
6
- });
7
-
8
- // ─── Auth check ───────────────────────────────────────────────────────────────
4
+ // ─── Auth ─────────────────────────────────────────────────────────────────────
9
5
  const auth = require('./auth');
10
6
 
11
7
  const arg = process.argv[2];
12
8
 
13
- // Handle: slek login / slek logout / slek status
14
- if (arg === 'login') {
15
- auth.login().catch(() => process.exit(1));
16
- return;
17
- }
18
- if (arg === 'logout') {
19
- auth.logout();
20
- process.exit(0);
21
- }
22
- if (arg === 'status') {
23
- auth.status();
24
- process.exit(0);
25
- }
9
+ if (arg === 'login') { auth.login().catch(() => process.exit(1)); return; }
10
+ if (arg === 'logout') { auth.logout(); process.exit(0); }
11
+ if (arg === 'status') { auth.status(); process.exit(0); }
26
12
 
27
13
  // Block access if not logged in
28
14
  if (!auth.isLoggedIn()) {
@@ -40,31 +26,31 @@ if (!auth.isLoggedIn()) {
40
26
  }
41
27
 
42
28
  const readline = require('readline');
43
- const axios = require('axios');
44
- const chalk = require('chalk');
45
- const boxen = require('boxen');
29
+ const axios = require('axios');
30
+ const chalk = require('chalk');
31
+ const boxen = require('boxen');
46
32
  const gradient = require('gradient-string');
47
- const figlet = require('figlet');
33
+ const figlet = require('figlet');
48
34
 
49
- // ─── NOTE: ora v5 is required (CommonJS compatible) ──────────────────────────
50
- // If ora gives errors, run: npm install ora@5
51
35
  let ora;
52
36
  try {
53
37
  ora = require('ora');
54
38
  } catch {
55
- // Fallback spinner if ora fails
56
39
  ora = (opts) => ({
57
- start: () => { process.stdout.write(chalk.cyan(' ⏳ ' + (opts.text || 'Loading...') + '\n')); return { stop: () => {}, fail: () => {} }; },
40
+ start: () => {
41
+ process.stdout.write(chalk.cyan(' ⏳ ' + (opts.text || 'Loading...') + '\n'));
42
+ return { stop: () => {}, fail: () => {} };
43
+ },
58
44
  stop: () => {},
59
45
  fail: () => {},
60
46
  });
61
47
  }
62
48
 
63
- // ─── NVIDIA API Config ────────────────────────────────────────────────────────
49
+ // ─── API Config ───────────────────────────────────────────────────────────────
64
50
  const NVIDIA_API_BASE = 'https://slek-ai-portal.vercel.app/api';
65
- const DEFAULT_MODEL = 'qwen/qwen3.5-122b-a10b';
51
+ const DEFAULT_MODEL = 'qwen/qwen3.5-122b-a10b';
66
52
 
67
- // ─── User config path (stored in user's home, not in project) ─────────────────
53
+ // ─── User config path ─────────────────────────────────────────────────────────
68
54
  const CONFIG_PATH = require('path').join(
69
55
  process.env.APPDATA || process.env.HOME || __dirname,
70
56
  '.slek-config.json'
@@ -75,24 +61,28 @@ function loadConfig() {
75
61
  if (require('fs').existsSync(CONFIG_PATH)) {
76
62
  return JSON.parse(require('fs').readFileSync(CONFIG_PATH, 'utf8'));
77
63
  }
78
- } catch { }
64
+ } catch (_) {}
79
65
  return {};
80
66
  }
81
67
 
82
68
  function saveConfig(data) {
83
69
  const current = loadConfig();
84
- require('fs').writeFileSync(CONFIG_PATH, JSON.stringify({ ...current, ...data }, null, 2), 'utf8');
70
+ require('fs').writeFileSync(
71
+ CONFIG_PATH,
72
+ JSON.stringify({ ...current, ...data }, null, 2),
73
+ 'utf8'
74
+ );
85
75
  }
86
76
 
87
- // ─── Gradient Colors ─────────────────────────────────────────────────────────
77
+ // ─── Gradients ────────────────────────────────────────────────────────────────
88
78
  const nvidiaGradient = gradient(['#76b900', '#00c8ff']);
89
- const userGradient = gradient(['#ff6b6b', '#feca57']);
90
- const aiGradient = gradient(['#48dbfb', '#ff9ff3']);
91
- const thinkGradient = gradient(['#f7971e', '#ffd200']);
79
+ const userGradient = gradient(['#ff6b6b', '#feca57']);
80
+ const aiGradient = gradient(['#48dbfb', '#ff9ff3']);
81
+ const thinkGradient = gradient(['#f7971e', '#ffd200']);
92
82
 
93
- // ─── State ───────────────────────────────────────────────────────────────────
94
- let chatHistory = [];
95
- let apiKey = process.env.NVIDIA_API_KEY || '';
83
+ // ─── State ────────────────────────────────────────────────────────────────────
84
+ let chatHistory = [];
85
+ let apiKey = loadConfig().apiKey || '';
96
86
  const currentUser = auth.getUser();
97
87
 
98
88
  // ─── Helpers ──────────────────────────────────────────────────────────────────
@@ -103,17 +93,14 @@ function clearLine() {
103
93
  // ─── Banner ───────────────────────────────────────────────────────────────────
104
94
  async function showBanner() {
105
95
  console.clear();
106
- const banner = figlet.textSync('SLEK AI', {
107
- font: 'ANSI Shadow',
108
- horizontalLayout: 'default',
109
- });
96
+ const banner = figlet.textSync('SLEK AI', { font: 'ANSI Shadow' });
110
97
  console.log(nvidiaGradient(banner));
111
98
  console.log(
112
99
  boxen(
113
100
  chalk.bold.white('🚀 SLEK AI CLI') + chalk.gray(' — Powered by NVIDIA API\n') +
114
- chalk.gray(''.repeat(42)) + '\n' +
101
+ chalk.gray(''.repeat(42)) + '\n' +
115
102
  chalk.cyan(' User : ') + chalk.green(currentUser ? currentUser.name : 'Unknown') + '\n' +
116
- chalk.gray(''.repeat(42)) + '\n' +
103
+ chalk.gray(''.repeat(42)) + '\n' +
117
104
  chalk.white(' Type ') + chalk.yellow('/help') + chalk.white(' for available commands'),
118
105
  {
119
106
  padding: 1,
@@ -128,87 +115,37 @@ async function showBanner() {
128
115
 
129
116
  // ─── Help ─────────────────────────────────────────────────────────────────────
130
117
  function showHelp() {
131
- const helpBox = boxen(
132
- chalk.bold.cyan('📋 Available Commands\n') +
133
- chalk.gray('═'.repeat(42)) + '\n\n' +
134
- chalk.yellow('/help ') + chalk.white('Show this help menu\n') +
135
- chalk.yellow('/clear ') + chalk.white('Clear chat history\n') +
136
- chalk.yellow('/history ') + chalk.white('Show chat history\n') +
137
- chalk.yellow('/save ') + chalk.white('Save chat to file\n') +
138
- chalk.yellow('/info ') + chalk.white('Show current settings\n') +
139
- chalk.yellow('/exit ') + chalk.white('Exit the CLI\n\n') +
140
- chalk.gray('Or just type anything to chat with AI!'),
141
- {
142
- padding: 1,
143
- margin: { left: 2 },
144
- borderStyle: 'round',
145
- borderColor: 'cyan',
146
- }
118
+ console.log(
119
+ boxen(
120
+ chalk.bold.cyan('📋 Available Commands\n') +
121
+ chalk.gray(''.repeat(42)) + '\n\n' +
122
+ chalk.yellow('/help ') + chalk.white('Show this help menu\n') +
123
+ chalk.yellow('/clear ') + chalk.white('Clear chat history\n') +
124
+ chalk.yellow('/history ') + chalk.white('Show chat history\n') +
125
+ chalk.yellow('/save ') + chalk.white('Save chat to file\n') +
126
+ chalk.yellow('/info ') + chalk.white('Show current settings\n') +
127
+ chalk.yellow('/exit ') + chalk.white('Exit the CLI\n\n') +
128
+ chalk.gray('Or just type anything to chat with AI!'),
129
+ { padding: 1, margin: { left: 2 }, borderStyle: 'round', borderColor: 'cyan' }
130
+ )
147
131
  );
148
- console.log(helpBox);
149
- }
150
-
151
- // ─── Show Models ──────────────────────────────────────────────────────────────
152
- function showModels() {
153
- console.log('\n' + chalk.bold.cyan(' 🤖 Available Models:\n'));
154
- Object.entries(MODELS).forEach(([key, model]) => {
155
- const active = model.id === currentModel ? chalk.green(' ◄ ACTIVE') : '';
156
- const thinking = model.thinking ? chalk.yellow(' [🧠 Thinking]') : '';
157
- console.log(` ${chalk.yellow(key + '.')} ${chalk.white(model.name)}${thinking}${active}`);
158
- });
159
- console.log();
160
- }
161
-
162
- // ─── Change Model ─────────────────────────────────────────────────────────────
163
- async function changeModel(rl) {
164
- showModels();
165
- return new Promise(resolve => {
166
- rl.question(chalk.cyan(' Enter model number (1-7): '), answer => {
167
- const chosen = MODELS[answer.trim()];
168
- if (chosen) {
169
- currentModel = chosen.id;
170
- enableThinking = chosen.thinking || false;
171
- const thinkNote = chosen.thinking ? chalk.yellow(' (Thinking mode ON)') : '';
172
- console.log(chalk.green(`\n ✓ Model: ${chalk.yellow(chosen.name.trim())}${thinkNote}\n`));
173
- } else {
174
- console.log(chalk.red('\n ✗ Invalid choice\n'));
175
- }
176
- resolve();
177
- });
178
- });
179
- }
180
-
181
- // ─── Toggle Thinking ──────────────────────────────────────────────────────────
182
- function toggleThinking() {
183
- enableThinking = !enableThinking;
184
- if (enableThinking) {
185
- console.log(chalk.green('\n 🧠 Thinking mode: ON\n'));
186
- } else {
187
- console.log(chalk.gray('\n 💤 Thinking mode: OFF\n'));
188
- }
189
132
  }
190
133
 
191
-
192
-
193
- // ─── Show Info ────────────────────────────────────────────────────────────────
134
+ // ─── Info ─────────────────────────────────────────────────────────────────────
194
135
  function showInfo() {
195
- const infoBox = boxen(
196
- chalk.bold.white('⚙ Current Settings\n') +
197
- chalk.gray('─'.repeat(40)) + '\n\n' +
198
- chalk.cyan('User : ') + chalk.green(currentUser ? currentUser.name : 'Unknown') + '\n' +
199
- chalk.cyan('Messages : ') + chalk.white(chatHistory.length + ' in history') + '\n' +
200
- chalk.cyan('API URL : ') + chalk.gray(NVIDIA_API_BASE),
201
- {
202
- padding: 1,
203
- margin: { left: 2 },
204
- borderStyle: 'single',
205
- borderColor: 'yellow',
206
- }
136
+ console.log(
137
+ '\n' + boxen(
138
+ chalk.bold.white('⚙ Current Settings\n') +
139
+ chalk.gray(''.repeat(40)) + '\n\n' +
140
+ chalk.cyan('User : ') + chalk.green(currentUser ? currentUser.name : 'Unknown') + '\n' +
141
+ chalk.cyan('Messages : ') + chalk.white(chatHistory.length + ' in history') + '\n' +
142
+ chalk.cyan('API URL : ') + chalk.gray(NVIDIA_API_BASE),
143
+ { padding: 1, margin: { left: 2 }, borderStyle: 'single', borderColor: 'yellow' }
144
+ )
207
145
  );
208
- console.log('\n' + infoBox);
209
146
  }
210
147
 
211
- // ─── Show History ─────────────────────────────────────────────────────────────
148
+ // ─── History ──────────────────────────────────────────────────────────────────
212
149
  function showHistory() {
213
150
  if (chatHistory.length === 0) {
214
151
  console.log(chalk.yellow('\n No chat history yet.\n'));
@@ -239,7 +176,7 @@ async function saveChat() {
239
176
 
240
177
  let content = `SLEK AI CLI - Chat Log\n`;
241
178
  content += `Date: ${new Date().toLocaleString()}\n`;
242
- content += `Model: ${currentModel}\n`;
179
+ content += `Model: ${DEFAULT_MODEL}\n`;
243
180
  content += `${'═'.repeat(50)}\n\n`;
244
181
 
245
182
  chatHistory.forEach(msg => {
@@ -252,13 +189,13 @@ async function saveChat() {
252
189
  });
253
190
 
254
191
  fs.writeFileSync(filepath, content, 'utf8');
255
- console.log(chalk.green(`\n Chat saved to: ${chalk.yellow(filename)}\n`));
192
+ console.log(chalk.green(`\n Chat saved to: ${chalk.yellow(filename)}\n`));
256
193
  }
257
194
 
258
195
  // ─── Stream API Call ──────────────────────────────────────────────────────────
259
196
  async function callNvidiaAPIStream(userMessage) {
260
197
  if (!apiKey) {
261
- throw new Error('API key not configured. Please set NVIDIA_API_KEY in your .env file.');
198
+ throw new Error('API key not set. Ask the admin for your SLEK API key.');
262
199
  }
263
200
 
264
201
  chatHistory.push({ role: 'user', content: userMessage });
@@ -273,19 +210,17 @@ async function callNvidiaAPIStream(userMessage) {
273
210
  ...chatHistory,
274
211
  ];
275
212
 
276
- const payload = {
277
- model: DEFAULT_MODEL,
278
- messages,
279
- max_tokens: 16384,
280
- temperature: 0.60,
281
- top_p: 0.95,
282
- stream: true,
283
- chat_template_kwargs: { enable_thinking: true },
284
- };
285
-
286
213
  const response = await axios.post(
287
214
  `${NVIDIA_API_BASE}/chat-free`,
288
- payload,
215
+ {
216
+ model: DEFAULT_MODEL,
217
+ messages,
218
+ max_tokens: 16384,
219
+ temperature: 0.60,
220
+ top_p: 0.95,
221
+ stream: true,
222
+ chat_template_kwargs: { enable_thinking: true },
223
+ },
289
224
  {
290
225
  headers: {
291
226
  Authorization: `Bearer ${apiKey}`,
@@ -298,8 +233,8 @@ async function callNvidiaAPIStream(userMessage) {
298
233
  );
299
234
 
300
235
  return new Promise((resolve, reject) => {
301
- let fullResponse = '';
302
- let inThinkBlock = false;
236
+ let fullResponse = '';
237
+ let inThinkBlock = false;
303
238
 
304
239
  process.stdout.write('\n ' + aiGradient('✦ SLEK AI: ') + '\n\n ');
305
240
 
@@ -325,12 +260,10 @@ async function callNvidiaAPIStream(userMessage) {
325
260
  continue;
326
261
  }
327
262
 
328
- if (inThinkBlock) {
329
- process.stdout.write(chalk.dim.yellow(token));
330
- } else {
331
- process.stdout.write(chalk.white(token));
332
- }
333
- } catch { /* ignore malformed SSE lines */ }
263
+ process.stdout.write(
264
+ inThinkBlock ? chalk.dim.yellow(token) : chalk.white(token)
265
+ );
266
+ } catch (_) { /* ignore malformed SSE lines */ }
334
267
  }
335
268
  }
336
269
  });
@@ -346,7 +279,7 @@ async function callNvidiaAPIStream(userMessage) {
346
279
  });
347
280
  }
348
281
 
349
- // ─── Process User Input ───────────────────────────────────────────────────────
282
+ // ─── Process Input ────────────────────────────────────────────────────────────
350
283
  async function processInput(input, rl) {
351
284
  const trimmed = input.trim();
352
285
  if (!trimmed) return;
@@ -354,14 +287,14 @@ async function processInput(input, rl) {
354
287
  if (trimmed.startsWith('/')) {
355
288
  const cmd = trimmed.toLowerCase().split(' ')[0];
356
289
  switch (cmd) {
357
- case '/help': showHelp(); break;
290
+ case '/help': showHelp(); break;
358
291
  case '/clear':
359
292
  chatHistory = [];
360
- console.log(chalk.green('\n Chat history cleared!\n'));
293
+ console.log(chalk.green('\n Chat history cleared!\n'));
361
294
  break;
362
- case '/history': showHistory(); break;
363
- case '/save': await saveChat(); break;
364
- case '/info': showInfo(); break;
295
+ case '/history': showHistory(); break;
296
+ case '/save': await saveChat(); break;
297
+ case '/info': showInfo(); break;
365
298
  case '/exit':
366
299
  case '/quit':
367
300
  console.log('\n' + nvidiaGradient(' 👋 Goodbye! Thanks for using SLEK AI CLI\n'));
@@ -375,9 +308,9 @@ async function processInput(input, rl) {
375
308
  }
376
309
 
377
310
  const spinner = ora({
378
- text: chalk.cyan(' Connecting to NVIDIA API...'),
379
- spinner: 'dots',
380
- color: 'cyan',
311
+ text: chalk.cyan(' Connecting to NVIDIA API...'),
312
+ spinner: 'dots',
313
+ color: 'cyan',
381
314
  prefixText: ' ',
382
315
  }).start();
383
316
 
@@ -393,13 +326,10 @@ async function processInput(input, rl) {
393
326
  err.message ||
394
327
  'Unknown error';
395
328
  console.log(
396
- '\n' +
397
- boxen(chalk.red('✗ Error: ') + chalk.white(errMsg), {
398
- padding: 1,
399
- margin: { left: 2 },
400
- borderStyle: 'round',
401
- borderColor: 'red',
402
- }) + '\n'
329
+ '\n' + boxen(
330
+ chalk.red('✗ Error: ') + chalk.white(errMsg),
331
+ { padding: 1, margin: { left: 2 }, borderStyle: 'round', borderColor: 'red' }
332
+ ) + '\n'
403
333
  );
404
334
  }
405
335
  }
@@ -408,9 +338,7 @@ async function processInput(input, rl) {
408
338
  function showPrompt(rl) {
409
339
  const prompt =
410
340
  '\n' +
411
- chalk.gray(' ┌─') +
412
- userGradient(' You ') +
413
- chalk.gray('─────────────────────────────────\n') +
341
+ chalk.gray(' ┌─') + userGradient(' You ') + chalk.gray('─────────────────────────────────\n') +
414
342
  chalk.gray(' └▶ ');
415
343
  rl.setPrompt(prompt);
416
344
  rl.prompt();
@@ -420,11 +348,9 @@ function showPrompt(rl) {
420
348
  async function main() {
421
349
  await showBanner();
422
350
 
423
-
424
-
425
351
  const rl = readline.createInterface({
426
- input: process.stdin,
427
- output: process.stdout,
352
+ input: process.stdin,
353
+ output: process.stdout,
428
354
  terminal: true,
429
355
  });
430
356
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slek-ai-cli",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "description": "SLEK AI CLI — Powered by NVIDIA API",
5
5
  "main": "cli.js",
6
6
  "bin": {
@@ -17,6 +17,7 @@
17
17
  "figlet": "^1.7.0",
18
18
  "gradient-string": "^2.0.2",
19
19
  "open": "^8.4.2",
20
- "ora": "^5.4.1"
20
+ "ora": "^5.4.1",
21
+ "slek-ai-cli": "^1.1.6"
21
22
  }
22
23
  }