hedgequantx 2.5.24 → 2.5.25

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/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  ### Prop Futures Algo Trading CLI
8
8
 
9
- *Connect to 37+ prop firms and automate your futures trading*
9
+ *Connect to 38+ prop firms and automate your futures trading with AI supervision*
10
10
 
11
11
  [![Website](https://img.shields.io/badge/Website-hedgequantx.com-00D4AA?style=for-the-badge&logo=google-chrome&logoColor=white)](https://hedgequantx.com)
12
12
  [![npm version](https://img.shields.io/npm/v/hedgequantx?style=for-the-badge&logo=npm&logoColor=white&color=CB3837)](https://www.npmjs.com/package/hedgequantx)
@@ -21,10 +21,11 @@
21
21
 
22
22
  [![Futures](https://img.shields.io/badge/Futures-Trading-F7931A?style=flat-square&logo=bitcoin&logoColor=white)](https://hedgequantx.com)
23
23
  [![Algo](https://img.shields.io/badge/Algo-Trading-00D4AA?style=flat-square&logo=probot&logoColor=white)](https://hedgequantx.com)
24
- [![Prop Firms](https://img.shields.io/badge/37+-Prop%20Firms-8B5CF6?style=flat-square&logo=building&logoColor=white)](https://hedgequantx.com)
24
+ [![AI Powered](https://img.shields.io/badge/AI-Powered-8B5CF6?style=flat-square&logo=openai&logoColor=white)](https://hedgequantx.com)
25
+ [![Prop Firms](https://img.shields.io/badge/38+-Prop%20Firms-8B5CF6?style=flat-square&logo=building&logoColor=white)](https://hedgequantx.com)
25
26
  [![Secure](https://img.shields.io/badge/AES--256-Encrypted-EF4444?style=flat-square&logo=shield&logoColor=white)](https://hedgequantx.com)
26
27
 
27
- [Website](https://hedgequantx.com) | [Installation](#installation) | [Features](#features) | [Algo Trading](#algo-trading) | [Discord](https://discord.gg/UBKCERctZu)
28
+ [Website](https://hedgequantx.com) | [Installation](#installation) | [Features](#features) | [AI Integration](#ai-integration) | [Algo Trading](#algo-trading) | [Discord](https://discord.gg/UBKCERctZu)
28
29
 
29
30
  </div>
30
31
 
@@ -34,12 +35,13 @@
34
35
 
35
36
  | Feature | Description |
36
37
  |---------|-------------|
37
- | **Multi-Platform** | ProjectX & Rithmic APIs |
38
- | **37+ Prop Firms** | TopStep, Apex, Bulenox, and more |
38
+ | **Multi-Platform** | ProjectX, Rithmic & Tradovate APIs |
39
+ | **38+ Prop Firms** | TopStep, Apex, Bulenox, and more |
39
40
  | **Multi-Account** | Connect multiple accounts simultaneously |
40
41
  | **Real-Time Stats** | Balance, P&L, positions, orders |
41
42
  | **Algo Trading** | One Account & Copy Trading modes |
42
- | **Algo Trading** | Proprietary HQX Strategy |
43
+ | **AI Supervision** | Claude, GPT, Gemini, and 15+ providers |
44
+ | **Claude Pro/Max OAuth** | Login with your Claude subscription |
43
45
  | **Market Hours** | Auto-blocks when market closed |
44
46
  | **Local Execution** | Direct API trading, no server needed |
45
47
  | **Secure Storage** | AES-256-GCM encrypted sessions |
@@ -95,6 +97,55 @@ hqx --version
95
97
 
96
98
  ---
97
99
 
100
+ ## AI Integration
101
+
102
+ HedgeQuantX integrates with leading AI providers for intelligent trading supervision.
103
+
104
+ ### Supported AI Providers
105
+
106
+ | Provider | Authentication | Models |
107
+ |----------|---------------|--------|
108
+ | **Anthropic Claude** | OAuth (Pro/Max) or API Key | Claude 4, Sonnet, Haiku, Opus |
109
+ | **OpenAI** | API Key | GPT-4o, GPT-4, GPT-3.5 |
110
+ | **Google Gemini** | API Key | Gemini Pro, Gemini Flash |
111
+ | **OpenRouter** | API Key | 100+ models (unified API) |
112
+ | **DeepSeek** | API Key | DeepSeek Chat, Coder |
113
+ | **Groq** | API Key | Llama, Mixtral (fast inference) |
114
+ | **xAI** | API Key | Grok |
115
+ | **Mistral** | API Key | Mistral Large, Medium, Small |
116
+ | **Perplexity** | API Key | Sonar models |
117
+ | **Together AI** | API Key | Open source models |
118
+ | **Ollama** | Local | Any local model |
119
+ | **LM Studio** | Local | Any local model |
120
+
121
+ ### Claude Pro/Max OAuth Login
122
+
123
+ If you have a Claude Pro or Max subscription, you can login directly without an API key:
124
+
125
+ ```
126
+ 1. AI Agent Menu -> [+] Add Agent
127
+ 2. Select DIRECT PROVIDERS -> CLAUDE (ANTHROPIC)
128
+ 3. Choose "CLAUDE PRO/MAX (OAUTH)"
129
+ 4. Browser opens -> Login to claude.ai
130
+ 5. Copy the authorization code
131
+ 6. Paste in terminal -> Connected!
132
+ ```
133
+
134
+ Benefits:
135
+ - No API key needed
136
+ - Use your existing subscription
137
+ - Unlimited usage with your plan
138
+ - Tokens auto-refresh
139
+
140
+ ### AI Features
141
+
142
+ - **Trading Analysis**: Real-time position and risk analysis
143
+ - **Multi-Agent Support**: Connect multiple AI providers simultaneously
144
+ - **Auto Token Scanner**: Detects existing AI sessions from VS Code, Cursor, Claude CLI
145
+ - **Token Auto-Refresh**: OAuth tokens refresh automatically when expired
146
+
147
+ ---
148
+
98
149
  ## Algo Trading
99
150
 
100
151
  ### One Account Mode
@@ -107,12 +158,18 @@ Trade on a single account with HQX algo strategy.
107
158
 
108
159
  ### Copy Trading Mode
109
160
 
110
- Mirror trades from Lead to Follower accounts.
161
+ Mirror trades from Lead to Follower accounts with real execution.
111
162
 
112
163
  <div align="center">
113
164
  <img src="assets/copy-trading.png" alt="HQX Copy Trading" width="800">
114
165
  </div>
115
166
 
167
+ Features:
168
+ - Real order execution via API
169
+ - Position synchronization
170
+ - Multi-account support
171
+ - Configurable lot multiplier
172
+
116
173
  ---
117
174
 
118
175
  ## Supported Prop Firms
@@ -151,13 +208,27 @@ Mirror trades from Lead to Follower accounts.
151
208
  | Rate Limiting | API protection |
152
209
  | File Permissions | 0600 (owner only) |
153
210
  | Credentials | Never stored in plain text |
211
+ | OAuth Tokens | Secure PKCE flow |
154
212
 
155
213
  ---
156
214
 
157
215
  ## Changelog
158
216
 
159
217
  <details>
160
- <summary><b>v1.8.x (Current)</b></summary>
218
+ <summary><b>v2.5.x (Current)</b></summary>
219
+
220
+ - **AI Integration**: Multi-provider AI supervision
221
+ - **Claude OAuth**: Login with Pro/Max subscription (no API key needed)
222
+ - **Token Scanner**: Auto-detect AI sessions from VS Code, Cursor, Claude CLI
223
+ - **Real API Models**: Fetch models from provider APIs (no hardcoded lists)
224
+ - **Copy Trading**: Real order execution via API
225
+ - **Multi-Agent**: Connect multiple AI providers simultaneously
226
+ - **Auto Token Refresh**: OAuth tokens refresh automatically
227
+
228
+ </details>
229
+
230
+ <details>
231
+ <summary><b>v1.8.x</b></summary>
161
232
 
162
233
  - Separate UI for One Account and Copy Trading
163
234
  - Market hours validation
@@ -194,12 +265,14 @@ Mirror trades from Lead to Follower accounts.
194
265
 
195
266
  | Done | Done | Coming Soon |
196
267
  |------|------|-------------|
197
- | :white_check_mark: ProjectX integration | :white_check_mark: One Account mode | :hourglass: Tradovate integration |
198
- | :white_check_mark: Rithmic integration | :white_check_mark: Copy Trading mode | :hourglass: Telegram alerts |
199
- | :white_check_mark: 38+ prop firms | :white_check_mark: HQX Server | :hourglass: Multi-symbol trading |
200
- | :white_check_mark: Multi-account | :white_check_mark: Market hours check | :hourglass: Performance analytics |
201
- | :white_check_mark: Trailing SL & BE | :white_check_mark: Session summary | :hourglass: Trade journal export |
202
- | :white_check_mark: Encrypted sessions | :white_check_mark: Auto-update | :hourglass: Web dashboard |
268
+ | :white_check_mark: ProjectX integration | :white_check_mark: One Account mode | :hourglass: Telegram alerts |
269
+ | :white_check_mark: Rithmic integration | :white_check_mark: Copy Trading mode | :hourglass: Multi-symbol trading |
270
+ | :white_check_mark: 38+ prop firms | :white_check_mark: HQX Server | :hourglass: Performance analytics |
271
+ | :white_check_mark: Multi-account | :white_check_mark: Market hours check | :hourglass: Trade journal export |
272
+ | :white_check_mark: Trailing SL & BE | :white_check_mark: Session summary | :hourglass: Web dashboard |
273
+ | :white_check_mark: Encrypted sessions | :white_check_mark: Auto-update | :hourglass: Advanced AI strategies |
274
+ | :white_check_mark: AI Integration | :white_check_mark: Claude OAuth | :hourglass: Voice commands |
275
+ | :white_check_mark: Multi-AI Agents | :white_check_mark: Token Scanner | |
203
276
 
204
277
  ---
205
278
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgequantx",
3
- "version": "2.5.24",
3
+ "version": "2.5.25",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -10,7 +10,6 @@ const { getLogoWidth, drawBoxHeader, drawBoxHeaderContinue, drawBoxFooter, displ
10
10
  const { prompts } = require('../utils');
11
11
  const aiService = require('../services/ai');
12
12
  const { getCategories, getProvidersByCategory } = require('../services/ai/providers');
13
- const tokenScanner = require('../services/ai/token-scanner');
14
13
  const oauthAnthropic = require('../services/ai/oauth-anthropic');
15
14
 
16
15
  /**
@@ -118,7 +117,7 @@ const aiAgentMenu = async () => {
118
117
 
119
118
  switch (input) {
120
119
  case '+':
121
- return await showExistingTokens();
120
+ return await selectCategory();
122
121
  case 's':
123
122
  if (agentCount > 1) {
124
123
  return await selectActiveAgent();
@@ -367,178 +366,6 @@ const selectAgentToRemove = async () => {
367
366
  return await aiAgentMenu();
368
367
  };
369
368
 
370
- // Cache for scanned tokens (avoid multiple Keychain prompts)
371
- let cachedTokens = null;
372
- let cacheTimestamp = 0;
373
- const CACHE_TTL = 60000; // 1 minute cache
374
-
375
- /**
376
- * Show existing tokens found on the system
377
- */
378
- const showExistingTokens = async () => {
379
- const boxWidth = getLogoWidth();
380
- const W = boxWidth - 2;
381
-
382
- const makeLine = (content) => {
383
- const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
384
- const padding = W - plainLen;
385
- return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
386
- };
387
-
388
- // Check cache first
389
- const now = Date.now();
390
- let tokens;
391
-
392
- if (cachedTokens && (now - cacheTimestamp) < CACHE_TTL) {
393
- tokens = cachedTokens;
394
- } else {
395
- console.clear();
396
- displayBanner();
397
- drawBoxHeaderContinue('SCANNING FOR EXISTING SESSIONS...', boxWidth);
398
- console.log(makeLine(''));
399
- console.log(makeLine(chalk.gray('CHECKING VS CODE, CURSOR, CLAUDE CLI, OPENCODE...')));
400
- console.log(makeLine(''));
401
- drawBoxFooter(boxWidth);
402
-
403
- // Scan for tokens and cache
404
- tokens = tokenScanner.scanAllSources();
405
- cachedTokens = tokens;
406
- cacheTimestamp = now;
407
- }
408
-
409
- if (tokens.length === 0) {
410
- // No tokens found, go directly to category selection
411
- return await selectCategory();
412
- }
413
-
414
- // Show found tokens
415
- console.clear();
416
- displayBanner();
417
- drawBoxHeaderContinue('EXISTING SESSIONS FOUND', boxWidth);
418
-
419
- console.log(makeLine(chalk.green(`FOUND ${tokens.length} EXISTING SESSION(S)`)));
420
- console.log(makeLine(''));
421
-
422
- const formatted = tokenScanner.formatResults(tokens);
423
-
424
- for (const t of formatted) {
425
- const providerColor = t.provider.includes('CLAUDE') ? chalk.magenta :
426
- t.provider.includes('OPENAI') ? chalk.green :
427
- t.provider.includes('OPENROUTER') ? chalk.yellow : chalk.cyan;
428
-
429
- console.log(makeLine(
430
- chalk.white(`[${t.index}] `) +
431
- providerColor(t.provider) +
432
- chalk.gray(` (${t.type})`)
433
- ));
434
- console.log(makeLine(
435
- chalk.gray(` ${t.icon} ${t.source} - ${t.lastUsed}`)
436
- ));
437
- console.log(makeLine(
438
- chalk.gray(` TOKEN: ${t.tokenPreview}`)
439
- ));
440
- console.log(makeLine(''));
441
- }
442
-
443
- console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
444
- console.log(makeLine(chalk.cyan('[N] CONNECT NEW PROVIDER')));
445
- console.log(makeLine(chalk.gray('[<] BACK')));
446
-
447
- drawBoxFooter(boxWidth);
448
-
449
- const choice = await prompts.textInput(chalk.cyan('SELECT (1-' + tokens.length + '/N/<):'));
450
-
451
- if (choice === '<' || choice?.toLowerCase() === 'b') {
452
- return await aiAgentMenu();
453
- }
454
-
455
- if (choice?.toLowerCase() === 'n') {
456
- return await selectCategory();
457
- }
458
-
459
- const index = parseInt(choice) - 1;
460
- if (isNaN(index) || index < 0 || index >= tokens.length) {
461
- return await showExistingTokens();
462
- }
463
-
464
- // Use selected token
465
- const selectedToken = tokens[index];
466
-
467
- const spinner = ora({ text: 'VALIDATING TOKEN...', color: 'cyan' }).start();
468
-
469
- try {
470
- // Validate the token - include metadata from scanner
471
- const credentials = {
472
- apiKey: selectedToken.token,
473
- sessionKey: selectedToken.token,
474
- accessToken: selectedToken.token,
475
- fromKeychain: selectedToken.sourceId === 'secureStorage' || selectedToken.sourceId === 'keychain',
476
- subscriptionType: selectedToken.subscriptionType,
477
- refreshToken: selectedToken.refreshToken,
478
- expiresAt: selectedToken.expiresAt
479
- };
480
- const validation = await aiService.validateConnection(selectedToken.provider, selectedToken.type, credentials);
481
-
482
- if (!validation.valid) {
483
- spinner.fail(`TOKEN INVALID OR EXPIRED: ${validation.error}`);
484
- await prompts.waitForEnter();
485
- return await showExistingTokens();
486
- }
487
-
488
- // Get provider info
489
- const { getProvider } = require('../services/ai/providers');
490
- const provider = getProvider(selectedToken.provider);
491
-
492
- if (!provider) {
493
- spinner.fail('PROVIDER NOT SUPPORTED');
494
- await prompts.waitForEnter();
495
- return await showExistingTokens();
496
- }
497
-
498
- spinner.text = 'FETCHING AVAILABLE MODELS...';
499
-
500
- // Fetch models from API with the token
501
- const { fetchAnthropicModels, fetchOpenAIModels } = require('../services/ai/client');
502
-
503
- let models = null;
504
- if (selectedToken.provider === 'anthropic') {
505
- models = await fetchAnthropicModels(credentials.apiKey);
506
- } else {
507
- models = await fetchOpenAIModels(provider.endpoint, credentials.apiKey);
508
- }
509
-
510
- if (!models || models.length === 0) {
511
- spinner.fail('COULD NOT FETCH MODELS FROM API');
512
- await prompts.waitForEnter();
513
- return await showExistingTokens();
514
- }
515
-
516
- spinner.succeed(`FOUND ${models.length} MODELS`);
517
-
518
- // Let user select model
519
- const selectedModel = await selectModelFromList(models, provider.name);
520
- if (!selectedModel) {
521
- return await showExistingTokens();
522
- }
523
-
524
- // Add agent with selected model
525
- const agentName = `${provider.name} (${selectedToken.source})`;
526
- await aiService.addAgent(selectedToken.provider, 'api_key', credentials, selectedModel, agentName);
527
-
528
- console.log(chalk.green(`\n AGENT ADDED: ${provider.name}`));
529
- console.log(chalk.gray(` SOURCE: ${selectedToken.source}`));
530
- console.log(chalk.gray(` MODEL: ${selectedModel}`));
531
-
532
- await prompts.waitForEnter();
533
- return await aiAgentMenu();
534
-
535
- } catch (error) {
536
- spinner.fail(`CONNECTION FAILED: ${error.message}`);
537
- await prompts.waitForEnter();
538
- return await showExistingTokens();
539
- }
540
- };
541
-
542
369
  /**
543
370
  * Select provider category
544
371
  */
@@ -937,16 +764,18 @@ const setupOAuthConnection = async (provider) => {
937
764
  spinner.succeed(`FOUND ${models.length} MODELS`);
938
765
  }
939
766
 
767
+ if (!models || models.length === 0) {
768
+ spinner.fail('COULD NOT FETCH MODELS FROM API');
769
+ console.log(chalk.gray(' OAuth authentication may not support model listing.'));
770
+ console.log(chalk.gray(' Please use API KEY authentication instead.'));
771
+ await prompts.waitForEnter();
772
+ return await selectProviderOption(provider);
773
+ }
774
+
775
+ spinner.succeed(`FOUND ${models.length} MODELS`);
776
+
940
777
  // Let user select model
941
- const availableModels = models && models.length > 0 ? models : [
942
- 'claude-sonnet-4-20250514',
943
- 'claude-sonnet-4-5-20250514',
944
- 'claude-3-5-sonnet-20241022',
945
- 'claude-3-5-haiku-20241022',
946
- 'claude-3-opus-20240229'
947
- ];
948
-
949
- const selectedModel = await selectModelFromList(availableModels, 'CLAUDE PRO/MAX');
778
+ const selectedModel = await selectModelFromList(models, 'CLAUDE PRO/MAX');
950
779
  if (!selectedModel) {
951
780
  return await selectProviderOption(provider);
952
781
  }
@@ -1173,13 +1002,24 @@ const selectModel = async (agent) => {
1173
1002
  drawBoxFooter(boxWidth);
1174
1003
 
1175
1004
  // Fetch models from real API
1176
- const { fetchAnthropicModels, fetchOpenAIModels } = require('../services/ai/client');
1005
+ const { fetchAnthropicModels, fetchAnthropicModelsOAuth, fetchOpenAIModels } = require('../services/ai/client');
1177
1006
 
1178
1007
  let models = null;
1179
1008
  const agentCredentials = aiService.getAgentCredentials(agent.id);
1180
1009
 
1181
1010
  if (agent.providerId === 'anthropic') {
1182
- models = await fetchAnthropicModels(agentCredentials?.apiKey);
1011
+ // Check if OAuth credentials or OAuth-like token (sk-ant-oat...)
1012
+ const token = agentCredentials?.apiKey || agentCredentials?.accessToken || agentCredentials?.sessionKey;
1013
+ const isOAuthToken = agentCredentials?.oauth?.access || (token && token.startsWith('sk-ant-oat'));
1014
+
1015
+ if (isOAuthToken) {
1016
+ // Use OAuth endpoint with Bearer token
1017
+ const accessToken = agentCredentials?.oauth?.access || token;
1018
+ models = await fetchAnthropicModelsOAuth(accessToken);
1019
+ } else {
1020
+ // Standard API key
1021
+ models = await fetchAnthropicModels(token);
1022
+ }
1183
1023
  } else {
1184
1024
  // OpenAI-compatible providers
1185
1025
  const endpoint = agentCredentials?.endpoint || agent.provider?.endpoint;
@@ -357,11 +357,12 @@ const fetchAnthropicModelsOAuth = async (accessToken) => {
357
357
  try {
358
358
  const response = await makeRequest(url, { method: 'GET', headers, timeout: 10000 });
359
359
  if (response.data && Array.isArray(response.data)) {
360
- return response.data.map(m => m.id).filter(Boolean);
360
+ const models = response.data.map(m => m.id).filter(Boolean);
361
+ if (models.length > 0) return models;
361
362
  }
362
363
  return null;
363
364
  } catch (error) {
364
- // OAuth may not support /models endpoint, return null to use defaults
365
+ // OAuth token may not support /models endpoint
365
366
  return null;
366
367
  }
367
368
  };
@@ -374,58 +374,28 @@ const validateConnection = async (providerId, optionId, credentials) => {
374
374
  const validateAnthropic = async (credentials) => {
375
375
  try {
376
376
  const token = credentials.apiKey || credentials.sessionKey || credentials.accessToken;
377
+ if (!token) return { valid: false, error: 'No API key provided' };
377
378
 
378
- // Check if it's an OAuth token (sk-ant-oat...) vs API key (sk-ant-api...)
379
- const isOAuthToken = token && token.startsWith('sk-ant-oat');
380
-
381
- if (isOAuthToken) {
382
- // OAuth tokens (from Claude Max/Pro subscription) cannot be validated via public API
383
- // They use a different authentication flow through claude.ai
384
- // Trust them if they have the correct format (sk-ant-oatXX-...)
385
- if (token.length > 50 && /^sk-ant-oat\d{2}-[a-zA-Z0-9_-]+$/.test(token)) {
386
- return {
387
- valid: true,
388
- tokenType: 'oauth',
389
- subscriptionType: credentials.subscriptionType || 'max',
390
- trusted: credentials.fromKeychain || false
391
- };
392
- }
393
-
394
- return { valid: false, error: 'Invalid OAuth token format' };
395
- }
396
-
397
- // Standard API key validation (sk-ant-api...)
398
- const response = await fetch('https://api.anthropic.com/v1/messages', {
399
- method: 'POST',
379
+ // Validate by fetching models from API - this proves the token works
380
+ const response = await fetch('https://api.anthropic.com/v1/models', {
381
+ method: 'GET',
400
382
  headers: {
401
- 'Content-Type': 'application/json',
402
383
  'x-api-key': token,
403
384
  'anthropic-version': '2023-06-01'
404
- },
405
- body: JSON.stringify({
406
- model: 'claude-sonnet-4-5-20250929',
407
- max_tokens: 10,
408
- messages: [{ role: 'user', content: 'Hi' }]
409
- })
385
+ }
410
386
  });
411
387
 
412
388
  if (response.ok) {
413
- return { valid: true, tokenType: 'api_key' };
389
+ const data = await response.json();
390
+ if (data.data && Array.isArray(data.data) && data.data.length > 0) {
391
+ return { valid: true, tokenType: 'api_key' };
392
+ }
393
+ return { valid: false, error: 'API returned no models' };
414
394
  }
415
395
 
416
396
  const error = await response.json();
417
397
  return { valid: false, error: error.error?.message || 'Invalid API key' };
418
398
  } catch (e) {
419
- // Network error - if it's an OAuth token, still accept it (can't validate anyway)
420
- const token = credentials.apiKey || credentials.sessionKey || credentials.accessToken;
421
- if (token && token.startsWith('sk-ant-oat') && token.length > 50) {
422
- return {
423
- valid: true,
424
- tokenType: 'oauth',
425
- subscriptionType: credentials.subscriptionType || 'max',
426
- warning: 'Could not validate online (network error), but token format is valid'
427
- };
428
- }
429
399
  return { valid: false, error: e.message };
430
400
  }
431
401
  };
@@ -10,17 +10,8 @@ const PROVIDERS = {
10
10
  name: 'OPENROUTER (RECOMMENDED)',
11
11
  description: '1 API key for 100+ models',
12
12
  category: 'unified',
13
- models: [
14
- 'anthropic/claude-sonnet-4',
15
- 'anthropic/claude-3-opus',
16
- 'openai/gpt-4o',
17
- 'openai/gpt-4-turbo',
18
- 'google/gemini-pro-1.5',
19
- 'meta-llama/llama-3-70b',
20
- 'mistralai/mistral-large',
21
- 'deepseek/deepseek-chat'
22
- ],
23
- defaultModel: 'anthropic/claude-sonnet-4',
13
+ models: [], // Fetched from API at runtime
14
+ defaultModel: null, // Will use first model from API
24
15
  options: [
25
16
  {
26
17
  id: 'api_key',