hedgequantx 2.6.73 → 2.6.75

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgequantx",
3
- "version": "2.6.73",
3
+ "version": "2.6.75",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -286,7 +286,8 @@ const selectActiveAgent = async () => {
286
286
 
287
287
  const choice = await prompts.textInput(chalk.cyan('SELECT AGENT:'));
288
288
 
289
- if (choice === '<' || choice?.toLowerCase() === 'b') {
289
+ // Empty input or < = go back
290
+ if (!choice || choice.trim() === '' || choice === '<' || choice?.toLowerCase() === 'b') {
290
291
  return await aiAgentMenu();
291
292
  }
292
293
 
@@ -340,7 +341,8 @@ const selectAgentForModelChange = async () => {
340
341
 
341
342
  const choice = await prompts.textInput(chalk.cyan('SELECT AGENT:'));
342
343
 
343
- if (choice === '<' || choice?.toLowerCase() === 'b') {
344
+ // Empty input or < = go back
345
+ if (!choice || choice.trim() === '' || choice === '<' || choice?.toLowerCase() === 'b') {
344
346
  return await aiAgentMenu();
345
347
  }
346
348
 
@@ -393,7 +395,8 @@ const selectAgentToRemove = async () => {
393
395
 
394
396
  const choice = await prompts.textInput(chalk.cyan('SELECT AGENT TO REMOVE:'));
395
397
 
396
- if (choice === '<' || choice?.toLowerCase() === 'b') {
398
+ // Empty input or < = go back
399
+ if (!choice || choice.trim() === '' || choice === '<' || choice?.toLowerCase() === 'b') {
397
400
  return await aiAgentMenu();
398
401
  }
399
402
 
@@ -898,7 +901,7 @@ const setupBrowserOAuth = async (provider, config) => {
898
901
  return await selectProviderOption(provider);
899
902
  }
900
903
 
901
- spinner.succeed('AUTHENTICATION SUCCESSFUL');
904
+ spinner.text = 'FETCHING AVAILABLE MODELS...';
902
905
 
903
906
  // Store OAuth credentials
904
907
  const credentials = {
@@ -916,15 +919,35 @@ const setupBrowserOAuth = async (provider, config) => {
916
919
  credentials.apiKey = result.apiKey;
917
920
  }
918
921
 
919
- // Use default model for OAuth providers (they typically have limited model access)
922
+ // Fetch available models for the provider
923
+ let models = [];
924
+ try {
925
+ const { fetchModelsWithOAuth } = require('../services/ai/client');
926
+ models = await fetchModelsWithOAuth(provider.id, result.access);
927
+ } catch (e) {
928
+ // Fallback to default models if fetch fails
929
+ }
930
+
931
+ // Fallback default models if API doesn't return list
920
932
  const defaultModels = {
921
- anthropic: 'claude-sonnet-4-20250514',
922
- openai: 'gpt-4o',
923
- gemini: 'gemini-2.5-pro',
924
- iflow: 'deepseek-v3'
933
+ anthropic: ['claude-sonnet-4-20250514', 'claude-opus-4-20250514', 'claude-3-5-sonnet-20241022', 'claude-3-5-haiku-20241022'],
934
+ openai: ['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'o1', 'o1-mini', 'o3-mini'],
935
+ gemini: ['gemini-2.5-pro', 'gemini-2.5-flash', 'gemini-2.0-flash', 'gemini-1.5-pro'],
936
+ iflow: ['deepseek-v3', 'deepseek-chat', 'kimi', 'glm-4']
925
937
  };
926
938
 
927
- const selectedModel = defaultModels[provider.id] || 'default';
939
+ if (!models || models.length === 0) {
940
+ models = defaultModels[provider.id] || ['default'];
941
+ spinner.warn('USING DEFAULT MODEL LIST');
942
+ } else {
943
+ spinner.succeed(`FOUND ${models.length} MODELS`);
944
+ }
945
+
946
+ // Let user select model
947
+ const selectedModel = await selectModelFromList(models, config.name);
948
+ if (!selectedModel) {
949
+ return await selectProviderOption(provider);
950
+ }
928
951
 
929
952
  // Add agent with OAuth credentials
930
953
  try {
@@ -1037,7 +1060,7 @@ const setupDeviceFlowOAuth = async (provider, config) => {
1037
1060
  return await selectProviderOption(provider);
1038
1061
  }
1039
1062
 
1040
- pollSpinner.succeed('AUTHENTICATION SUCCESSFUL');
1063
+ pollSpinner.text = 'FETCHING AVAILABLE MODELS...';
1041
1064
 
1042
1065
  // Store OAuth credentials
1043
1066
  const credentials = {
@@ -1049,7 +1072,16 @@ const setupDeviceFlowOAuth = async (provider, config) => {
1049
1072
  }
1050
1073
  };
1051
1074
 
1052
- const selectedModel = 'qwen3-coder-plus';
1075
+ // Default models for Qwen
1076
+ const defaultModels = ['qwen3-coder-plus', 'qwen3-235b', 'qwen-max', 'qwen-plus', 'qwen-turbo'];
1077
+
1078
+ pollSpinner.succeed('AUTHENTICATION SUCCESSFUL');
1079
+
1080
+ // Let user select model
1081
+ const selectedModel = await selectModelFromList(defaultModels, config.name);
1082
+ if (!selectedModel) {
1083
+ return await selectProviderOption(provider);
1084
+ }
1053
1085
 
1054
1086
  // Add agent with OAuth credentials
1055
1087
  try {
@@ -1292,7 +1324,8 @@ const selectModelFromList = async (models, providerName) => {
1292
1324
 
1293
1325
  const choice = await prompts.textInput(chalk.cyan('SELECT MODEL:'));
1294
1326
 
1295
- if (choice === '<' || choice?.toLowerCase() === 'b') {
1327
+ // Empty input or < = go back
1328
+ if (!choice || choice.trim() === '' || choice === '<' || choice?.toLowerCase() === 'b') {
1296
1329
  return null;
1297
1330
  }
1298
1331
 
@@ -1417,7 +1450,8 @@ const selectModel = async (agent) => {
1417
1450
 
1418
1451
  const choice = await prompts.textInput(chalk.cyan('SELECT MODEL:'));
1419
1452
 
1420
- if (choice === '<' || choice?.toLowerCase() === 'b') {
1453
+ // Empty input or < = go back
1454
+ if (!choice || choice.trim() === '' || choice === '<' || choice?.toLowerCase() === 'b') {
1421
1455
  return await aiAgentMenu();
1422
1456
  }
1423
1457
 
@@ -565,6 +565,47 @@ const fetchOpenAIModels = async (endpoint, apiKey) => {
565
565
  }
566
566
  };
567
567
 
568
+ /**
569
+ * Fetch available models for OAuth-authenticated providers
570
+ * @param {string} providerId - Provider ID (anthropic, openai, gemini, etc.)
571
+ * @param {string} accessToken - OAuth access token
572
+ * @returns {Promise<Array|null>} Array of model IDs or null on error
573
+ */
574
+ const fetchModelsWithOAuth = async (providerId, accessToken) => {
575
+ if (!accessToken) return null;
576
+
577
+ try {
578
+ switch (providerId) {
579
+ case 'anthropic':
580
+ return await fetchAnthropicModelsOAuth(accessToken);
581
+
582
+ case 'openai':
583
+ // OpenAI OAuth uses the same endpoint as API key
584
+ return await fetchOpenAIModels('https://api.openai.com/v1', accessToken);
585
+
586
+ case 'gemini':
587
+ // Gemini OAuth - try to fetch from API
588
+ const geminiUrl = 'https://generativelanguage.googleapis.com/v1/models';
589
+ const geminiHeaders = {
590
+ 'Authorization': `Bearer ${accessToken}`
591
+ };
592
+ const geminiResponse = await makeRequest(geminiUrl, { method: 'GET', headers: geminiHeaders, timeout: 10000 });
593
+ if (geminiResponse.models && Array.isArray(geminiResponse.models)) {
594
+ return geminiResponse.models
595
+ .filter(m => m.supportedGenerationMethods?.includes('generateContent'))
596
+ .map(m => m.name.replace('models/', ''))
597
+ .filter(Boolean);
598
+ }
599
+ return null;
600
+
601
+ default:
602
+ return null;
603
+ }
604
+ } catch (error) {
605
+ return null;
606
+ }
607
+ };
608
+
568
609
  module.exports = {
569
610
  callAI,
570
611
  analyzeTrading,
@@ -577,5 +618,6 @@ module.exports = {
577
618
  fetchAnthropicModelsOAuth,
578
619
  fetchGeminiModels,
579
620
  fetchOpenAIModels,
621
+ fetchModelsWithOAuth,
580
622
  getValidOAuthToken
581
623
  };