hedgequantx 2.6.105 → 2.6.107
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/package.json +1 -1
- package/src/menus/ai-agent.js +52 -4
- package/src/pages/algo/ui.js +12 -12
- package/src/services/ai/proxy-manager.js +59 -0
package/package.json
CHANGED
package/src/menus/ai-agent.js
CHANGED
|
@@ -1029,17 +1029,65 @@ const setupProxyOAuth = async (provider, config) => {
|
|
|
1029
1029
|
}
|
|
1030
1030
|
console.log();
|
|
1031
1031
|
|
|
1032
|
-
// Step 4: Wait for OAuth callback
|
|
1032
|
+
// Step 4: Wait for OAuth callback (with manual fallback for VPS/remote)
|
|
1033
1033
|
const waitSpinner = ora({ text: 'Waiting for authorization...', color: 'cyan' }).start();
|
|
1034
1034
|
|
|
1035
|
+
let authSuccess = false;
|
|
1036
|
+
|
|
1037
|
+
// First try: wait 45 seconds for automatic callback
|
|
1035
1038
|
try {
|
|
1036
|
-
await proxyManager.waitForAuth(authState,
|
|
1039
|
+
await proxyManager.waitForAuth(authState, 45000, (status) => {
|
|
1037
1040
|
waitSpinner.text = status;
|
|
1038
1041
|
});
|
|
1042
|
+
authSuccess = true;
|
|
1039
1043
|
waitSpinner.succeed('Authorization successful!');
|
|
1040
1044
|
} catch (error) {
|
|
1041
|
-
|
|
1042
|
-
|
|
1045
|
+
// Timeout - offer manual callback entry
|
|
1046
|
+
if (error.message === 'Authentication timeout') {
|
|
1047
|
+
waitSpinner.stop();
|
|
1048
|
+
console.log();
|
|
1049
|
+
console.log(chalk.yellow(' ⚠ Callback not received automatically.'));
|
|
1050
|
+
console.log(chalk.gray(' If you\'re on a remote server (VPS), the callback cannot reach this machine.'));
|
|
1051
|
+
console.log();
|
|
1052
|
+
console.log(chalk.white(' After authorizing, you should see a page with URL like:'));
|
|
1053
|
+
console.log(chalk.cyan(' http://localhost:54545/callback?code=xxx&state=yyy'));
|
|
1054
|
+
console.log();
|
|
1055
|
+
console.log(chalk.white(' Paste that full URL below (or press Enter to cancel):'));
|
|
1056
|
+
console.log();
|
|
1057
|
+
|
|
1058
|
+
const callbackUrl = await prompts.input(' Callback URL: ');
|
|
1059
|
+
|
|
1060
|
+
if (callbackUrl && callbackUrl.trim()) {
|
|
1061
|
+
const submitSpinner = ora({ text: 'Submitting callback...', color: 'cyan' }).start();
|
|
1062
|
+
try {
|
|
1063
|
+
await proxyManager.submitCallback(callbackUrl.trim());
|
|
1064
|
+
submitSpinner.text = 'Verifying authorization...';
|
|
1065
|
+
|
|
1066
|
+
// Wait a bit for the proxy to process the callback
|
|
1067
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
1068
|
+
|
|
1069
|
+
// Verify auth status
|
|
1070
|
+
await proxyManager.waitForAuth(authState, 10000, () => {});
|
|
1071
|
+
authSuccess = true;
|
|
1072
|
+
submitSpinner.succeed('Authorization successful!');
|
|
1073
|
+
} catch (submitError) {
|
|
1074
|
+
submitSpinner.fail(`Failed: ${submitError.message}`);
|
|
1075
|
+
await prompts.waitForEnter();
|
|
1076
|
+
return await selectProviderOption(provider);
|
|
1077
|
+
}
|
|
1078
|
+
} else {
|
|
1079
|
+
console.log(chalk.gray(' Cancelled.'));
|
|
1080
|
+
await prompts.waitForEnter();
|
|
1081
|
+
return await selectProviderOption(provider);
|
|
1082
|
+
}
|
|
1083
|
+
} else {
|
|
1084
|
+
waitSpinner.fail(`Authorization failed: ${error.message}`);
|
|
1085
|
+
await prompts.waitForEnter();
|
|
1086
|
+
return await selectProviderOption(provider);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
if (!authSuccess) {
|
|
1043
1091
|
return await selectProviderOption(provider);
|
|
1044
1092
|
}
|
|
1045
1093
|
|
package/src/pages/algo/ui.js
CHANGED
|
@@ -48,19 +48,19 @@ const LOG_ICONS = {
|
|
|
48
48
|
win: '✔ WIN ',
|
|
49
49
|
loss: '✘ LOSS ',
|
|
50
50
|
be: '★ BE ',
|
|
51
|
-
entry: '➡ ENTRY
|
|
51
|
+
entry: '➡ ENTRY',
|
|
52
52
|
filled: '✔ FILL ',
|
|
53
53
|
connected: '✔ CONN ',
|
|
54
|
-
ready: '✔ READY
|
|
55
|
-
error: '✘
|
|
56
|
-
reject: '✘
|
|
54
|
+
ready: '✔ READY',
|
|
55
|
+
error: '✘ ERROR',
|
|
56
|
+
reject: '✘ REJCT',
|
|
57
57
|
info: '➡ INFO ',
|
|
58
|
-
system: '★
|
|
59
|
-
signal: '★
|
|
60
|
-
trade: '✔ TRADE
|
|
61
|
-
success: '✔
|
|
62
|
-
warning: '⬅
|
|
63
|
-
analysis: '★ ANLYS
|
|
58
|
+
system: '★ SYSTM',
|
|
59
|
+
signal: '★ SIGNL',
|
|
60
|
+
trade: '✔ TRADE',
|
|
61
|
+
success: '✔ SUCCS',
|
|
62
|
+
warning: '⬅ WARNG',
|
|
63
|
+
analysis: '★ ANLYS'
|
|
64
64
|
};
|
|
65
65
|
|
|
66
66
|
/**
|
|
@@ -365,12 +365,12 @@ class AlgoUI {
|
|
|
365
365
|
} else {
|
|
366
366
|
visible.forEach(log => {
|
|
367
367
|
const color = LOG_COLORS[log.type] || chalk.gray;
|
|
368
|
-
const icon = LOG_ICONS[log.type] || 'INFO
|
|
368
|
+
const icon = LOG_ICONS[log.type] || '➡ INFO ';
|
|
369
369
|
// HF style: TIME | COLORED TYPE | MESSAGE with colored numbers
|
|
370
370
|
const coloredIcon = color.bold(icon);
|
|
371
371
|
// Color numbers: positive=cyan, negative=red, symbols=yellow
|
|
372
372
|
const coloredMessage = colorizeMessage(log.message);
|
|
373
|
-
const line = ` ${chalk.gray(log.timestamp)} ${coloredIcon}${coloredMessage}`;
|
|
373
|
+
const line = ` ${chalk.gray(log.timestamp)} ${coloredIcon} ${coloredMessage}`;
|
|
374
374
|
this._line(chalk.cyan(BOX.V) + fitToWidth(line, W) + chalk.cyan(BOX.V));
|
|
375
375
|
});
|
|
376
376
|
for (let i = visible.length; i < maxLogs; i++) {
|
|
@@ -530,6 +530,64 @@ const waitForAuth = async (state, timeoutMs = 300000, onStatus = () => {}) => {
|
|
|
530
530
|
throw new Error('Authentication timeout');
|
|
531
531
|
};
|
|
532
532
|
|
|
533
|
+
/**
|
|
534
|
+
* Submit OAuth callback URL manually (for remote/VPS use)
|
|
535
|
+
* Extracts code and state from callback URL and submits to local proxy
|
|
536
|
+
* @param {string} callbackUrl - Full callback URL (http://localhost:54545/callback?code=xxx&state=yyy)
|
|
537
|
+
* @returns {Promise<boolean>}
|
|
538
|
+
*/
|
|
539
|
+
const submitCallback = async (callbackUrl) => {
|
|
540
|
+
// Parse the callback URL
|
|
541
|
+
let url;
|
|
542
|
+
try {
|
|
543
|
+
url = new URL(callbackUrl);
|
|
544
|
+
} catch (e) {
|
|
545
|
+
throw new Error('Invalid callback URL format');
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const code = url.searchParams.get('code');
|
|
549
|
+
const state = url.searchParams.get('state');
|
|
550
|
+
|
|
551
|
+
if (!code || !state) {
|
|
552
|
+
throw new Error('Missing code or state in callback URL');
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// Submit to local callback server
|
|
556
|
+
return new Promise((resolve, reject) => {
|
|
557
|
+
const callbackPath = `/callback?code=${encodeURIComponent(code)}&state=${encodeURIComponent(state)}`;
|
|
558
|
+
|
|
559
|
+
const req = http.request({
|
|
560
|
+
hostname: '127.0.0.1',
|
|
561
|
+
port: 54545,
|
|
562
|
+
path: callbackPath,
|
|
563
|
+
method: 'GET',
|
|
564
|
+
timeout: 30000
|
|
565
|
+
}, (res) => {
|
|
566
|
+
let data = '';
|
|
567
|
+
res.on('data', chunk => data += chunk);
|
|
568
|
+
res.on('end', () => {
|
|
569
|
+
// Success if we get a redirect or success page
|
|
570
|
+
if (res.statusCode === 200 || res.statusCode === 302 || res.statusCode === 301) {
|
|
571
|
+
resolve(true);
|
|
572
|
+
} else {
|
|
573
|
+
reject(new Error(`Callback failed with status ${res.statusCode}`));
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
req.on('error', (e) => {
|
|
579
|
+
reject(new Error(`Failed to submit callback: ${e.message}`));
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
req.on('timeout', () => {
|
|
583
|
+
req.destroy();
|
|
584
|
+
reject(new Error('Callback request timeout'));
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
req.end();
|
|
588
|
+
});
|
|
589
|
+
};
|
|
590
|
+
|
|
533
591
|
/**
|
|
534
592
|
* Get available models from the proxy
|
|
535
593
|
* @returns {Promise<Array<string>>}
|
|
@@ -766,6 +824,7 @@ module.exports = {
|
|
|
766
824
|
getAuthUrl,
|
|
767
825
|
pollAuthStatus,
|
|
768
826
|
waitForAuth,
|
|
827
|
+
submitCallback,
|
|
769
828
|
getModels,
|
|
770
829
|
getAuthFiles,
|
|
771
830
|
chatCompletion,
|