vibex-sh 0.12.3 → 0.13.0
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.js +118 -22
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -449,6 +449,7 @@ async function handleInit(options) {
|
|
|
449
449
|
|
|
450
450
|
// Get token - required for authenticated session creation
|
|
451
451
|
let token = process.env.VIBEX_TOKEN || await getStoredToken();
|
|
452
|
+
const tokenSource = process.env.VIBEX_TOKEN ? 'cli-env' : 'cli-config';
|
|
452
453
|
if (!token) {
|
|
453
454
|
console.error('\n ✗ Authentication required');
|
|
454
455
|
console.error(' 💡 Run: npx vibex-sh login');
|
|
@@ -462,6 +463,7 @@ async function handleInit(options) {
|
|
|
462
463
|
headers: {
|
|
463
464
|
'Content-Type': 'application/json',
|
|
464
465
|
'Authorization': `Bearer ${token}`,
|
|
466
|
+
'X-Token-Source': tokenSource,
|
|
465
467
|
},
|
|
466
468
|
body: JSON.stringify({
|
|
467
469
|
enabledParsers: enabledParsers.length > 0 ? enabledParsers : undefined,
|
|
@@ -556,7 +558,20 @@ async function handleSendLogs(options) {
|
|
|
556
558
|
const { webUrl, socketUrl } = getProductionUrls();
|
|
557
559
|
|
|
558
560
|
// Get token - REQUIRED for all operations
|
|
559
|
-
|
|
561
|
+
// Track token source for debugging
|
|
562
|
+
let token;
|
|
563
|
+
let tokenSource = 'cli-config'; // default
|
|
564
|
+
if (options.token) {
|
|
565
|
+
token = options.token;
|
|
566
|
+
tokenSource = 'cli-option';
|
|
567
|
+
} else if (process.env.VIBEX_TOKEN) {
|
|
568
|
+
token = process.env.VIBEX_TOKEN;
|
|
569
|
+
tokenSource = 'cli-env';
|
|
570
|
+
} else {
|
|
571
|
+
token = await getStoredToken();
|
|
572
|
+
tokenSource = 'cli-config';
|
|
573
|
+
}
|
|
574
|
+
|
|
560
575
|
if (!token) {
|
|
561
576
|
console.error('\n ✗ Authentication required');
|
|
562
577
|
console.error(' 💡 Run: npx vibex-sh login to authenticate');
|
|
@@ -602,11 +617,14 @@ async function handleSendLogs(options) {
|
|
|
602
617
|
|
|
603
618
|
try {
|
|
604
619
|
const createUrl = `${webUrl}/api/sessions/create`;
|
|
620
|
+
// Determine token source for this request
|
|
621
|
+
const requestTokenSource = options.token ? 'cli-option' : (process.env.VIBEX_TOKEN ? 'cli-env' : 'cli-config');
|
|
605
622
|
const response = await httpRequest(createUrl, {
|
|
606
623
|
method: 'POST',
|
|
607
624
|
headers: {
|
|
608
625
|
'Content-Type': 'application/json',
|
|
609
626
|
'Authorization': `Bearer ${token}`,
|
|
627
|
+
'X-Token-Source': requestTokenSource,
|
|
610
628
|
},
|
|
611
629
|
body: JSON.stringify({
|
|
612
630
|
enabledParsers: enabledParsers.length > 0 ? enabledParsers : undefined,
|
|
@@ -728,7 +746,69 @@ async function handleSendLogs(options) {
|
|
|
728
746
|
});
|
|
729
747
|
};
|
|
730
748
|
|
|
731
|
-
|
|
749
|
+
// WebSocket token cache
|
|
750
|
+
let websocketToken = null;
|
|
751
|
+
let websocketTokenExpiresAt = 0;
|
|
752
|
+
|
|
753
|
+
// Fetch WebSocket token from API
|
|
754
|
+
const fetchWebSocketToken = async () => {
|
|
755
|
+
try {
|
|
756
|
+
// Check if we have a valid cached token
|
|
757
|
+
const now = Date.now();
|
|
758
|
+
if (websocketToken && websocketTokenExpiresAt > now + 60000) {
|
|
759
|
+
// Token is still valid (at least 1 minute remaining)
|
|
760
|
+
return websocketToken;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// Fetch new token
|
|
764
|
+
const tokenUrl = `${webUrl}/api/session/${sessionId}/websocket-token`;
|
|
765
|
+
const response = await httpRequest(tokenUrl, {
|
|
766
|
+
method: 'GET',
|
|
767
|
+
headers: {
|
|
768
|
+
'Authorization': `Bearer ${token}`,
|
|
769
|
+
'Content-Type': 'application/json',
|
|
770
|
+
},
|
|
771
|
+
});
|
|
772
|
+
|
|
773
|
+
if (!response.ok) {
|
|
774
|
+
const errorData = await response.json().catch(() => ({ message: response.status === 401 ? 'Authentication required' : 'Unknown error' }));
|
|
775
|
+
|
|
776
|
+
if (response.status === 401) {
|
|
777
|
+
console.error(chalk.red('\n ✗ Authentication failed'));
|
|
778
|
+
console.error(chalk.yellow(' 💡 Run: npx vibex-sh login to authenticate'));
|
|
779
|
+
console.error('');
|
|
780
|
+
process.exit(1);
|
|
781
|
+
} else if (response.status === 403) {
|
|
782
|
+
console.error(chalk.red(`\n ✗ Access denied: ${errorData.message || 'You do not have permission to access this session'}`));
|
|
783
|
+
process.exit(1);
|
|
784
|
+
} else if (response.status === 404) {
|
|
785
|
+
console.error(chalk.red(`\n ✗ Session not found: ${errorData.message || 'The session does not exist'}`));
|
|
786
|
+
process.exit(1);
|
|
787
|
+
} else if (response.status === 503) {
|
|
788
|
+
// Database not ready yet - retry after delay
|
|
789
|
+
console.warn(chalk.yellow(' ⚠️ Session database not ready yet, retrying in 2 seconds...'));
|
|
790
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
791
|
+
return await fetchWebSocketToken(); // Retry
|
|
792
|
+
} else {
|
|
793
|
+
console.error(chalk.red(`\n ✗ Failed to get WebSocket token: ${errorData.message || 'Unknown error'}`));
|
|
794
|
+
process.exit(1);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
const data = await response.json();
|
|
799
|
+
websocketToken = data.token;
|
|
800
|
+
websocketTokenExpiresAt = data.expiresAt;
|
|
801
|
+
|
|
802
|
+
return websocketToken;
|
|
803
|
+
} catch (err) {
|
|
804
|
+
console.error(chalk.red(`\n ✗ Error fetching WebSocket token: ${err.message}`));
|
|
805
|
+
console.error(chalk.yellow(' 💡 Run: npx vibex-sh login to authenticate'));
|
|
806
|
+
console.error('');
|
|
807
|
+
process.exit(1);
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
|
|
811
|
+
const connectWebSocket = async () => {
|
|
732
812
|
// Prevent multiple simultaneous connections
|
|
733
813
|
if (connectionLock) {
|
|
734
814
|
console.log(' ⚠️ Connection already in progress, skipping...');
|
|
@@ -746,24 +826,32 @@ async function handleSendLogs(options) {
|
|
|
746
826
|
reconnectTimeout = null;
|
|
747
827
|
}
|
|
748
828
|
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
829
|
+
connectionLock = true;
|
|
830
|
+
connectionState = 'connecting';
|
|
831
|
+
connectionStartTime = Date.now();
|
|
832
|
+
if (!hasStdin || !progressBar) {
|
|
833
|
+
console.log(chalk.blue(' 🔄 Connecting to WebSocket...'));
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
try {
|
|
837
|
+
// Fetch WebSocket token first
|
|
838
|
+
const wsToken = await fetchWebSocketToken();
|
|
839
|
+
if (!wsToken) {
|
|
840
|
+
connectionLock = false;
|
|
841
|
+
connectionState = 'disconnected';
|
|
842
|
+
return;
|
|
754
843
|
}
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
// Ignore errors when closing
|
|
763
|
-
}
|
|
844
|
+
|
|
845
|
+
// Close existing socket if any (cleanup)
|
|
846
|
+
if (socket && socket.readyState !== WebSocket.CLOSED) {
|
|
847
|
+
try {
|
|
848
|
+
socket.close();
|
|
849
|
+
} catch (e) {
|
|
850
|
+
// Ignore errors when closing
|
|
764
851
|
}
|
|
765
|
-
|
|
766
|
-
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
socket = new WebSocket(`${socketUrl}?sessionId=${sessionId}&token=${wsToken}`);
|
|
767
855
|
|
|
768
856
|
socket.onopen = () => {
|
|
769
857
|
const connectTime = Date.now() - connectionStartTime;
|
|
@@ -948,7 +1036,9 @@ async function handleSendLogs(options) {
|
|
|
948
1036
|
console.log(` ↻ Reconnecting in ${delay}ms (attempt ${reconnectAttempts})...\n`);
|
|
949
1037
|
|
|
950
1038
|
reconnectTimeout = setTimeout(() => {
|
|
951
|
-
connectWebSocket()
|
|
1039
|
+
connectWebSocket().catch(err => {
|
|
1040
|
+
console.error(` ✗ Error reconnecting: ${err.message}`);
|
|
1041
|
+
});
|
|
952
1042
|
}, delay);
|
|
953
1043
|
} else if (event.code === 1000) {
|
|
954
1044
|
console.log(' ✓ Normal closure, no reconnect needed\n');
|
|
@@ -962,7 +1052,9 @@ async function handleSendLogs(options) {
|
|
|
962
1052
|
console.error(` ↻ URL: ${socketUrl}`);
|
|
963
1053
|
// Retry connection
|
|
964
1054
|
reconnectTimeout = setTimeout(() => {
|
|
965
|
-
connectWebSocket()
|
|
1055
|
+
connectWebSocket().catch(err => {
|
|
1056
|
+
console.error(` ✗ Error retrying connection: ${err.message}`);
|
|
1057
|
+
});
|
|
966
1058
|
}, 1000);
|
|
967
1059
|
}
|
|
968
1060
|
};
|
|
@@ -981,6 +1073,7 @@ async function handleSendLogs(options) {
|
|
|
981
1073
|
const headers = {
|
|
982
1074
|
'Content-Type': 'application/json',
|
|
983
1075
|
'Authorization': `Bearer ${token}`,
|
|
1076
|
+
'X-Token-Source': tokenSource, // Track token origin for debugging
|
|
984
1077
|
};
|
|
985
1078
|
|
|
986
1079
|
const response = await fetch(ingestUrl, {
|
|
@@ -1123,7 +1216,10 @@ async function handleSendLogs(options) {
|
|
|
1123
1216
|
// Only start WebSocket connection if we have stdin (piped input)
|
|
1124
1217
|
// Don't connect WebSocket when run without parameters
|
|
1125
1218
|
if (hasStdin) {
|
|
1126
|
-
connectWebSocket()
|
|
1219
|
+
connectWebSocket().catch(err => {
|
|
1220
|
+
console.error(chalk.red(`\n ✗ Failed to connect WebSocket: ${err.message}`));
|
|
1221
|
+
// Don't exit - HTTP POST will still work
|
|
1222
|
+
});
|
|
1127
1223
|
}
|
|
1128
1224
|
|
|
1129
1225
|
// Rate limiting queue for piped input
|
|
@@ -1289,7 +1385,7 @@ async function handleSendLogs(options) {
|
|
|
1289
1385
|
: `${webUrl}/${sessionId}`;
|
|
1290
1386
|
|
|
1291
1387
|
console.log(chalk.cyan(' ╔═══════════════════════════════════════╗'));
|
|
1292
|
-
console.log(chalk.cyan(' ║ ✓ Upload Complete
|
|
1388
|
+
console.log(chalk.cyan(' ║ ✓ Upload Complete ║'));
|
|
1293
1389
|
console.log(chalk.cyan(' ╚═══════════════════════════════════════╝'));
|
|
1294
1390
|
console.log('');
|
|
1295
1391
|
console.log(chalk.white(` 📊 Stats:`));
|