hedgequantx 2.7.41 → 2.7.43

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.7.41",
3
+ "version": "2.7.43",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
package/src/app.js CHANGED
@@ -109,7 +109,7 @@ const refreshStats = async () => {
109
109
 
110
110
  // ==================== BANNER ====================
111
111
 
112
- const banner = async (withLoading = false) => {
112
+ const banner = async () => {
113
113
  console.clear();
114
114
 
115
115
  const termWidth = process.stdout.columns || 100;
@@ -135,14 +135,6 @@ const banner = async (withLoading = false) => {
135
135
  const tagline = isMobile ? `HQX V${version}` : `PROP FUTURES ALGO TRADING V${version}`;
136
136
  console.log(chalk.cyan('║') + chalk.white(centerText(tagline, innerWidth)) + chalk.cyan('║'));
137
137
 
138
- // Show loading message if requested
139
- if (withLoading) {
140
- const loadingText = ' LOADING DASHBOARD...';
141
- const loadingPad = innerWidth - loadingText.length;
142
- console.log(chalk.cyan('╠' + '═'.repeat(innerWidth) + '╣'));
143
- console.log(chalk.cyan('║') + chalk.yellow(loadingText) + ' '.repeat(loadingPad) + chalk.cyan('║'));
144
- }
145
-
146
138
  // ALWAYS close the banner
147
139
  console.log(chalk.cyan('╚' + '═'.repeat(innerWidth) + '╝'));
148
140
  };
@@ -171,15 +163,22 @@ const run = async () => {
171
163
  try {
172
164
  log.info('Starting HQX CLI');
173
165
 
174
- // First launch - show banner with loading (closed box)
175
- await banner(true);
166
+ // First launch - show banner then spinner
167
+ await banner();
168
+
169
+ const spinner = ora({ text: 'LOADING DASHBOARD...', color: 'yellow' }).start();
176
170
 
177
171
  const restored = await connections.restoreFromStorage();
178
172
 
179
173
  if (restored) {
180
174
  currentService = connections.getAll()[0].service;
181
175
  await refreshStats();
176
+ spinner.succeed('SESSION RESTORED');
177
+ } else {
178
+ spinner.stop();
182
179
  }
180
+
181
+ await new Promise(r => setTimeout(r, 500));
183
182
 
184
183
  // Main loop
185
184
  while (true) {
@@ -57,27 +57,45 @@ const draw2ColTable = (title, titleColor, items, backText, W) => {
57
57
  console.log(chalk.cyan('╚' + '═'.repeat(W) + '╝'));
58
58
  };
59
59
 
60
+ /**
61
+ * Draw centered 2-column row
62
+ * @param {string} leftText - Left column text
63
+ * @param {string} rightText - Right column text
64
+ * @param {number} W - Inner width
65
+ */
66
+ const draw2ColRowCentered = (leftText, rightText, W) => {
67
+ const colWidth = Math.floor(W / 2);
68
+ const leftLen = visibleLength(leftText);
69
+ const rightLen = visibleLength(rightText || '');
70
+
71
+ // Center left text in left column
72
+ const leftPadTotal = colWidth - leftLen;
73
+ const leftPadL = Math.floor(leftPadTotal / 2);
74
+ const leftPadR = leftPadTotal - leftPadL;
75
+ const leftCol = ' '.repeat(Math.max(0, leftPadL)) + leftText + ' '.repeat(Math.max(0, leftPadR));
76
+
77
+ // Center right text in right column
78
+ const rightColWidth = W - colWidth;
79
+ const rightPadTotal = rightColWidth - rightLen;
80
+ const rightPadL = Math.floor(rightPadTotal / 2);
81
+ const rightPadR = rightPadTotal - rightPadL;
82
+ const rightCol = ' '.repeat(Math.max(0, rightPadL)) + (rightText || '') + ' '.repeat(Math.max(0, rightPadR));
83
+
84
+ console.log(chalk.cyan('║') + leftCol + rightCol + chalk.cyan('║'));
85
+ };
86
+
60
87
  /**
61
88
  * Draw providers table
62
89
  * @param {Array} providers - List of AI providers
63
90
  * @param {Object} config - Current config
64
91
  * @param {number} boxWidth - Box width
65
- * @param {string} cliproxyUrl - Current CLIProxy URL (optional)
66
92
  */
67
- const drawProvidersTable = (providers, config, boxWidth, cliproxyUrl = null) => {
93
+ const drawProvidersTable = (providers, config, boxWidth) => {
68
94
  const W = boxWidth - 2;
69
95
 
70
96
  // New rectangle (banner is always closed)
71
97
  console.log(chalk.cyan('╔' + '═'.repeat(W) + '╗'));
72
98
  console.log(chalk.cyan('║') + chalk.yellow.bold(centerText('AI AGENTS CONFIGURATION', W)) + chalk.cyan('║'));
73
-
74
- // Show CLIProxy URL if provided
75
- if (cliproxyUrl) {
76
- console.log(chalk.cyan('╠' + '─'.repeat(W) + '╣'));
77
- const proxyText = chalk.gray('CLIProxy: ') + chalk.cyan(cliproxyUrl);
78
- console.log(chalk.cyan('║') + centerText(proxyText, W) + chalk.cyan('║'));
79
- }
80
-
81
99
  console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
82
100
 
83
101
  const items = providers.map((p, i) => {
@@ -89,11 +107,9 @@ const drawProvidersTable = (providers, config, boxWidth, cliproxyUrl = null) =>
89
107
  for (let row = 0; row < rows; row++) {
90
108
  const left = items[row];
91
109
  const right = items[row + rows];
92
- draw2ColRow(left || '', right || '', W);
110
+ draw2ColRowCentered(left || '', right || '', W);
93
111
  }
94
112
 
95
- console.log(chalk.cyan('╠' + '─'.repeat(W) + '╣'));
96
- console.log(chalk.cyan('║') + chalk.gray(centerText('[S] CLIPROXY STATUS', W)) + chalk.cyan('║'));
97
113
  console.log(chalk.cyan('╠' + '─'.repeat(W) + '╣'));
98
114
  console.log(chalk.cyan('║') + chalk.red(centerText('[B] BACK TO MENU', W)) + chalk.cyan('║'));
99
115
  console.log(chalk.cyan('╚' + '═'.repeat(W) + '╝'));
@@ -392,26 +392,6 @@ const getActiveProvider = () => {
392
392
  /** Count active AI agents */
393
393
  const getActiveAgentCount = () => getActiveProvider() ? 1 : 0;
394
394
 
395
- /** Show CLIProxy status */
396
- const showCliProxyStatus = async () => {
397
- clearWithBanner();
398
- console.log(chalk.yellow('\n CLIPROXYAPI STATUS\n'));
399
-
400
- const installed = cliproxy.isInstalled();
401
- console.log(chalk.gray(' INSTALLED: ') + (installed ? chalk.green('YES') : chalk.red('NO')));
402
-
403
- if (installed) {
404
- const status = await cliproxy.isRunning();
405
- console.log(chalk.gray(' RUNNING: ') + (status.running ? chalk.green('YES') : chalk.red('NO')));
406
- console.log(chalk.gray(' VERSION: ') + chalk.cyan(cliproxy.CLIPROXY_VERSION));
407
- console.log(chalk.gray(' PORT: ') + chalk.cyan(cliproxy.DEFAULT_PORT));
408
- console.log(chalk.gray(' INSTALL DIR: ') + chalk.cyan(cliproxy.INSTALL_DIR));
409
- }
410
-
411
- console.log();
412
- await prompts.waitForEnter();
413
- };
414
-
415
395
  /** Main AI Agents menu */
416
396
  const aiAgentsMenu = async () => {
417
397
  let config = loadConfig();
@@ -419,20 +399,13 @@ const aiAgentsMenu = async () => {
419
399
 
420
400
  while (true) {
421
401
  clearWithBanner();
422
- const status = await cliproxy.isRunning();
423
- const statusText = status.running ? `LOCALHOST:${cliproxy.DEFAULT_PORT}` : 'NOT RUNNING';
424
- drawProvidersTable(AI_PROVIDERS, config, boxWidth, statusText);
402
+ drawProvidersTable(AI_PROVIDERS, config, boxWidth);
425
403
 
426
- const input = await prompts.textInput(chalk.cyan('SELECT (1-8/S/B): '));
404
+ const input = await prompts.textInput(chalk.cyan('SELECT (1-8/B): '));
427
405
  const choice = (input || '').toLowerCase().trim();
428
406
 
429
407
  if (choice === 'b' || choice === '') break;
430
408
 
431
- if (choice === 's') {
432
- await showCliProxyStatus();
433
- continue;
434
- }
435
-
436
409
  const num = parseInt(choice);
437
410
  if (!isNaN(num) && num >= 1 && num <= AI_PROVIDERS.length) {
438
411
  config = await handleProviderConfig(AI_PROVIDERS[num - 1], config);