hedgequantx 2.7.71 → 2.7.73

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.71",
3
+ "version": "2.7.73",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -242,9 +242,18 @@ const handleUpdate = async () => {
242
242
 
243
243
  spinner.succeed(`UPDATED TO V${latestVersion}!`);
244
244
  console.log(chalk.green('\n ✓ UPDATE SUCCESSFUL!'));
245
- console.log(chalk.yellow('\n PLEASE RESTART HQX TO USE THE NEW VERSION:'));
246
- console.log(chalk.white(' hqx'));
247
- await prompts.waitForEnter();
245
+ console.log(chalk.cyan('\n RESTARTING HQX...'));
246
+
247
+ // Restart CLI with new version using spawn detached
248
+ const { spawn } = require('child_process');
249
+ const child = spawn('hqx', [], {
250
+ detached: true,
251
+ stdio: 'inherit',
252
+ shell: true
253
+ });
254
+ child.unref();
255
+
256
+ // Exit current process to let new one take over
248
257
  process.exit(0);
249
258
 
250
259
  } catch (error) {
@@ -155,15 +155,70 @@ const drawProvidersTable = (providers, config, boxWidth) => {
155
155
  };
156
156
 
157
157
  /**
158
- * Draw models table
158
+ * Draw models table with 2-column layout
159
159
  * @param {Object} provider - Provider object
160
160
  * @param {Array} models - List of models
161
161
  * @param {number} boxWidth - Box width
162
162
  */
163
163
  const drawModelsTable = (provider, models, boxWidth) => {
164
164
  const W = boxWidth - 2;
165
- const items = models.map((m, i) => chalk.cyan(`[${i + 1}]`) + ' ' + chalk.white(m.name.toUpperCase()));
166
- draw2ColTable(`${provider.name.toUpperCase()} - MODELS`, chalk[provider.color].bold, items, '[B] BACK', W);
165
+ const colWidth = Math.floor(W / 2);
166
+
167
+ // New rectangle
168
+ console.log(chalk.cyan('╔' + '═'.repeat(W) + '╗'));
169
+ console.log(chalk.cyan('║') + chalk[provider.color].bold(centerText(`${provider.name.toUpperCase()} - SELECT MODEL`, W)) + chalk.cyan('║'));
170
+ console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
171
+
172
+ // Calculate rows (2 columns)
173
+ const rows = Math.ceil(models.length / 2);
174
+
175
+ // Find max model name length for alignment
176
+ const maxNameLen = Math.min(
177
+ Math.max(...models.map(m => m.name.length)),
178
+ colWidth - 8 // [XX] + space + padding
179
+ );
180
+
181
+ for (let row = 0; row < rows; row++) {
182
+ const leftIdx = row;
183
+ const rightIdx = row + rows;
184
+ const leftModel = models[leftIdx];
185
+ const rightModel = models[rightIdx];
186
+
187
+ // Left column
188
+ let leftCol = '';
189
+ if (leftModel) {
190
+ const num = String(leftIdx + 1).padStart(2);
191
+ const name = leftModel.name.length > maxNameLen
192
+ ? leftModel.name.substring(0, maxNameLen - 2) + '..'
193
+ : leftModel.name.padEnd(maxNameLen);
194
+ leftCol = ` ${chalk.cyan(`[${num}]`)} ${chalk.white(name)}`;
195
+ const leftLen = 2 + 4 + 1 + maxNameLen; // padding + [XX] + space + name
196
+ leftCol += ' '.repeat(Math.max(0, colWidth - leftLen));
197
+ } else {
198
+ leftCol = ' '.repeat(colWidth);
199
+ }
200
+
201
+ // Right column
202
+ let rightCol = '';
203
+ const rightColWidth = W - colWidth;
204
+ if (rightModel) {
205
+ const num = String(rightIdx + 1).padStart(2);
206
+ const name = rightModel.name.length > maxNameLen
207
+ ? rightModel.name.substring(0, maxNameLen - 2) + '..'
208
+ : rightModel.name.padEnd(maxNameLen);
209
+ rightCol = ` ${chalk.cyan(`[${num}]`)} ${chalk.white(name)}`;
210
+ const rightLen = 2 + 4 + 1 + maxNameLen;
211
+ rightCol += ' '.repeat(Math.max(0, rightColWidth - rightLen));
212
+ } else {
213
+ rightCol = ' '.repeat(rightColWidth);
214
+ }
215
+
216
+ console.log(chalk.cyan('║') + leftCol + rightCol + chalk.cyan('║'));
217
+ }
218
+
219
+ console.log(chalk.cyan('╠' + '─'.repeat(W) + '╣'));
220
+ console.log(chalk.cyan('║') + chalk.red(centerText('[B] BACK', W)) + chalk.cyan('║'));
221
+ console.log(chalk.cyan('╚' + '═'.repeat(W) + '╝'));
167
222
  };
168
223
 
169
224
  /**
@@ -219,6 +219,24 @@ const handleCliProxyConnection = async (provider, config, boxWidth) => {
219
219
  return false;
220
220
  }
221
221
 
222
+ spinner.text = 'EXCHANGING TOKEN...';
223
+
224
+ // Wait for login process to exit naturally (it saves auth file then exits)
225
+ await new Promise((resolve) => {
226
+ if (!loginResult.childProcess) return resolve();
227
+
228
+ const timeout = setTimeout(() => {
229
+ // Safety timeout after 15s - kill if still running
230
+ try { loginResult.childProcess.kill(); } catch (e) { /* ignore */ }
231
+ resolve();
232
+ }, 15000);
233
+
234
+ loginResult.childProcess.on('exit', () => {
235
+ clearTimeout(timeout);
236
+ resolve();
237
+ });
238
+ });
239
+
222
240
  spinner.succeed('AUTHENTICATION SUCCESSFUL!');
223
241
  } catch (err) {
224
242
  spinner.fail(`ERROR: ${err.message}`);
@@ -232,13 +250,11 @@ const handleCliProxyConnection = async (provider, config, boxWidth) => {
232
250
  await prompts.waitForEnter();
233
251
  }
234
252
 
235
- // Kill login process - we don't need to wait for it
236
- if (loginResult.childProcess) {
237
- try { loginResult.childProcess.kill(); } catch (e) { /* ignore */ }
238
- }
239
-
240
- // Fetch models directly from CLIProxy API (models are already available)
253
+ // Small delay for CLIProxy to detect new auth file
241
254
  const spinner = ora({ text: 'LOADING MODELS...', color: 'yellow' }).start();
255
+ await new Promise(r => setTimeout(r, 1000));
256
+
257
+ // Fetch models from CLIProxy API
242
258
  const modelsResult = await cliproxy.fetchProviderModels(provider.id);
243
259
  spinner.stop();
244
260