npm-noxyai 1.0.19 → 1.0.20
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/index-noxyai.js +85 -12
- package/package.json +1 -1
package/index-noxyai.js
CHANGED
|
@@ -129,10 +129,12 @@ async function login() {
|
|
|
129
129
|
const platform = os.platform();
|
|
130
130
|
if (platform === 'darwin') execSync(`echo "${userCode}" | pbcopy`);
|
|
131
131
|
else if (platform === 'win32') execSync(`echo ${userCode} | clip`);
|
|
132
|
-
else if (platform === 'linux' && execSync('which xclip').toString())
|
|
132
|
+
else if (platform === 'linux' && execSync('which xclip 2>/dev/null').toString())
|
|
133
133
|
execSync(`echo "${userCode}" | xclip -selection clipboard`);
|
|
134
134
|
console.log('\x1b[32m✓ Code copied to clipboard!\x1b[0m');
|
|
135
|
-
} catch (e) {
|
|
135
|
+
} catch (e) {
|
|
136
|
+
// Clipboard not available, ignore
|
|
137
|
+
}
|
|
136
138
|
|
|
137
139
|
rl.question('\x1b[36mPress ENTER to open browser or type "q" to cancel:\x1b[0m ', (answer) => {
|
|
138
140
|
if (answer.toLowerCase() === 'q') {
|
|
@@ -155,7 +157,7 @@ async function login() {
|
|
|
155
157
|
if (Date.now() - startTime > maxTime) {
|
|
156
158
|
clearInterval(pollInterval);
|
|
157
159
|
stopSpinner();
|
|
158
|
-
console.log('\x1b[31m❌ Login timeout. Please try again.\x1b[0m');
|
|
160
|
+
console.log('\n\x1b[31m❌ Login timeout. Please try again.\x1b[0m');
|
|
159
161
|
process.exit(1);
|
|
160
162
|
}
|
|
161
163
|
|
|
@@ -175,6 +177,7 @@ async function login() {
|
|
|
175
177
|
config.token = data.token;
|
|
176
178
|
config.userEmail = data.email;
|
|
177
179
|
config.userId = data.userId;
|
|
180
|
+
config.lastLogin = Date.now();
|
|
178
181
|
saveConfig(config);
|
|
179
182
|
console.clear();
|
|
180
183
|
printLogo();
|
|
@@ -248,7 +251,7 @@ function runTerminalCommand(cmd, options = {}) {
|
|
|
248
251
|
});
|
|
249
252
|
}
|
|
250
253
|
|
|
251
|
-
//
|
|
254
|
+
// FIXED: Safe context gathering without Git errors
|
|
252
255
|
function getLocalContext() {
|
|
253
256
|
try {
|
|
254
257
|
const cwd = process.cwd();
|
|
@@ -260,10 +263,20 @@ function getLocalContext() {
|
|
|
260
263
|
? JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'))
|
|
261
264
|
: null;
|
|
262
265
|
|
|
266
|
+
// FIX: Silent Git branch check - no error output
|
|
263
267
|
const gitBranch = (() => {
|
|
264
268
|
try {
|
|
265
|
-
|
|
266
|
-
|
|
269
|
+
// Check if .git directory exists first
|
|
270
|
+
if (fs.existsSync(path.join(cwd, '.git'))) {
|
|
271
|
+
return execSync('git branch --show-current', {
|
|
272
|
+
encoding: 'utf8',
|
|
273
|
+
stdio: ['pipe', 'pipe', 'pipe'] // Suppress stderr
|
|
274
|
+
}).trim();
|
|
275
|
+
}
|
|
276
|
+
return null;
|
|
277
|
+
} catch (e) {
|
|
278
|
+
return null; // Silently fail
|
|
279
|
+
}
|
|
267
280
|
})();
|
|
268
281
|
|
|
269
282
|
return `\n[SYSTEM CONTEXT]
|
|
@@ -300,13 +313,57 @@ function cacheSearchResults(query, results) {
|
|
|
300
313
|
}));
|
|
301
314
|
}
|
|
302
315
|
|
|
316
|
+
// FIXED: Better session validation
|
|
317
|
+
async function validateSession(config) {
|
|
318
|
+
if (!config.token) return false;
|
|
319
|
+
|
|
320
|
+
// Check if session is recent (within 24h)
|
|
321
|
+
if (config.lastLogin && Date.now() - config.lastLogin < 86400000) {
|
|
322
|
+
return true;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
try {
|
|
326
|
+
const res = await fetch(BASE_URL + '/api/cli/validate', {
|
|
327
|
+
method: 'POST',
|
|
328
|
+
headers: {
|
|
329
|
+
'Authorization': 'Bearer ' + config.token,
|
|
330
|
+
'Content-Type': 'application/json'
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
if (res.ok) {
|
|
335
|
+
config.lastLogin = Date.now();
|
|
336
|
+
saveConfig(config);
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return false;
|
|
341
|
+
} catch (e) {
|
|
342
|
+
// Network error - assume valid if we have a token
|
|
343
|
+
return true;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
303
347
|
async function chat(prompt, depth = 0) {
|
|
304
348
|
const config = loadConfig();
|
|
349
|
+
|
|
350
|
+
// FIXED: Better session validation
|
|
305
351
|
if (!config.token) {
|
|
306
|
-
console.error('\x1b[31m❌
|
|
352
|
+
console.error('\x1b[31m❌ Not logged in. Run "noxyai login" first\x1b[0m');
|
|
307
353
|
return;
|
|
308
354
|
}
|
|
309
355
|
|
|
356
|
+
// FIXED: Don't immediately invalidate session on network errors
|
|
357
|
+
const isValid = await validateSession(config);
|
|
358
|
+
if (!isValid) {
|
|
359
|
+
console.error('\x1b[31m❌ Session expired. Please login again.\x1b[0m');
|
|
360
|
+
config.token = null;
|
|
361
|
+
config.userEmail = null;
|
|
362
|
+
config.lastLogin = null;
|
|
363
|
+
saveConfig(config);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
310
367
|
if (depth > 8) {
|
|
311
368
|
console.error('\n\x1b[31m❌ Maximum recursion depth reached. Breaking loop.\x1b[0m');
|
|
312
369
|
return;
|
|
@@ -343,17 +400,31 @@ async function chat(prompt, depth = 0) {
|
|
|
343
400
|
|
|
344
401
|
if (!res.ok) {
|
|
345
402
|
const errorText = await res.text();
|
|
403
|
+
|
|
404
|
+
// FIXED: Better error handling
|
|
346
405
|
if (res.status === 401) {
|
|
347
|
-
console.error('\x1b[31m❌
|
|
406
|
+
console.error('\x1b[31m❌ Invalid or expired session.\x1b[0m');
|
|
407
|
+
console.error('\x1b[33mPlease run:\x1b[0m \x1b[36mnoxyai login\x1b[0m\n');
|
|
348
408
|
config.token = null;
|
|
409
|
+
config.userEmail = null;
|
|
410
|
+
config.lastLogin = null;
|
|
349
411
|
saveConfig(config);
|
|
350
412
|
return;
|
|
351
413
|
}
|
|
414
|
+
|
|
352
415
|
if (res.status === 402) {
|
|
353
|
-
console.error('\x1b[31m❌ Insufficient credits
|
|
416
|
+
console.error('\x1b[31m❌ Insufficient credits.\x1b[0m');
|
|
417
|
+
console.error('\x1b[33mVisit:\x1b[0m \x1b[36mhttps://noxyai.com/pricing\x1b[0m\n');
|
|
354
418
|
return;
|
|
355
419
|
}
|
|
356
|
-
|
|
420
|
+
|
|
421
|
+
if (res.status === 429) {
|
|
422
|
+
console.error('\x1b[31m❌ Rate limit exceeded. Please wait a moment.\x1b[0m');
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
console.error(`\x1b[31m❌ API Error (${res.status}):\x1b[0m ${errorText.substring(0, 200)}`);
|
|
427
|
+
return;
|
|
357
428
|
}
|
|
358
429
|
|
|
359
430
|
console.log(`\n🤖 \x1b[36mNoxyAI (${config.model}):\x1b[0m\n`);
|
|
@@ -650,7 +721,8 @@ async function chat(prompt, depth = 0) {
|
|
|
650
721
|
|
|
651
722
|
} catch (error) {
|
|
652
723
|
stopSpinner();
|
|
653
|
-
console.error('\n\x1b[31m❌ Connection error:\x1b[0m ' + error.message);
|
|
724
|
+
console.error('\n\x1b[31m❌ Connection error:\x1b[0m ' + error.message);
|
|
725
|
+
console.error('\x1b[33mTip: Check your internet connection and try again.\x1b[0m');
|
|
654
726
|
}
|
|
655
727
|
}
|
|
656
728
|
|
|
@@ -746,6 +818,7 @@ if (command === 'login') {
|
|
|
746
818
|
const c = loadConfig();
|
|
747
819
|
c.token = null;
|
|
748
820
|
c.userEmail = null;
|
|
821
|
+
c.lastLogin = null;
|
|
749
822
|
saveConfig(c);
|
|
750
823
|
console.log('\x1b[32m✓ Successfully logged out.\x1b[0m\n');
|
|
751
824
|
process.exit(0);
|
|
@@ -779,7 +852,7 @@ if (command === 'login') {
|
|
|
779
852
|
`);
|
|
780
853
|
process.exit(0);
|
|
781
854
|
} else if (command === 'version' || command === '--version' || command === '-v') {
|
|
782
|
-
console.log('NoxyAI CLI v1.0.
|
|
855
|
+
console.log('NoxyAI CLI v1.0.1');
|
|
783
856
|
process.exit(0);
|
|
784
857
|
} else if (!command) {
|
|
785
858
|
startInteractiveMode();
|