hedgequantx 2.9.18 → 2.9.20

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 (39) hide show
  1. package/package.json +1 -1
  2. package/src/app.js +42 -64
  3. package/src/lib/m/hqx-2b.js +7 -0
  4. package/src/lib/m/index.js +138 -0
  5. package/src/lib/m/ultra-scalping.js +7 -0
  6. package/src/menus/connect.js +14 -17
  7. package/src/menus/dashboard.js +58 -76
  8. package/src/pages/accounts.js +38 -49
  9. package/src/pages/algo/copy-trading.js +546 -178
  10. package/src/pages/algo/index.js +18 -75
  11. package/src/pages/algo/one-account.js +322 -57
  12. package/src/pages/algo/ui.js +15 -15
  13. package/src/pages/orders.js +19 -22
  14. package/src/pages/positions.js +19 -22
  15. package/src/pages/stats/index.js +15 -16
  16. package/src/pages/user.js +7 -11
  17. package/src/services/ai-supervision/health.js +35 -47
  18. package/src/services/index.js +1 -9
  19. package/src/services/rithmic/accounts.js +8 -6
  20. package/src/ui/box.js +9 -5
  21. package/src/ui/index.js +5 -18
  22. package/src/ui/menu.js +4 -4
  23. package/src/pages/ai-agents-ui.js +0 -388
  24. package/src/pages/ai-agents.js +0 -494
  25. package/src/pages/ai-models.js +0 -389
  26. package/src/pages/algo/algo-executor.js +0 -307
  27. package/src/pages/algo/copy-executor.js +0 -331
  28. package/src/pages/algo/custom-strategy.js +0 -313
  29. package/src/services/ai-supervision/consensus.js +0 -284
  30. package/src/services/ai-supervision/context.js +0 -275
  31. package/src/services/ai-supervision/directive.js +0 -167
  32. package/src/services/ai-supervision/index.js +0 -309
  33. package/src/services/ai-supervision/parser.js +0 -278
  34. package/src/services/ai-supervision/symbols.js +0 -259
  35. package/src/services/cliproxy/index.js +0 -256
  36. package/src/services/cliproxy/installer.js +0 -111
  37. package/src/services/cliproxy/manager.js +0 -387
  38. package/src/services/llmproxy/index.js +0 -166
  39. package/src/services/llmproxy/manager.js +0 -411
@@ -1,388 +0,0 @@
1
- /**
2
- * AI Agents UI Components
3
- *
4
- * UI drawing functions for the AI Agents configuration page.
5
- */
6
-
7
- const chalk = require('chalk');
8
- const ora = require('ora');
9
- const { centerText, visibleLength } = require('../ui');
10
- const cliproxy = require('../services/cliproxy');
11
- const { runPreflightCheck, formatPreflightResults, getPreflightSummary } = require('../services/ai-supervision');
12
-
13
- /**
14
- * Draw a 2-column row with perfect alignment
15
- * @param {string} leftText - Left column text
16
- * @param {string} rightText - Right column text
17
- * @param {number} W - Inner width
18
- * @param {number} padding - Left padding for each column (default 3)
19
- */
20
- const draw2ColRow = (leftText, rightText, W, padding = 3) => {
21
- const colWidth = Math.floor(W / 2);
22
- const leftLen = visibleLength(leftText);
23
- const rightLen = visibleLength(rightText || '');
24
-
25
- // Left column: padding + text + fill to colWidth
26
- const leftFill = colWidth - padding - leftLen;
27
- const leftCol = ' '.repeat(padding) + leftText + ' '.repeat(Math.max(0, leftFill));
28
-
29
- // Right column: padding + text + fill to remaining width
30
- const rightColWidth = W - colWidth;
31
- const rightFill = rightColWidth - padding - rightLen;
32
- const rightCol = ' '.repeat(padding) + (rightText || '') + ' '.repeat(Math.max(0, rightFill));
33
-
34
- console.log(chalk.cyan('║') + leftCol + rightCol + chalk.cyan('║'));
35
- };
36
-
37
- /**
38
- * Draw 2-column table with title and back option
39
- * @param {string} title - Table title
40
- * @param {Function} titleColor - Chalk color function
41
- * @param {Array} items - Items to display
42
- * @param {string} backText - Back button text
43
- * @param {number} W - Inner width
44
- */
45
- const draw2ColTable = (title, titleColor, items, backText, W) => {
46
- // New rectangle (banner is always closed)
47
- console.log(chalk.cyan('╔' + '═'.repeat(W) + '╗'));
48
- console.log(chalk.cyan('║') + titleColor(centerText(title, W)) + chalk.cyan('║'));
49
- console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
50
-
51
- const rows = Math.ceil(items.length / 2);
52
- for (let row = 0; row < rows; row++) {
53
- const left = items[row];
54
- const right = items[row + rows];
55
- draw2ColRow(left || '', right || '', W);
56
- }
57
-
58
- console.log(chalk.cyan('╠' + '─'.repeat(W) + '╣'));
59
- console.log(chalk.cyan('║') + chalk.red(centerText(backText, W)) + chalk.cyan('║'));
60
- console.log(chalk.cyan('╚' + '═'.repeat(W) + '╝'));
61
- };
62
-
63
- /**
64
- * Draw centered 2-column row
65
- * @param {string} leftText - Left column text
66
- * @param {string} rightText - Right column text
67
- * @param {number} W - Inner width
68
- */
69
- const draw2ColRowCentered = (leftText, rightText, W) => {
70
- const colWidth = Math.floor(W / 2);
71
- const leftLen = visibleLength(leftText);
72
- const rightLen = visibleLength(rightText || '');
73
-
74
- // Center left text in left column
75
- const leftPadTotal = colWidth - leftLen;
76
- const leftPadL = Math.floor(leftPadTotal / 2);
77
- const leftPadR = leftPadTotal - leftPadL;
78
- const leftCol = ' '.repeat(Math.max(0, leftPadL)) + leftText + ' '.repeat(Math.max(0, leftPadR));
79
-
80
- // Center right text in right column
81
- const rightColWidth = W - colWidth;
82
- const rightPadTotal = rightColWidth - rightLen;
83
- const rightPadL = Math.floor(rightPadTotal / 2);
84
- const rightPadR = rightPadTotal - rightPadL;
85
- const rightCol = ' '.repeat(Math.max(0, rightPadL)) + (rightText || '') + ' '.repeat(Math.max(0, rightPadR));
86
-
87
- console.log(chalk.cyan('║') + leftCol + rightCol + chalk.cyan('║'));
88
- };
89
-
90
- /**
91
- * Draw providers table with vertically aligned columns
92
- * @param {Array} providers - List of AI providers
93
- * @param {Object} config - Current config
94
- * @param {number} boxWidth - Box width
95
- * @param {boolean} showTest - Show [T] TEST option
96
- */
97
- const drawProvidersTable = (providers, config, boxWidth, showTest = false) => {
98
- const W = boxWidth - 2;
99
- const colWidth = Math.floor(W / 2);
100
-
101
- // Get connected providers (have auth files)
102
- const connected = cliproxy.getConnectedProviders();
103
-
104
- // New rectangle (banner is always closed)
105
- console.log(chalk.cyan('╔' + '═'.repeat(W) + '╗'));
106
- console.log(chalk.cyan('║') + chalk.cyan.bold(centerText('AI AGENTS CONFIGURATION', W)) + chalk.cyan('║'));
107
- console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
108
-
109
- const rows = Math.ceil(providers.length / 2);
110
-
111
- // Find max name length across ALL providers for consistent alignment
112
- const maxNameLen = Math.max(...providers.map(p => p.name.length));
113
-
114
- // Fixed format: "● [XX] NAME" where XX is 2-digit padded number
115
- // Total content width = 2 (● ) + 4 ([XX]) + 1 (space) + maxNameLen
116
- const contentWidth = 2 + 4 + 1 + maxNameLen;
117
- const leftPad = Math.floor((colWidth - contentWidth) / 2);
118
- const rightPad = Math.floor(((W - colWidth) - contentWidth) / 2);
119
-
120
- for (let row = 0; row < rows; row++) {
121
- const leftP = providers[row];
122
- const rightP = providers[row + rows];
123
-
124
- // Left column
125
- let leftCol = '';
126
- if (leftP) {
127
- const num = String(row + 1).padStart(2);
128
- // Show cyan dot if provider has auth file (connected via OAuth)
129
- const isConnected = connected[leftP.id] || config.providers[leftP.id]?.active;
130
- const status = isConnected ? chalk.cyan('● ') : ' ';
131
- const name = leftP.provider ? leftP.provider.name : leftP.name;
132
- const namePadded = name.toUpperCase().padEnd(maxNameLen);
133
- const content = status + chalk.yellow(`[${num}]`) + ' ' + chalk.cyan(namePadded);
134
- const contentLen = 2 + 4 + 1 + maxNameLen;
135
- const padR = colWidth - leftPad - contentLen;
136
- leftCol = ' '.repeat(leftPad) + content + ' '.repeat(Math.max(0, padR));
137
- } else {
138
- leftCol = ' '.repeat(colWidth);
139
- }
140
-
141
- // Right column
142
- let rightCol = '';
143
- const rightColWidth = W - colWidth;
144
- if (rightP) {
145
- const num = String(row + rows + 1).padStart(2);
146
- // Show cyan dot if provider has auth file (connected via OAuth)
147
- const isConnected = connected[rightP.id] || config.providers[rightP.id]?.active;
148
- const status = isConnected ? chalk.cyan('● ') : ' ';
149
- const name = rightP.provider ? rightP.provider.name : rightP.name;
150
- const namePadded = name.toUpperCase().padEnd(maxNameLen);
151
- const content = status + chalk.yellow(`[${num}]`) + ' ' + chalk.cyan(namePadded);
152
- const contentLen = 2 + 4 + 1 + maxNameLen;
153
- const padR2 = rightColWidth - rightPad - contentLen;
154
- rightCol = ' '.repeat(rightPad) + content + ' '.repeat(Math.max(0, padR2));
155
- } else {
156
- rightCol = ' '.repeat(rightColWidth);
157
- }
158
-
159
- console.log(chalk.cyan('║') + leftCol + rightCol + chalk.cyan('║'));
160
- }
161
-
162
- // Show [T] TEST option if agents are configured
163
- if (showTest) {
164
- console.log(chalk.cyan('╠' + '─'.repeat(W) + '╣'));
165
- console.log(chalk.cyan('║') + chalk.green(centerText('[T] TEST ALL CONNECTIONS', W)) + chalk.cyan('║'));
166
- }
167
-
168
- console.log(chalk.cyan('╠' + '─'.repeat(W) + '╣'));
169
- console.log(chalk.cyan('║') + chalk.red(centerText('[B] BACK TO MENU', W)) + chalk.cyan('║'));
170
- console.log(chalk.cyan('╚' + '═'.repeat(W) + '╝'));
171
- };
172
-
173
- /**
174
- * Draw models table with 2-column layout
175
- * @param {Object} provider - Provider object
176
- * @param {Array} models - List of models
177
- * @param {number} boxWidth - Box width
178
- */
179
- const drawModelsTable = (provider, models, boxWidth) => {
180
- const W = boxWidth - 2;
181
- const colWidth = Math.floor(W / 2);
182
-
183
- // New rectangle
184
- console.log(chalk.cyan('╔' + '═'.repeat(W) + '╗'));
185
- console.log(chalk.cyan('║') + chalk[provider.color].bold(centerText(`${provider.name.toUpperCase()} - SELECT MODEL`, W)) + chalk.cyan('║'));
186
- console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
187
-
188
- // Calculate rows (2 columns)
189
- const rows = Math.ceil(models.length / 2);
190
-
191
- // Find max model name length for alignment
192
- const maxNameLen = Math.min(
193
- Math.max(...models.map(m => m.name.length)),
194
- colWidth - 8 // [XX] + space + padding
195
- );
196
-
197
- for (let row = 0; row < rows; row++) {
198
- const leftIdx = row;
199
- const rightIdx = row + rows;
200
- const leftModel = models[leftIdx];
201
- const rightModel = models[rightIdx];
202
-
203
- // Left column
204
- let leftCol = '';
205
- if (leftModel) {
206
- const num = String(leftIdx + 1).padStart(2);
207
- const name = leftModel.name.length > maxNameLen
208
- ? leftModel.name.substring(0, maxNameLen - 2) + '..'
209
- : leftModel.name.padEnd(maxNameLen);
210
- leftCol = ` ${chalk.cyan(`[${num}]`)} ${chalk.white(name)}`;
211
- const leftLen = 2 + 4 + 1 + maxNameLen; // padding + [XX] + space + name
212
- leftCol += ' '.repeat(Math.max(0, colWidth - leftLen));
213
- } else {
214
- leftCol = ' '.repeat(colWidth);
215
- }
216
-
217
- // Right column
218
- let rightCol = '';
219
- const rightColWidth = W - colWidth;
220
- if (rightModel) {
221
- const num = String(rightIdx + 1).padStart(2);
222
- const name = rightModel.name.length > maxNameLen
223
- ? rightModel.name.substring(0, maxNameLen - 2) + '..'
224
- : rightModel.name.padEnd(maxNameLen);
225
- rightCol = ` ${chalk.cyan(`[${num}]`)} ${chalk.white(name)}`;
226
- const rightLen = 2 + 4 + 1 + maxNameLen;
227
- rightCol += ' '.repeat(Math.max(0, rightColWidth - rightLen));
228
- } else {
229
- rightCol = ' '.repeat(rightColWidth);
230
- }
231
-
232
- console.log(chalk.cyan('║') + leftCol + rightCol + chalk.cyan('║'));
233
- }
234
-
235
- console.log(chalk.cyan('╠' + '─'.repeat(W) + '╣'));
236
- console.log(chalk.cyan('║') + chalk.red(centerText('[B] BACK', W)) + chalk.cyan('║'));
237
- console.log(chalk.cyan('╚' + '═'.repeat(W) + '╝'));
238
- };
239
-
240
- /**
241
- * Draw provider configuration window
242
- * Shows connection options based on provider capabilities (OAuth and/or API Key)
243
- * @param {Object} provider - Provider object with supportsOAuth and supportsApiKey flags
244
- * @param {Object} config - Current config
245
- * @param {number} boxWidth - Box width
246
- */
247
- const drawProviderWindow = (provider, config, boxWidth) => {
248
- const W = boxWidth - 2;
249
- const col1Width = Math.floor(W / 2);
250
- const col2Width = W - col1Width;
251
- const providerConfig = config.providers[provider.id] || {};
252
-
253
- // Check provider capabilities (default to both if not specified)
254
- const supportsOAuth = provider.supportsOAuth !== false;
255
- const supportsApiKey = provider.supportsApiKey !== false;
256
-
257
- // New rectangle (banner is always closed)
258
- console.log(chalk.cyan('╔' + '═'.repeat(W) + '╗'));
259
- console.log(chalk.cyan('║') + chalk[provider.color].bold(centerText(provider.name.toUpperCase(), W)) + chalk.cyan('║'));
260
- console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
261
-
262
- // Display connection options based on provider capabilities
263
- if (supportsOAuth && supportsApiKey) {
264
- // Both options: 2 columns
265
- const opt1 = '[1] CONNECT VIA PAID PLAN';
266
- const opt2 = '[2] CONNECT VIA API KEY';
267
-
268
- const left1 = chalk.green(opt1);
269
- const right1 = chalk.yellow(opt2);
270
- const left1Len = visibleLength(left1);
271
- const right1Len = visibleLength(right1);
272
- const left1PadTotal = col1Width - left1Len;
273
- const left1PadL = Math.floor(left1PadTotal / 2);
274
- const left1PadR = left1PadTotal - left1PadL;
275
- const right1PadTotal = col2Width - right1Len;
276
- const right1PadL = Math.floor(right1PadTotal / 2);
277
- const right1PadR = right1PadTotal - right1PadL;
278
-
279
- console.log(
280
- chalk.cyan('║') +
281
- ' '.repeat(left1PadL) + left1 + ' '.repeat(left1PadR) +
282
- ' '.repeat(right1PadL) + right1 + ' '.repeat(right1PadR) +
283
- chalk.cyan('║')
284
- );
285
- } else if (supportsApiKey) {
286
- // API Key only: centered single option
287
- const opt = '[1] CONNECT VIA API KEY';
288
- console.log(chalk.cyan('║') + chalk.yellow(centerText(opt, W)) + chalk.cyan('║'));
289
- } else if (supportsOAuth) {
290
- // OAuth only: centered single option
291
- const opt = '[1] CONNECT VIA PAID PLAN';
292
- console.log(chalk.cyan('║') + chalk.green(centerText(opt, W)) + chalk.cyan('║'));
293
- }
294
-
295
- // Status bar
296
- console.log(chalk.cyan('╠' + '─'.repeat(W) + '╣'));
297
-
298
- let statusText = '';
299
- if (providerConfig.active) {
300
- const connType = providerConfig.connectionType === 'cliproxy' ? 'CLIPROXY' : 'API KEY';
301
- const modelName = (providerConfig.modelName || 'N/A').toUpperCase();
302
- statusText = chalk.green('● ACTIVE') + chalk.gray(' MODEL: ') + chalk.yellow(modelName) + chalk.gray(' VIA ') + chalk.cyan(connType);
303
- } else if (providerConfig.apiKey || providerConfig.connectionType) {
304
- statusText = chalk.yellow('● CONFIGURED') + chalk.gray(' (NOT ACTIVE)');
305
- } else {
306
- statusText = chalk.gray('○ NOT CONFIGURED');
307
- }
308
- console.log(chalk.cyan('║') + centerText(statusText, W) + chalk.cyan('║'));
309
-
310
- // Disconnect option if active
311
- if (providerConfig.active) {
312
- console.log(chalk.cyan('╠' + '─'.repeat(W) + '╣'));
313
- console.log(chalk.cyan('║') + chalk.red(centerText('[D] DISCONNECT', W)) + chalk.cyan('║'));
314
- }
315
-
316
- // Back
317
- console.log(chalk.cyan('╠' + '─'.repeat(W) + '╣'));
318
- console.log(chalk.cyan('║') + chalk.red(centerText('[B] BACK', W)) + chalk.cyan('║'));
319
- console.log(chalk.cyan('╚' + '═'.repeat(W) + '╝'));
320
- };
321
-
322
- /**
323
- * Draw and run connection test for all agents
324
- * @param {Array} agents - Array of agent configs
325
- * @param {number} boxWidth - Box width
326
- * @param {Function} clearWithBanner - Function to clear and show banner
327
- * @returns {Promise<Object>} Test results
328
- */
329
- const drawConnectionTest = async (agents, boxWidth, clearWithBanner) => {
330
- if (agents.length === 0) {
331
- console.log(chalk.yellow('\n No agents configured. Connect an agent first.'));
332
- return { success: false, error: 'No agents' };
333
- }
334
-
335
- const W = boxWidth - 2;
336
-
337
- // Show loading state with spinner
338
- clearWithBanner();
339
- console.log(chalk.cyan('╔' + '═'.repeat(W) + '╗'));
340
- console.log(chalk.cyan('║') + chalk.yellow.bold(centerText('AI AGENTS CONNECTION TEST', W)) + chalk.cyan('║'));
341
- console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
342
- console.log(chalk.cyan('║') + ' '.repeat(W) + chalk.cyan('║'));
343
-
344
- // Start spinner on the loading line
345
- const spinnerText = 'Testing connections... Please wait';
346
- const spinner = ora({
347
- text: spinnerText,
348
- spinner: 'dots',
349
- color: 'yellow'
350
- }).start();
351
-
352
- // Run pre-flight check
353
- const results = await runPreflightCheck(agents);
354
-
355
- // Stop spinner
356
- spinner.stop();
357
-
358
- // Clear and redraw with results
359
- clearWithBanner();
360
- console.log(chalk.cyan('╔' + '═'.repeat(W) + '╗'));
361
- console.log(chalk.cyan('║') + chalk.yellow.bold(centerText('AI AGENTS CONNECTION TEST', W)) + chalk.cyan('║'));
362
- console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
363
-
364
- // Display results
365
- const lines = formatPreflightResults(results, boxWidth);
366
- for (const line of lines) {
367
- const lineLen = visibleLength(line);
368
- const padding = Math.max(0, W - lineLen);
369
- console.log(chalk.cyan('║') + line + ' '.repeat(padding) + chalk.cyan('║'));
370
- }
371
-
372
- // Summary
373
- console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
374
- const summary = getPreflightSummary(results);
375
- console.log(chalk.cyan('║') + centerText(summary.text, W) + chalk.cyan('║'));
376
- console.log(chalk.cyan('╚' + '═'.repeat(W) + '╝'));
377
-
378
- return results;
379
- };
380
-
381
- module.exports = {
382
- draw2ColRow,
383
- draw2ColTable,
384
- drawProvidersTable,
385
- drawModelsTable,
386
- drawProviderWindow,
387
- drawConnectionTest
388
- };