hedgequantx 2.6.163 → 2.7.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.
Files changed (146) hide show
  1. package/README.md +15 -88
  2. package/bin/cli.js +0 -11
  3. package/dist/lib/api.jsc +0 -0
  4. package/dist/lib/api2.jsc +0 -0
  5. package/dist/lib/core.jsc +0 -0
  6. package/dist/lib/core2.jsc +0 -0
  7. package/dist/lib/data.js +1 -1
  8. package/dist/lib/data.jsc +0 -0
  9. package/dist/lib/data2.jsc +0 -0
  10. package/dist/lib/decoder.jsc +0 -0
  11. package/dist/lib/m/mod1.jsc +0 -0
  12. package/dist/lib/m/mod2.jsc +0 -0
  13. package/dist/lib/n/r1.jsc +0 -0
  14. package/dist/lib/n/r2.jsc +0 -0
  15. package/dist/lib/n/r3.jsc +0 -0
  16. package/dist/lib/n/r4.jsc +0 -0
  17. package/dist/lib/n/r5.jsc +0 -0
  18. package/dist/lib/n/r6.jsc +0 -0
  19. package/dist/lib/n/r7.jsc +0 -0
  20. package/dist/lib/o/util1.jsc +0 -0
  21. package/dist/lib/o/util2.jsc +0 -0
  22. package/package.json +6 -3
  23. package/src/app.js +40 -162
  24. package/src/config/constants.js +31 -33
  25. package/src/config/propfirms.js +13 -217
  26. package/src/config/settings.js +0 -43
  27. package/src/lib/api.js +198 -0
  28. package/src/lib/api2.js +353 -0
  29. package/src/lib/core.js +539 -0
  30. package/src/lib/core2.js +341 -0
  31. package/src/lib/data.js +555 -0
  32. package/src/lib/data2.js +492 -0
  33. package/src/lib/decoder.js +599 -0
  34. package/src/lib/m/s1.js +804 -0
  35. package/src/lib/m/s2.js +34 -0
  36. package/src/lib/n/r1.js +454 -0
  37. package/src/lib/n/r2.js +514 -0
  38. package/src/lib/n/r3.js +631 -0
  39. package/src/lib/n/r4.js +401 -0
  40. package/src/lib/n/r5.js +335 -0
  41. package/src/lib/n/r6.js +425 -0
  42. package/src/lib/n/r7.js +530 -0
  43. package/src/lib/o/l1.js +44 -0
  44. package/src/lib/o/l2.js +427 -0
  45. package/src/lib/python-bridge.js +206 -0
  46. package/src/menus/connect.js +14 -176
  47. package/src/menus/dashboard.js +65 -110
  48. package/src/pages/accounts.js +18 -18
  49. package/src/pages/algo/copy-trading.js +210 -240
  50. package/src/pages/algo/index.js +41 -104
  51. package/src/pages/algo/one-account.js +386 -33
  52. package/src/pages/algo/ui.js +312 -151
  53. package/src/pages/orders.js +3 -3
  54. package/src/pages/positions.js +3 -3
  55. package/src/pages/stats/chart.js +74 -0
  56. package/src/pages/stats/display.js +228 -0
  57. package/src/pages/stats/index.js +236 -0
  58. package/src/pages/stats/metrics.js +213 -0
  59. package/src/pages/user.js +6 -6
  60. package/src/services/hqx-server/constants.js +55 -0
  61. package/src/services/hqx-server/index.js +401 -0
  62. package/src/services/hqx-server/latency.js +81 -0
  63. package/src/services/index.js +12 -3
  64. package/src/services/rithmic/accounts.js +7 -32
  65. package/src/services/rithmic/connection.js +1 -204
  66. package/src/services/rithmic/contracts.js +116 -99
  67. package/src/services/rithmic/handlers.js +21 -196
  68. package/src/services/rithmic/index.js +63 -120
  69. package/src/services/rithmic/market.js +31 -0
  70. package/src/services/rithmic/orders.js +5 -111
  71. package/src/services/rithmic/protobuf.js +384 -138
  72. package/src/services/session.js +22 -173
  73. package/src/ui/box.js +10 -18
  74. package/src/ui/index.js +1 -3
  75. package/src/ui/menu.js +1 -1
  76. package/src/utils/prompts.js +2 -2
  77. package/dist/lib/m/s1.js +0 -1
  78. package/src/menus/ai-agent-connect.js +0 -181
  79. package/src/menus/ai-agent-models.js +0 -219
  80. package/src/menus/ai-agent-oauth.js +0 -292
  81. package/src/menus/ai-agent-ui.js +0 -141
  82. package/src/menus/ai-agent.js +0 -484
  83. package/src/pages/algo/algo-config.js +0 -195
  84. package/src/pages/algo/algo-multi.js +0 -801
  85. package/src/pages/algo/algo-utils.js +0 -58
  86. package/src/pages/algo/copy-engine.js +0 -449
  87. package/src/pages/algo/custom-strategy.js +0 -459
  88. package/src/pages/algo/logger.js +0 -245
  89. package/src/pages/algo/smart-logs-data.js +0 -218
  90. package/src/pages/algo/smart-logs.js +0 -387
  91. package/src/pages/algo/ui-constants.js +0 -144
  92. package/src/pages/algo/ui-summary.js +0 -184
  93. package/src/pages/stats-calculations.js +0 -191
  94. package/src/pages/stats-ui.js +0 -381
  95. package/src/pages/stats.js +0 -339
  96. package/src/services/ai/client-analysis.js +0 -194
  97. package/src/services/ai/client-models.js +0 -333
  98. package/src/services/ai/client.js +0 -343
  99. package/src/services/ai/index.js +0 -384
  100. package/src/services/ai/oauth-anthropic.js +0 -265
  101. package/src/services/ai/oauth-gemini.js +0 -223
  102. package/src/services/ai/oauth-iflow.js +0 -269
  103. package/src/services/ai/oauth-openai.js +0 -233
  104. package/src/services/ai/oauth-qwen.js +0 -279
  105. package/src/services/ai/providers/direct-providers.js +0 -323
  106. package/src/services/ai/providers/index.js +0 -62
  107. package/src/services/ai/providers/other-providers.js +0 -104
  108. package/src/services/ai/proxy-install.js +0 -249
  109. package/src/services/ai/proxy-manager.js +0 -494
  110. package/src/services/ai/proxy-remote.js +0 -161
  111. package/src/services/ai/strategy-supervisor.js +0 -1312
  112. package/src/services/ai/supervisor-data.js +0 -195
  113. package/src/services/ai/supervisor-optimize.js +0 -215
  114. package/src/services/ai/supervisor-sync.js +0 -178
  115. package/src/services/ai/supervisor-utils.js +0 -158
  116. package/src/services/ai/supervisor.js +0 -484
  117. package/src/services/ai/validation.js +0 -250
  118. package/src/services/hqx-server-events.js +0 -110
  119. package/src/services/hqx-server-handlers.js +0 -217
  120. package/src/services/hqx-server-latency.js +0 -136
  121. package/src/services/hqx-server.js +0 -403
  122. package/src/services/position-constants.js +0 -28
  123. package/src/services/position-exit-logic.js +0 -174
  124. package/src/services/position-manager.js +0 -438
  125. package/src/services/position-momentum.js +0 -206
  126. package/src/services/projectx/accounts.js +0 -142
  127. package/src/services/projectx/index.js +0 -443
  128. package/src/services/projectx/market.js +0 -172
  129. package/src/services/projectx/stats.js +0 -110
  130. package/src/services/projectx/trading.js +0 -180
  131. package/src/services/rithmic/latency-tracker.js +0 -182
  132. package/src/services/rithmic/market-data-decoders.js +0 -229
  133. package/src/services/rithmic/market-data.js +0 -272
  134. package/src/services/rithmic/orders-fast.js +0 -246
  135. package/src/services/rithmic/proto-decoders.js +0 -403
  136. package/src/services/rithmic/specs.js +0 -146
  137. package/src/services/rithmic/trade-history.js +0 -254
  138. package/src/services/session-history.js +0 -475
  139. package/src/services/strategy/hft-signal-calc.js +0 -147
  140. package/src/services/strategy/hft-tick.js +0 -407
  141. package/src/services/strategy/recovery-math.js +0 -402
  142. package/src/services/tradovate/constants.js +0 -109
  143. package/src/services/tradovate/index.js +0 -392
  144. package/src/services/tradovate/market.js +0 -47
  145. package/src/services/tradovate/orders.js +0 -145
  146. package/src/services/tradovate/websocket.js +0 -97
@@ -1,333 +0,0 @@
1
- /**
2
- * @fileoverview AI Client - Model Fetching Functions
3
- *
4
- * Functions to fetch available models from various AI providers
5
- * Data comes from provider APIs - NO hardcoded fallbacks
6
- */
7
-
8
- const https = require('https');
9
- const http = require('http');
10
-
11
- /**
12
- * Make HTTP request
13
- * @param {string} url - Full URL
14
- * @param {Object} options - Request options
15
- * @returns {Promise<Object>} Response data
16
- */
17
- const makeRequest = (url, options) => {
18
- return new Promise((resolve, reject) => {
19
- const parsedUrl = new URL(url);
20
- const protocol = parsedUrl.protocol === 'https:' ? https : http;
21
-
22
- const req = protocol.request(url, {
23
- method: options.method || 'POST',
24
- headers: options.headers || {},
25
- timeout: options.timeout || 30000
26
- }, (res) => {
27
- let data = '';
28
- res.on('data', chunk => data += chunk);
29
- res.on('end', () => {
30
- try {
31
- const json = JSON.parse(data);
32
- if (res.statusCode >= 200 && res.statusCode < 300) {
33
- resolve(json);
34
- } else {
35
- reject(new Error(json.error?.message || `HTTP ${res.statusCode}`));
36
- }
37
- } catch (e) {
38
- reject(new Error(`Invalid JSON response: ${data.substring(0, 100)}`));
39
- }
40
- });
41
- });
42
-
43
- req.on('error', reject);
44
- req.on('timeout', () => reject(new Error('Request timeout')));
45
-
46
- if (options.body) {
47
- req.write(JSON.stringify(options.body));
48
- }
49
- req.end();
50
- });
51
- };
52
-
53
- /**
54
- * Fetch available models from Anthropic API (API Key auth)
55
- * @param {string} apiKey - API key
56
- * @returns {Promise<Array|null>} Array of model IDs or null on error
57
- */
58
- const fetchAnthropicModels = async (apiKey) => {
59
- if (!apiKey) return null;
60
-
61
- const url = 'https://api.anthropic.com/v1/models';
62
-
63
- const headers = {
64
- 'x-api-key': apiKey,
65
- 'anthropic-version': '2023-06-01'
66
- };
67
-
68
- try {
69
- const response = await makeRequest(url, { method: 'GET', headers, timeout: 10000 });
70
- if (response.data && Array.isArray(response.data)) {
71
- return response.data.map(m => m.id).filter(Boolean);
72
- }
73
- return null;
74
- } catch (error) {
75
- return null;
76
- }
77
- };
78
-
79
- /**
80
- * Fetch available models from Anthropic API (OAuth auth)
81
- * @param {string} accessToken - OAuth access token
82
- * @returns {Promise<Object>} { models: Array, error: string|null }
83
- */
84
- const fetchAnthropicModelsOAuth = async (accessToken) => {
85
- if (!accessToken) return { models: null, error: 'No access token provided' };
86
-
87
- const modelsUrl = 'https://api.anthropic.com/v1/models';
88
-
89
- const headers = {
90
- 'Authorization': `Bearer ${accessToken}`,
91
- 'anthropic-version': '2023-06-01',
92
- 'anthropic-beta': 'oauth-2025-04-20'
93
- };
94
-
95
- try {
96
- const response = await makeRequest(modelsUrl, { method: 'GET', headers, timeout: 15000 });
97
- if (response.data && Array.isArray(response.data)) {
98
- const models = response.data.map(m => m.id).filter(Boolean);
99
- if (models.length > 0) return { models, error: null };
100
- }
101
- return { models: null, error: 'API returned empty or invalid response' };
102
- } catch (error) {
103
- return { models: null, error: error.message };
104
- }
105
- };
106
-
107
- /**
108
- * Fetch available models from Google Gemini API
109
- * @param {string} apiKey - API key
110
- * @returns {Promise<Array|null>} Array of model IDs or null on error
111
- */
112
- const fetchGeminiModels = async (apiKey) => {
113
- if (!apiKey) return null;
114
-
115
- const url = `https://generativelanguage.googleapis.com/v1/models?key=${apiKey}`;
116
-
117
- try {
118
- const response = await makeRequest(url, { method: 'GET', timeout: 10000 });
119
- if (response.models && Array.isArray(response.models)) {
120
- return response.models
121
- .filter(m => m.supportedGenerationMethods?.includes('generateContent'))
122
- .map(m => m.name.replace('models/', ''))
123
- .filter(Boolean);
124
- }
125
- return null;
126
- } catch (error) {
127
- return null;
128
- }
129
- };
130
-
131
- /**
132
- * Fetch available models from OpenAI-compatible API
133
- * @param {string} endpoint - API endpoint base URL
134
- * @param {string} apiKey - API key or OAuth token
135
- * @returns {Promise<Array|null>} Array of model IDs from API, null if unavailable
136
- */
137
- const fetchOpenAIModels = async (endpoint, apiKey) => {
138
- if (!endpoint) return null;
139
-
140
- const url = `${endpoint}/models`;
141
-
142
- const headers = {
143
- 'Content-Type': 'application/json'
144
- };
145
-
146
- if (apiKey) {
147
- headers['Authorization'] = `Bearer ${apiKey}`;
148
- }
149
-
150
- try {
151
- const response = await makeRequest(url, { method: 'GET', headers, timeout: 10000 });
152
- if (response.data && Array.isArray(response.data)) {
153
- const chatModels = response.data
154
- .map(m => m.id)
155
- .filter(id => id && (
156
- id.includes('gpt') ||
157
- id.includes('o1') ||
158
- id.includes('o3') ||
159
- id.includes('claude') ||
160
- id.includes('gemini')
161
- ))
162
- .filter(id =>
163
- !id.includes('embedding') &&
164
- !id.includes('whisper') &&
165
- !id.includes('tts') &&
166
- !id.includes('dall-e')
167
- );
168
-
169
- return chatModels.length > 0 ? chatModels : null;
170
- }
171
- return null;
172
- } catch (error) {
173
- return null;
174
- }
175
- };
176
-
177
- /**
178
- * Fetch available models for OAuth-authenticated providers
179
- * @param {string} providerId - Provider ID
180
- * @param {string} accessToken - OAuth access token
181
- * @returns {Promise<Array|null>} Array of model IDs from API, null if unavailable
182
- */
183
- const fetchModelsWithOAuth = async (providerId, accessToken) => {
184
- if (!accessToken) return null;
185
-
186
- try {
187
- switch (providerId) {
188
- case 'anthropic':
189
- return await fetchAnthropicModelsOAuth(accessToken);
190
-
191
- case 'openai': {
192
- const openaiModels = await fetchOpenAIModels('https://api.openai.com/v1', accessToken);
193
- if (openaiModels && openaiModels.length > 0) {
194
- return openaiModels;
195
- }
196
-
197
- // Try ChatGPT backend API (for Plus/Pro plans)
198
- try {
199
- const chatgptUrl = 'https://chatgpt.com/backend-api/models';
200
- const chatgptHeaders = {
201
- 'Authorization': `Bearer ${accessToken}`,
202
- 'Content-Type': 'application/json'
203
- };
204
- const chatgptResponse = await makeRequest(chatgptUrl, {
205
- method: 'GET',
206
- headers: chatgptHeaders,
207
- timeout: 10000
208
- });
209
- if (chatgptResponse.models && Array.isArray(chatgptResponse.models)) {
210
- return chatgptResponse.models
211
- .map(m => m.slug || m.id || m.name)
212
- .filter(Boolean);
213
- }
214
- } catch (e) {
215
- if (process.env.HQX_DEBUG) {
216
- console.error('[DEBUG] ChatGPT backend error:', e.message);
217
- }
218
- }
219
-
220
- return null;
221
- }
222
-
223
- case 'gemini': {
224
- try {
225
- const geminiUrl = 'https://generativelanguage.googleapis.com/v1/models';
226
- const geminiHeaders = {
227
- 'Authorization': `Bearer ${accessToken}`
228
- };
229
- const geminiResponse = await makeRequest(geminiUrl, {
230
- method: 'GET',
231
- headers: geminiHeaders,
232
- timeout: 15000
233
- });
234
- if (geminiResponse.models && Array.isArray(geminiResponse.models)) {
235
- const models = geminiResponse.models
236
- .filter(m => m.supportedGenerationMethods?.includes('generateContent'))
237
- .map(m => m.name.replace('models/', ''))
238
- .filter(Boolean);
239
- if (models.length > 0) return models;
240
- }
241
- } catch (e) {
242
- if (process.env.HQX_DEBUG) {
243
- console.error('[DEBUG] Gemini models API error:', e.message);
244
- }
245
- }
246
-
247
- return null;
248
- }
249
-
250
- case 'qwen': {
251
- try {
252
- const qwenUrl = 'https://dashscope.aliyuncs.com/api/v1/models';
253
- const qwenHeaders = {
254
- 'Authorization': `Bearer ${accessToken}`,
255
- 'Content-Type': 'application/json'
256
- };
257
- const qwenResponse = await makeRequest(qwenUrl, {
258
- method: 'GET',
259
- headers: qwenHeaders,
260
- timeout: 10000
261
- });
262
- if (qwenResponse.data && Array.isArray(qwenResponse.data)) {
263
- return qwenResponse.data
264
- .map(m => m.id || m.model_id)
265
- .filter(Boolean);
266
- }
267
- } catch (e) {
268
- // Qwen API may not support model listing
269
- }
270
- return null;
271
- }
272
-
273
- case 'iflow': {
274
- try {
275
- const iflowUrl = 'https://apis.iflow.cn/v1/models';
276
- const iflowHeaders = {
277
- 'Authorization': `Bearer ${accessToken}`,
278
- 'Content-Type': 'application/json'
279
- };
280
- const iflowResponse = await makeRequest(iflowUrl, {
281
- method: 'GET',
282
- headers: iflowHeaders,
283
- timeout: 10000
284
- });
285
- if (iflowResponse.data && Array.isArray(iflowResponse.data)) {
286
- return iflowResponse.data
287
- .map(m => m.id)
288
- .filter(Boolean);
289
- }
290
- } catch (e) {
291
- // iFlow API may not support model listing
292
- }
293
- return null;
294
- }
295
-
296
- default:
297
- return null;
298
- }
299
- } catch (error) {
300
- return null;
301
- }
302
- };
303
-
304
- /**
305
- * Fetch models via local CLIProxyAPI proxy
306
- * @returns {Promise<Array|null>} Array of model IDs or null
307
- */
308
- const fetchModelsViaProxy = async (proxyPort = 8317) => {
309
- const url = `http://127.0.0.1:${proxyPort}/v1/models`;
310
-
311
- const headers = {
312
- 'Authorization': 'Bearer hqx-local-key'
313
- };
314
-
315
- try {
316
- const response = await makeRequest(url, { method: 'GET', headers, timeout: 10000 });
317
- if (response.data && Array.isArray(response.data)) {
318
- return response.data.map(m => m.id || m).filter(Boolean);
319
- }
320
- return null;
321
- } catch (error) {
322
- return null;
323
- }
324
- };
325
-
326
- module.exports = {
327
- fetchAnthropicModels,
328
- fetchAnthropicModelsOAuth,
329
- fetchGeminiModels,
330
- fetchOpenAIModels,
331
- fetchModelsWithOAuth,
332
- fetchModelsViaProxy,
333
- };
@@ -1,343 +0,0 @@
1
- /**
2
- * AI Client - Makes real API calls to AI providers
3
- *
4
- * STRICT RULE: No mock responses. Real API calls only.
5
- * If API fails → return null, not fake data.
6
- *
7
- * Supports two modes:
8
- * 1. Direct API calls (with API keys)
9
- * 2. Proxy mode (via CLIProxyAPI for subscription accounts)
10
- */
11
-
12
- const https = require('https');
13
- const http = require('http');
14
- const { getProvider } = require('./providers');
15
- const { analyzeTrading: analyzeTradingImpl, analyzePerformance: analyzePerformanceImpl, getMarketAdvice: getMarketAdviceImpl } = require('./client-analysis');
16
- const { fetchAnthropicModels, fetchAnthropicModelsOAuth, fetchGeminiModels, fetchOpenAIModels, fetchModelsWithOAuth, fetchModelsViaProxy } = require('./client-models');
17
-
18
- /**
19
- * Make HTTP request to AI provider
20
- * @param {string} url - Full URL
21
- * @param {Object} options - Request options
22
- * @returns {Promise<Object>} Response data
23
- */
24
- const makeRequest = (url, options) => {
25
- return new Promise((resolve, reject) => {
26
- const parsedUrl = new URL(url);
27
- const protocol = parsedUrl.protocol === 'https:' ? https : http;
28
-
29
- const req = protocol.request(url, {
30
- method: options.method || 'POST',
31
- headers: options.headers || {},
32
- timeout: options.timeout || 30000
33
- }, (res) => {
34
- let data = '';
35
- res.on('data', chunk => data += chunk);
36
- res.on('end', () => {
37
- try {
38
- const json = JSON.parse(data);
39
- if (res.statusCode >= 200 && res.statusCode < 300) {
40
- resolve(json);
41
- } else {
42
- reject(new Error(json.error?.message || `HTTP ${res.statusCode}`));
43
- }
44
- } catch (e) {
45
- reject(new Error(`Invalid JSON response: ${data.substring(0, 100)}`));
46
- }
47
- });
48
- });
49
-
50
- req.on('error', reject);
51
- req.on('timeout', () => reject(new Error('Request timeout')));
52
-
53
- if (options.body) {
54
- req.write(JSON.stringify(options.body));
55
- }
56
- req.end();
57
- });
58
- };
59
-
60
- /**
61
- * Call OpenAI-compatible API
62
- * Works with: OpenAI, Groq, Together, DeepSeek, Mistral, xAI, etc.
63
- * @param {Object} agent - Agent configuration
64
- * @param {string} prompt - User prompt
65
- * @param {string} systemPrompt - System prompt
66
- * @param {Object} options - Optional settings { maxTokens, temperature, timeout }
67
- * @returns {Promise<string|null>} Response text or null on error
68
- */
69
- const callOpenAICompatible = async (agent, prompt, systemPrompt, options = {}) => {
70
- const provider = getProvider(agent.providerId);
71
- if (!provider) return null;
72
-
73
- const endpoint = agent.credentials?.endpoint || provider.endpoint;
74
- const apiKey = agent.credentials?.apiKey;
75
- const model = agent.model || provider.defaultModel;
76
-
77
- if (!apiKey && provider.category !== 'local') {
78
- return null;
79
- }
80
-
81
- const url = `${endpoint}/chat/completions`;
82
-
83
- const headers = {
84
- 'Content-Type': 'application/json'
85
- };
86
-
87
- if (apiKey) {
88
- headers['Authorization'] = `Bearer ${apiKey}`;
89
- }
90
-
91
- // OpenRouter requires additional headers
92
- if (agent.providerId === 'openrouter') {
93
- headers['HTTP-Referer'] = 'https://hedgequantx.com';
94
- headers['X-Title'] = 'HQX-CLI';
95
- }
96
-
97
- const body = {
98
- model,
99
- messages: [
100
- { role: 'system', content: systemPrompt },
101
- { role: 'user', content: prompt }
102
- ],
103
- temperature: options.temperature || 0.3
104
- };
105
-
106
- try {
107
- const timeout = options.timeout || 30000;
108
- const response = await makeRequest(url, { headers, body, timeout });
109
- return response.choices?.[0]?.message?.content || null;
110
- } catch (error) {
111
- return null;
112
- }
113
- };
114
-
115
- /**
116
- * Get valid OAuth token (refresh if needed)
117
- * @param {Object} credentials - Agent credentials with oauth data
118
- * @returns {Promise<string|null>} Valid access token or null
119
- */
120
- const getValidOAuthToken = async (credentials) => {
121
- if (!credentials?.oauth) return null;
122
-
123
- const oauthAnthropic = require('./oauth-anthropic');
124
- const validToken = await oauthAnthropic.getValidToken(credentials.oauth);
125
-
126
- if (!validToken) return null;
127
-
128
- // If token was refreshed, we should update storage (handled by caller)
129
- if (validToken.refreshed) {
130
- credentials.oauth.access = validToken.access;
131
- credentials.oauth.refresh = validToken.refresh;
132
- credentials.oauth.expires = validToken.expires;
133
- }
134
-
135
- return validToken.access;
136
- };
137
-
138
- /**
139
- * Call Anthropic Claude API
140
- * Supports both API key and OAuth authentication
141
- * @param {Object} agent - Agent configuration
142
- * @param {string} prompt - User prompt
143
- * @param {string} systemPrompt - System prompt
144
- * @param {Object} options - Optional settings { maxTokens, temperature, timeout }
145
- * @returns {Promise<string|null>} Response text or null on error
146
- */
147
- const callAnthropic = async (agent, prompt, systemPrompt, options = {}) => {
148
- const provider = getProvider('anthropic');
149
- if (!provider) return null;
150
-
151
- const model = agent.model || provider.defaultModel;
152
- const url = `${provider.endpoint}/messages`;
153
-
154
- // Determine authentication method
155
- const isOAuth = agent.credentials?.oauth?.refresh;
156
- let headers = {
157
- 'Content-Type': 'application/json',
158
- 'anthropic-version': '2023-06-01'
159
- };
160
-
161
- if (isOAuth) {
162
- // OAuth Bearer token authentication
163
- const accessToken = await getValidOAuthToken(agent.credentials);
164
- if (!accessToken) return null;
165
-
166
- headers['Authorization'] = `Bearer ${accessToken}`;
167
- headers['anthropic-beta'] = 'oauth-2025-04-20,interleaved-thinking-2025-05-14';
168
- } else {
169
- // Standard API key authentication
170
- const apiKey = agent.credentials?.apiKey;
171
- if (!apiKey) return null;
172
-
173
- headers['x-api-key'] = apiKey;
174
- }
175
-
176
- const body = {
177
- model,
178
- system: systemPrompt,
179
- messages: [
180
- { role: 'user', content: prompt }
181
- ]
182
- };
183
-
184
- try {
185
- const timeout = options.timeout || 30000;
186
- const response = await makeRequest(url, { headers, body, timeout });
187
- return response.content?.[0]?.text || null;
188
- } catch (error) {
189
- return null;
190
- }
191
- };
192
-
193
- /**
194
- * Call Google Gemini API
195
- * @param {Object} agent - Agent configuration
196
- * @param {string} prompt - User prompt
197
- * @param {string} systemPrompt - System prompt
198
- * @returns {Promise<string|null>} Response text or null on error
199
- */
200
- const callGemini = async (agent, prompt, systemPrompt, options = {}) => {
201
- const provider = getProvider('gemini');
202
- if (!provider) return null;
203
-
204
- const apiKey = agent.credentials?.apiKey;
205
- const model = agent.model || provider.defaultModel;
206
-
207
- if (!apiKey) return null;
208
-
209
- const url = `${provider.endpoint}/models/${model}:generateContent?key=${apiKey}`;
210
-
211
- const headers = {
212
- 'Content-Type': 'application/json'
213
- };
214
-
215
- const body = {
216
- contents: [
217
- { role: 'user', parts: [{ text: `${systemPrompt}\n\n${prompt}` }] }
218
- ],
219
- generationConfig: {
220
- temperature: 0.3
221
- }
222
- };
223
-
224
- try {
225
- const timeout = options.timeout || 60000;
226
- const response = await makeRequest(url, { headers, body, timeout });
227
- return response.candidates?.[0]?.content?.parts?.[0]?.text || null;
228
- } catch (error) {
229
- return null;
230
- }
231
- };
232
-
233
- /**
234
- * Call AI via local CLIProxyAPI proxy
235
- * Used for subscription accounts (ChatGPT Plus, Claude Pro, etc.)
236
- * @param {Object} agent - Agent configuration
237
- * @param {string} prompt - User prompt
238
- * @param {string} systemPrompt - System prompt
239
- * @returns {Promise<string|null>} Response text or null on error
240
- */
241
- const callViaProxy = async (agent, prompt, systemPrompt, options = {}) => {
242
- const proxyPort = agent.credentials?.proxyPort || 8317;
243
- const model = agent.model;
244
-
245
- if (!model) return null;
246
-
247
- const url = `http://127.0.0.1:${proxyPort}/v1/chat/completions`;
248
-
249
- const headers = {
250
- 'Content-Type': 'application/json',
251
- 'Authorization': 'Bearer hqx-local-key'
252
- };
253
-
254
- const body = {
255
- model,
256
- messages: [
257
- { role: 'system', content: systemPrompt },
258
- { role: 'user', content: prompt }
259
- ],
260
- temperature: 0.3
261
- };
262
-
263
- try {
264
- const timeout = options.timeout || 60000;
265
- const response = await makeRequest(url, { headers, body, timeout });
266
- return response.choices?.[0]?.message?.content || null;
267
- } catch (error) {
268
- return null;
269
- }
270
- };
271
-
272
- /**
273
- * Call AI provider based on agent configuration
274
- * @param {Object} agent - Agent with providerId and credentials
275
- * @param {string} prompt - User prompt
276
- * @param {string} systemPrompt - System prompt
277
- * @param {Object} options - Optional settings { maxTokens, temperature, timeout }
278
- * @returns {Promise<string|null>} AI response or null on error
279
- */
280
- const callAI = async (agent, prompt, systemPrompt = '', options = {}) => {
281
- if (!agent || !agent.providerId) return null;
282
-
283
- // Default timeout 60s for code generation
284
- const opts = { timeout: 60000, ...options };
285
-
286
- // Check if using proxy mode (subscription accounts)
287
- if (agent.credentials?.useProxy) {
288
- return callViaProxy(agent, prompt, systemPrompt, opts);
289
- }
290
-
291
- switch (agent.providerId) {
292
- case 'anthropic':
293
- return callAnthropic(agent, prompt, systemPrompt, opts);
294
-
295
- case 'gemini':
296
- return callGemini(agent, prompt, systemPrompt, opts);
297
-
298
- // All OpenAI-compatible APIs
299
- case 'openai':
300
- case 'openrouter':
301
- case 'deepseek':
302
- case 'groq':
303
- case 'xai':
304
- case 'mistral':
305
- case 'perplexity':
306
- case 'together':
307
- case 'qwen':
308
- case 'moonshot':
309
- case 'yi':
310
- case 'zhipu':
311
- case 'baichuan':
312
- case 'ollama':
313
- case 'lmstudio':
314
- case 'custom':
315
- return callOpenAICompatible(agent, prompt, systemPrompt, opts);
316
-
317
- default:
318
- return null;
319
- }
320
- };
321
-
322
- // Wrapper functions for analysis (pass callAI to implementation)
323
- const analyzeTrading = (agent, data) => analyzeTradingImpl(callAI, agent, data);
324
- const analyzePerformance = (agent, performanceData) => analyzePerformanceImpl(callAI, agent, performanceData);
325
- const getMarketAdvice = (agent, marketData) => getMarketAdviceImpl(callAI, agent, marketData);
326
-
327
- module.exports = {
328
- callAI,
329
- callViaProxy,
330
- analyzeTrading,
331
- analyzePerformance,
332
- getMarketAdvice,
333
- callOpenAICompatible,
334
- callAnthropic,
335
- callGemini,
336
- fetchAnthropicModels,
337
- fetchAnthropicModelsOAuth,
338
- fetchGeminiModels,
339
- fetchOpenAIModels,
340
- fetchModelsWithOAuth,
341
- fetchModelsViaProxy,
342
- getValidOAuthToken
343
- };