hedgequantx 2.6.96 → 2.6.98
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 +60 -219
package/package.json
CHANGED
package/src/menus/ai-agent.js
CHANGED
|
@@ -838,8 +838,8 @@ const setupOAuthConnection = async (provider) => {
|
|
|
838
838
|
};
|
|
839
839
|
|
|
840
840
|
/**
|
|
841
|
-
* Setup OAuth via
|
|
842
|
-
*
|
|
841
|
+
* Setup OAuth via Manual Code Entry (unified flow for local and VPS)
|
|
842
|
+
* User copies the authorization code from the URL or page
|
|
843
843
|
*/
|
|
844
844
|
const setupRemoteOAuth = async (provider, config) => {
|
|
845
845
|
const boxWidth = getLogoWidth();
|
|
@@ -851,44 +851,29 @@ const setupRemoteOAuth = async (provider, config) => {
|
|
|
851
851
|
return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
|
|
852
852
|
};
|
|
853
853
|
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
console.log(makeLine(chalk.yellow('REMOTE AUTHENTICATION (VPS/SERVER)')));
|
|
859
|
-
console.log(makeLine(''));
|
|
860
|
-
console.log(makeLine(chalk.white('CREATING SECURE SESSION...')));
|
|
861
|
-
|
|
862
|
-
drawBoxFooter(boxWidth);
|
|
863
|
-
|
|
864
|
-
const spinner = ora({ text: 'Creating OAuth session...', color: 'cyan' }).start();
|
|
865
|
-
|
|
866
|
-
let sessionData;
|
|
867
|
-
try {
|
|
868
|
-
sessionData = await proxyManager.createRemoteSession(provider.id);
|
|
869
|
-
} catch (error) {
|
|
870
|
-
spinner.fail(`Failed to create session: ${error.message}`);
|
|
871
|
-
await prompts.waitForEnter();
|
|
872
|
-
return await selectProviderOption(provider);
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
spinner.stop();
|
|
854
|
+
// Generate OAuth URL using the existing oauth module
|
|
855
|
+
const authResult = oauthAnthropic.authorize('max');
|
|
856
|
+
const url = authResult.url;
|
|
857
|
+
const verifier = authResult.verifier;
|
|
876
858
|
|
|
877
|
-
// Show
|
|
859
|
+
// Show instructions
|
|
878
860
|
console.clear();
|
|
879
861
|
displayBanner();
|
|
880
862
|
drawBoxHeaderContinue(`CONNECT ${config.name}`, boxWidth);
|
|
881
863
|
|
|
882
|
-
console.log(makeLine(chalk.yellow('
|
|
864
|
+
console.log(makeLine(chalk.yellow('CONNECT YOUR ACCOUNT')));
|
|
883
865
|
console.log(makeLine(''));
|
|
884
|
-
console.log(makeLine(chalk.white('1. OPEN THE LINK BELOW IN
|
|
885
|
-
console.log(makeLine(chalk.white(' (Phone, laptop, any device)')));
|
|
866
|
+
console.log(makeLine(chalk.white('1. OPEN THE LINK BELOW IN YOUR BROWSER')));
|
|
886
867
|
console.log(makeLine(''));
|
|
887
868
|
console.log(makeLine(chalk.white(`2. LOGIN WITH YOUR ${config.accountName.toUpperCase()} ACCOUNT`)));
|
|
888
869
|
console.log(makeLine(''));
|
|
889
|
-
console.log(makeLine(chalk.white('3. AUTHORIZE
|
|
870
|
+
console.log(makeLine(chalk.white('3. CLICK "AUTHORIZE"')));
|
|
890
871
|
console.log(makeLine(''));
|
|
891
|
-
console.log(makeLine(chalk.green('THE
|
|
872
|
+
console.log(makeLine(chalk.green('4. COPY THE CODE FROM THE URL BAR')));
|
|
873
|
+
console.log(makeLine(chalk.white(' Look for: code=XXXXXX in the URL')));
|
|
874
|
+
console.log(makeLine(chalk.white(' Copy everything after code= until &')));
|
|
875
|
+
console.log(makeLine(''));
|
|
876
|
+
console.log(makeLine(chalk.white('5. PASTE THE CODE BELOW')));
|
|
892
877
|
console.log(makeLine(''));
|
|
893
878
|
|
|
894
879
|
drawBoxFooter(boxWidth);
|
|
@@ -897,40 +882,61 @@ const setupRemoteOAuth = async (provider, config) => {
|
|
|
897
882
|
console.log();
|
|
898
883
|
console.log(chalk.yellow(' OPEN THIS URL IN YOUR BROWSER:'));
|
|
899
884
|
console.log();
|
|
900
|
-
console.log(chalk.cyan(` ${
|
|
885
|
+
console.log(chalk.cyan(` ${url}`));
|
|
901
886
|
console.log();
|
|
902
887
|
|
|
903
|
-
//
|
|
904
|
-
const
|
|
888
|
+
// Get code from user
|
|
889
|
+
const code = await prompts.textInput(chalk.cyan('PASTE AUTHORIZATION CODE:'));
|
|
905
890
|
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
891
|
+
if (!code || code.trim() === '<' || code.trim() === '') {
|
|
892
|
+
return await selectProviderOption(provider);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
// Exchange code for tokens
|
|
896
|
+
const spinner = ora({ text: 'Exchanging code for tokens...', color: 'cyan' }).start();
|
|
897
|
+
|
|
898
|
+
const result = await oauthAnthropic.exchange(code.trim(), verifier);
|
|
899
|
+
|
|
900
|
+
if (result.type === 'failed') {
|
|
901
|
+
spinner.fail(`Authentication failed: ${result.error || 'Invalid code'}`);
|
|
913
902
|
await prompts.waitForEnter();
|
|
914
903
|
return await selectProviderOption(provider);
|
|
915
904
|
}
|
|
916
905
|
|
|
917
|
-
|
|
906
|
+
spinner.succeed('Authorization successful!');
|
|
918
907
|
|
|
919
908
|
// Save credentials
|
|
920
909
|
const credentials = {
|
|
921
910
|
oauth: {
|
|
922
|
-
access:
|
|
923
|
-
refresh:
|
|
924
|
-
expires:
|
|
925
|
-
|
|
926
|
-
|
|
911
|
+
access: result.access,
|
|
912
|
+
refresh: result.refresh,
|
|
913
|
+
expires: result.expires,
|
|
914
|
+
apiKey: result.apiKey,
|
|
915
|
+
email: result.email
|
|
916
|
+
}
|
|
927
917
|
};
|
|
928
918
|
|
|
929
|
-
//
|
|
930
|
-
|
|
931
|
-
|
|
919
|
+
// Try to fetch models with the new token
|
|
920
|
+
spinner.text = 'Fetching available models...';
|
|
921
|
+
spinner.start();
|
|
932
922
|
|
|
933
|
-
|
|
923
|
+
let models = [];
|
|
924
|
+
try {
|
|
925
|
+
const { fetchAnthropicModelsOAuth } = require('../services/ai/client');
|
|
926
|
+
models = await fetchAnthropicModelsOAuth(result.access);
|
|
927
|
+
} catch (e) {
|
|
928
|
+
// Ignore - will use defaults
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// Use defaults if API doesn't return models
|
|
932
|
+
if (!models || models.length === 0) {
|
|
933
|
+
models = getDefaultModelsForProvider(provider.id);
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
spinner.succeed(`Found ${models.length} models`);
|
|
937
|
+
|
|
938
|
+
// Let user select model
|
|
939
|
+
const selectedModel = await selectModelFromList(models, config.name);
|
|
934
940
|
if (!selectedModel) {
|
|
935
941
|
return await selectProviderOption(provider);
|
|
936
942
|
}
|
|
@@ -981,177 +987,12 @@ const getDefaultModelsForProvider = (providerId) => {
|
|
|
981
987
|
};
|
|
982
988
|
|
|
983
989
|
/**
|
|
984
|
-
* Setup OAuth via
|
|
985
|
-
*
|
|
990
|
+
* Setup OAuth via Manual Code Entry (unified flow for local and VPS)
|
|
991
|
+
* User copies the authorization code from the URL or page
|
|
986
992
|
*/
|
|
987
993
|
const setupProxyOAuth = async (provider, config) => {
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
const makeLine = (content) => {
|
|
992
|
-
const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
993
|
-
const padding = W - plainLen;
|
|
994
|
-
return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
|
|
995
|
-
};
|
|
996
|
-
|
|
997
|
-
console.clear();
|
|
998
|
-
displayBanner();
|
|
999
|
-
drawBoxHeaderContinue(`CONNECT ${config.name}`, boxWidth);
|
|
1000
|
-
|
|
1001
|
-
console.log(makeLine(chalk.yellow('AUTOMATIC SETUP')));
|
|
1002
|
-
console.log(makeLine(''));
|
|
1003
|
-
console.log(makeLine(chalk.white('PREPARING CONNECTION...')));
|
|
1004
|
-
|
|
1005
|
-
drawBoxFooter(boxWidth);
|
|
1006
|
-
|
|
1007
|
-
// Ensure proxy is running (will install if needed)
|
|
1008
|
-
const spinner = ora({ text: 'Setting up AI connection...', color: 'cyan' }).start();
|
|
1009
|
-
|
|
1010
|
-
try {
|
|
1011
|
-
await proxyManager.ensureRunning((msg) => {
|
|
1012
|
-
spinner.text = msg;
|
|
1013
|
-
});
|
|
1014
|
-
} catch (error) {
|
|
1015
|
-
spinner.fail(`Setup failed: ${error.message}`);
|
|
1016
|
-
await prompts.waitForEnter();
|
|
1017
|
-
return await selectProviderOption(provider);
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
// Get OAuth URL from proxy
|
|
1021
|
-
spinner.text = 'Generating authorization link...';
|
|
1022
|
-
|
|
1023
|
-
let authData;
|
|
1024
|
-
try {
|
|
1025
|
-
authData = await proxyManager.getAuthUrl(provider.id);
|
|
1026
|
-
} catch (error) {
|
|
1027
|
-
spinner.fail(`Failed to get auth URL: ${error.message}`);
|
|
1028
|
-
await prompts.waitForEnter();
|
|
1029
|
-
return await selectProviderOption(provider);
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
spinner.stop();
|
|
1033
|
-
|
|
1034
|
-
// Show URL to user
|
|
1035
|
-
console.clear();
|
|
1036
|
-
displayBanner();
|
|
1037
|
-
drawBoxHeaderContinue(`CONNECT ${config.name}`, boxWidth);
|
|
1038
|
-
|
|
1039
|
-
console.log(makeLine(chalk.yellow('LOGIN TO YOUR ACCOUNT')));
|
|
1040
|
-
console.log(makeLine(''));
|
|
1041
|
-
console.log(makeLine(chalk.white('1. OPEN THE LINK BELOW IN YOUR BROWSER')));
|
|
1042
|
-
console.log(makeLine(chalk.white(`2. LOGIN WITH YOUR ${config.accountName.toUpperCase()} ACCOUNT`)));
|
|
1043
|
-
console.log(makeLine(chalk.white('3. AUTHORIZE THE APPLICATION')));
|
|
1044
|
-
console.log(makeLine(''));
|
|
1045
|
-
console.log(makeLine(chalk.green('THE CONNECTION WILL BE AUTOMATIC!')));
|
|
1046
|
-
console.log(makeLine(chalk.white('NO CODE TO COPY - JUST LOGIN AND AUTHORIZE')));
|
|
1047
|
-
console.log(makeLine(''));
|
|
1048
|
-
console.log(makeLine(chalk.white('PRESS ENTER AFTER YOU AUTHORIZED...')));
|
|
1049
|
-
|
|
1050
|
-
drawBoxFooter(boxWidth);
|
|
1051
|
-
|
|
1052
|
-
// Display URL outside the box for easy copy
|
|
1053
|
-
console.log();
|
|
1054
|
-
console.log(chalk.yellow(' OPEN THIS URL IN YOUR BROWSER:'));
|
|
1055
|
-
console.log();
|
|
1056
|
-
console.log(chalk.cyan(` ${authData.url}`));
|
|
1057
|
-
console.log();
|
|
1058
|
-
|
|
1059
|
-
// Try to open browser automatically
|
|
1060
|
-
const browserOpened = await openBrowser(authData.url);
|
|
1061
|
-
if (browserOpened) {
|
|
1062
|
-
console.log(chalk.green(' Browser opened automatically!'));
|
|
1063
|
-
console.log();
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
// Wait for user to press enter
|
|
1067
|
-
await prompts.waitForEnter();
|
|
1068
|
-
|
|
1069
|
-
// Check if auth was successful
|
|
1070
|
-
const authSpinner = ora({ text: 'Checking authorization...', color: 'cyan' }).start();
|
|
1071
|
-
|
|
1072
|
-
try {
|
|
1073
|
-
// Poll for auth status (with timeout)
|
|
1074
|
-
const startTime = Date.now();
|
|
1075
|
-
const timeout = 60000; // 1 minute
|
|
1076
|
-
|
|
1077
|
-
while (Date.now() - startTime < timeout) {
|
|
1078
|
-
const status = await proxyManager.pollAuthStatus(authData.state);
|
|
1079
|
-
|
|
1080
|
-
if (status.status === 'ok') {
|
|
1081
|
-
authSpinner.succeed('Authorization successful!');
|
|
1082
|
-
break;
|
|
1083
|
-
} else if (status.status === 'error') {
|
|
1084
|
-
authSpinner.fail(`Authorization failed: ${status.error}`);
|
|
1085
|
-
await prompts.waitForEnter();
|
|
1086
|
-
return await selectProviderOption(provider);
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
// Still waiting
|
|
1090
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
1091
|
-
}
|
|
1092
|
-
} catch (error) {
|
|
1093
|
-
// If polling fails, try to get models anyway (user might have authorized)
|
|
1094
|
-
authSpinner.text = 'Verifying connection...';
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
// Fetch available models from proxy
|
|
1098
|
-
authSpinner.text = 'Fetching available models...';
|
|
1099
|
-
|
|
1100
|
-
let models = [];
|
|
1101
|
-
try {
|
|
1102
|
-
models = await proxyManager.getModels();
|
|
1103
|
-
} catch (e) {
|
|
1104
|
-
// Try again
|
|
1105
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
1106
|
-
models = await proxyManager.getModels();
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
|
-
if (!models || models.length === 0) {
|
|
1110
|
-
authSpinner.fail('No models available - authorization may have failed');
|
|
1111
|
-
console.log(chalk.red('\n Please try again and make sure to complete the login.'));
|
|
1112
|
-
await prompts.waitForEnter();
|
|
1113
|
-
return await selectProviderOption(provider);
|
|
1114
|
-
}
|
|
1115
|
-
|
|
1116
|
-
// Filter models for this provider
|
|
1117
|
-
const providerModels = models.filter(m => {
|
|
1118
|
-
const modelLower = m.toLowerCase();
|
|
1119
|
-
if (provider.id === 'anthropic') return modelLower.includes('claude');
|
|
1120
|
-
if (provider.id === 'openai') return modelLower.includes('gpt') || modelLower.includes('o1') || modelLower.includes('o3');
|
|
1121
|
-
if (provider.id === 'gemini') return modelLower.includes('gemini');
|
|
1122
|
-
if (provider.id === 'qwen') return modelLower.includes('qwen');
|
|
1123
|
-
if (provider.id === 'iflow') return true; // iFlow has various models
|
|
1124
|
-
return true;
|
|
1125
|
-
});
|
|
1126
|
-
|
|
1127
|
-
const finalModels = providerModels.length > 0 ? providerModels : models;
|
|
1128
|
-
|
|
1129
|
-
authSpinner.succeed(`Found ${finalModels.length} models`);
|
|
1130
|
-
|
|
1131
|
-
// Let user select model
|
|
1132
|
-
const selectedModel = await selectModelFromList(finalModels, config.name);
|
|
1133
|
-
if (!selectedModel) {
|
|
1134
|
-
return await selectProviderOption(provider);
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
// Save agent configuration (using proxy)
|
|
1138
|
-
const credentials = {
|
|
1139
|
-
useProxy: true,
|
|
1140
|
-
proxyPort: proxyManager.PROXY_PORT
|
|
1141
|
-
};
|
|
1142
|
-
|
|
1143
|
-
try {
|
|
1144
|
-
await aiService.addAgent(provider.id, config.optionId, credentials, selectedModel, config.agentName);
|
|
1145
|
-
|
|
1146
|
-
console.log(chalk.green(`\n CONNECTED TO ${config.name}`));
|
|
1147
|
-
console.log(chalk.white(` MODEL: ${selectedModel}`));
|
|
1148
|
-
console.log(chalk.white(' UNLIMITED USAGE WITH YOUR SUBSCRIPTION'));
|
|
1149
|
-
} catch (error) {
|
|
1150
|
-
console.log(chalk.red(`\n FAILED TO SAVE: ${error.message}`));
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
|
-
await prompts.waitForEnter();
|
|
1154
|
-
return await aiAgentMenu();
|
|
994
|
+
// Use the same flow as VPS - it works everywhere
|
|
995
|
+
return await setupRemoteOAuth(provider, config);
|
|
1155
996
|
};
|
|
1156
997
|
|
|
1157
998
|
/**
|