hedgequantx 2.4.43 → 2.5.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.
package/README.md CHANGED
@@ -208,7 +208,7 @@ Mirror trades from Lead to Follower accounts.
208
208
  <div align="center">
209
209
 
210
210
  [![Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/UBKCERctZu)
211
- [![GitHub Issues](https://img.shields.io/badge/GitHub-Issues-181717?style=for-the-badge&logo=github&logoColor=white)](https://github.com/HedgeQuantX/HQX-CLI/issues)
211
+ [![GitHub Issues](https://img.shields.io/badge/GitHub-Issues-181717?style=for-the-badge&logo=github&logoColor=white)](https://github.com/HedgeQuantX/HedgeQuantX/issues)
212
212
 
213
213
  </div>
214
214
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgequantx",
3
- "version": "2.4.43",
3
+ "version": "2.5.0",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
package/src/app.js CHANGED
@@ -27,6 +27,7 @@ const {
27
27
  dashboardMenu,
28
28
  handleUpdate,
29
29
  } = require('./menus');
30
+ const { aiAgentMenu } = require('./menus/ai-agent');
30
31
 
31
32
  /** @type {Object|null} */
32
33
  let currentService = null;
@@ -143,6 +144,38 @@ const banner = async (clear = true) => {
143
144
 
144
145
  const tagline = isMobile ? `HQX v${version}` : `PROP FUTURES ALGO TRADING v${version}`;
145
146
  console.log(chalk.cyan('║') + chalk.white(centerText(tagline, innerWidth)) + chalk.cyan('║'));
147
+
148
+ // Close box for loading state
149
+ console.log(chalk.cyan('╚' + '═'.repeat(innerWidth) + '╝'));
150
+ };
151
+
152
+ /**
153
+ * Display banner WITHOUT bottom border (for dashboard to continue)
154
+ */
155
+ const bannerOpen = async () => {
156
+ const termWidth = process.stdout.columns || 100;
157
+ const isMobile = termWidth < 60;
158
+ const boxWidth = isMobile ? Math.max(termWidth - 2, 40) : Math.max(getLogoWidth(), 98);
159
+ const innerWidth = boxWidth - 2;
160
+ const version = require('../package.json').version;
161
+
162
+ console.log(chalk.cyan('╔' + '═'.repeat(innerWidth) + '╗'));
163
+
164
+ const logoLines = isMobile ? getMobileLogo() : getFullLogo();
165
+
166
+ for (const [hq, x] of logoLines) {
167
+ const fullLine = chalk.cyan(hq) + chalk.yellow(x);
168
+ const totalLen = hq.length + x.length;
169
+ const padding = innerWidth - totalLen;
170
+ const leftPad = Math.floor(padding / 2);
171
+ console.log(chalk.cyan('║') + ' '.repeat(leftPad) + fullLine + ' '.repeat(padding - leftPad) + chalk.cyan('║'));
172
+ }
173
+
174
+ console.log(chalk.cyan('╠' + '═'.repeat(innerWidth) + '╣'));
175
+
176
+ const tagline = isMobile ? `HQX v${version}` : `PROP FUTURES ALGO TRADING v${version}`;
177
+ console.log(chalk.cyan('║') + chalk.white(centerText(tagline, innerWidth)) + chalk.cyan('║'));
178
+ // NO bottom border - dashboardMenu will continue
146
179
  };
147
180
 
148
181
  /**
@@ -172,13 +205,10 @@ const getMobileLogo = () => [
172
205
  ];
173
206
 
174
207
  /**
175
- * Display banner with closing border
208
+ * Display banner with closing border (alias for banner)
176
209
  */
177
210
  const bannerClosed = async () => {
178
211
  await banner();
179
- const termWidth = process.stdout.columns || 100;
180
- const boxWidth = termWidth < 60 ? Math.max(termWidth - 2, 40) : Math.max(getLogoWidth(), 98);
181
- console.log(chalk.cyan('╚' + '═'.repeat(boxWidth - 2) + '╝'));
182
212
  };
183
213
 
184
214
  // ==================== MENUS ====================
@@ -262,13 +292,17 @@ const run = async () => {
262
292
  await refreshStats();
263
293
  }
264
294
  } else {
265
- // Clear screen first, show banner, then spinner while loading
295
+ // Show banner with loading spinner
266
296
  console.clear();
267
297
  await banner(false);
268
298
 
269
299
  const spinner = ora({ text: 'LOADING DASHBOARD...', color: 'cyan' }).start();
270
300
  await refreshStats();
271
- spinner.succeed('READY');
301
+ spinner.stop();
302
+
303
+ // Redraw clean dashboard (banner without bottom border + menu)
304
+ console.clear();
305
+ await bannerOpen();
272
306
 
273
307
  const action = await dashboardMenu(currentService);
274
308
 
@@ -303,6 +337,10 @@ const run = async () => {
303
337
  }
304
338
  break;
305
339
 
340
+ case 'ai_agent':
341
+ await aiAgentMenu();
342
+ break;
343
+
306
344
  case 'update':
307
345
  await handleUpdate();
308
346
  break;
@@ -0,0 +1,406 @@
1
+ /**
2
+ * AI Agent Menu
3
+ * Configure AI provider connection
4
+ */
5
+
6
+ const chalk = require('chalk');
7
+ const ora = require('ora');
8
+
9
+ const { getLogoWidth, drawBoxHeader, drawBoxFooter } = require('../ui');
10
+ const { prompts } = require('../utils');
11
+ const aiService = require('../services/ai');
12
+ const { getCategories, getProvidersByCategory } = require('../services/ai/providers');
13
+
14
+ /**
15
+ * Main AI Agent menu
16
+ */
17
+ const aiAgentMenu = async () => {
18
+ const boxWidth = getLogoWidth();
19
+ const W = boxWidth - 2;
20
+
21
+ const makeLine = (content, align = 'left') => {
22
+ const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
23
+ const padding = W - plainLen;
24
+ if (align === 'center') {
25
+ const leftPad = Math.floor(padding / 2);
26
+ return chalk.cyan('║') + ' '.repeat(leftPad) + content + ' '.repeat(padding - leftPad) + chalk.cyan('║');
27
+ }
28
+ return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
29
+ };
30
+
31
+ console.clear();
32
+ drawBoxHeader('AI AGENT', boxWidth);
33
+
34
+ // Show current status
35
+ const connection = aiService.getConnection();
36
+
37
+ if (connection) {
38
+ console.log(makeLine(chalk.green('STATUS: ● CONNECTED'), 'left'));
39
+ console.log(makeLine(chalk.white(`PROVIDER: ${connection.provider.name}`), 'left'));
40
+ console.log(makeLine(chalk.white(`MODEL: ${connection.model}`), 'left'));
41
+ } else {
42
+ console.log(makeLine(chalk.gray('STATUS: ○ NOT CONNECTED'), 'left'));
43
+ }
44
+
45
+ console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
46
+
47
+ // Menu options
48
+ const options = [];
49
+
50
+ if (!connection) {
51
+ options.push({ label: chalk.green('[1] CONNECT PROVIDER'), value: 'connect' });
52
+ } else {
53
+ options.push({ label: chalk.cyan('[1] CHANGE PROVIDER'), value: 'connect' });
54
+ options.push({ label: chalk.yellow('[2] CHANGE MODEL'), value: 'model' });
55
+ options.push({ label: chalk.red('[3] DISCONNECT'), value: 'disconnect' });
56
+ }
57
+ options.push({ label: chalk.gray('[<] BACK'), value: 'back' });
58
+
59
+ for (const opt of options) {
60
+ console.log(makeLine(opt.label, 'left'));
61
+ }
62
+
63
+ drawBoxFooter(boxWidth);
64
+
65
+ const choice = await prompts.textInput(chalk.cyan('SELECT:'));
66
+
67
+ switch (choice?.toLowerCase()) {
68
+ case '1':
69
+ return await selectCategory();
70
+ case '2':
71
+ if (connection) {
72
+ return await selectModel(connection.provider);
73
+ }
74
+ return;
75
+ case '3':
76
+ if (connection) {
77
+ aiService.disconnect();
78
+ console.log(chalk.yellow('\n AI AGENT DISCONNECTED'));
79
+ await prompts.waitForEnter();
80
+ }
81
+ return;
82
+ case '<':
83
+ case 'b':
84
+ return;
85
+ default:
86
+ return;
87
+ }
88
+ };
89
+
90
+ /**
91
+ * Select provider category
92
+ */
93
+ const selectCategory = async () => {
94
+ const boxWidth = getLogoWidth();
95
+ const W = boxWidth - 2;
96
+
97
+ const makeLine = (content) => {
98
+ const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
99
+ const padding = W - plainLen;
100
+ return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
101
+ };
102
+
103
+ console.clear();
104
+ drawBoxHeader('SELECT PROVIDER TYPE', boxWidth);
105
+
106
+ const categories = getCategories();
107
+
108
+ categories.forEach((cat, index) => {
109
+ const color = cat.id === 'unified' ? chalk.green :
110
+ cat.id === 'local' ? chalk.yellow : chalk.cyan;
111
+ console.log(makeLine(color(`[${index + 1}] ${cat.name}`)));
112
+ console.log(makeLine(chalk.gray(' ' + cat.description)));
113
+ console.log(makeLine(''));
114
+ });
115
+
116
+ console.log(makeLine(chalk.gray('[<] BACK')));
117
+
118
+ drawBoxFooter(boxWidth);
119
+
120
+ const choice = await prompts.textInput(chalk.cyan('SELECT (1-4):'));
121
+
122
+ if (choice === '<' || choice?.toLowerCase() === 'b') {
123
+ return await aiAgentMenu();
124
+ }
125
+
126
+ const index = parseInt(choice) - 1;
127
+ if (isNaN(index) || index < 0 || index >= categories.length) {
128
+ return await aiAgentMenu();
129
+ }
130
+
131
+ const selectedCategory = categories[index];
132
+ return await selectProvider(selectedCategory.id);
133
+ };
134
+
135
+ /**
136
+ * Select AI provider from category
137
+ */
138
+ const selectProvider = async (categoryId) => {
139
+ const boxWidth = getLogoWidth();
140
+ const W = boxWidth - 2;
141
+
142
+ const makeLine = (content) => {
143
+ const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
144
+ const padding = W - plainLen;
145
+ return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
146
+ };
147
+
148
+ console.clear();
149
+
150
+ const categories = getCategories();
151
+ const category = categories.find(c => c.id === categoryId);
152
+ drawBoxHeader(category.name, boxWidth);
153
+
154
+ const providers = getProvidersByCategory(categoryId);
155
+
156
+ if (providers.length === 0) {
157
+ console.log(makeLine(chalk.gray('No providers in this category')));
158
+ drawBoxFooter(boxWidth);
159
+ await prompts.waitForEnter();
160
+ return await selectCategory();
161
+ }
162
+
163
+ // Display providers
164
+ providers.forEach((provider, index) => {
165
+ const isRecommended = provider.id === 'openrouter';
166
+ const color = isRecommended ? chalk.green : chalk.cyan;
167
+ console.log(makeLine(color(`[${index + 1}] ${provider.name}`)));
168
+ console.log(makeLine(chalk.gray(' ' + provider.description)));
169
+ if (provider.models && provider.models.length > 0) {
170
+ const modelList = provider.models.slice(0, 3).join(', ');
171
+ console.log(makeLine(chalk.gray(' Models: ' + modelList + (provider.models.length > 3 ? '...' : ''))));
172
+ }
173
+ console.log(makeLine(''));
174
+ });
175
+
176
+ console.log(makeLine(chalk.gray('[<] BACK')));
177
+
178
+ drawBoxFooter(boxWidth);
179
+
180
+ const choice = await prompts.textInput(chalk.cyan('SELECT PROVIDER:'));
181
+
182
+ if (choice === '<' || choice?.toLowerCase() === 'b') {
183
+ return await selectCategory();
184
+ }
185
+
186
+ const index = parseInt(choice) - 1;
187
+ if (isNaN(index) || index < 0 || index >= providers.length) {
188
+ return await selectCategory();
189
+ }
190
+
191
+ const selectedProvider = providers[index];
192
+ return await selectProviderOption(selectedProvider);
193
+ };
194
+
195
+ /**
196
+ * Select connection option for provider
197
+ */
198
+ const selectProviderOption = async (provider) => {
199
+ const boxWidth = getLogoWidth();
200
+ const W = boxWidth - 2;
201
+
202
+ const makeLine = (content) => {
203
+ const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
204
+ const padding = W - plainLen;
205
+ return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
206
+ };
207
+
208
+ // If only one option, skip selection
209
+ if (provider.options.length === 1) {
210
+ return await setupConnection(provider, provider.options[0]);
211
+ }
212
+
213
+ console.clear();
214
+ drawBoxHeader(provider.name, boxWidth);
215
+
216
+ console.log(makeLine(chalk.white('SELECT CONNECTION METHOD:')));
217
+ console.log(makeLine(''));
218
+
219
+ provider.options.forEach((option, index) => {
220
+ console.log(makeLine(chalk.cyan(`[${index + 1}] ${option.label}`)));
221
+ option.description.forEach(desc => {
222
+ console.log(makeLine(chalk.gray(' ' + desc)));
223
+ });
224
+ console.log(makeLine(''));
225
+ });
226
+
227
+ console.log(makeLine(chalk.gray('[<] BACK')));
228
+
229
+ drawBoxFooter(boxWidth);
230
+
231
+ const choice = await prompts.textInput(chalk.cyan('SELECT:'));
232
+
233
+ if (choice === '<' || choice?.toLowerCase() === 'b') {
234
+ return await selectProvider(provider.category);
235
+ }
236
+
237
+ const index = parseInt(choice) - 1;
238
+ if (isNaN(index) || index < 0 || index >= provider.options.length) {
239
+ return await selectProvider(provider.category);
240
+ }
241
+
242
+ const selectedOption = provider.options[index];
243
+ return await setupConnection(provider, selectedOption);
244
+ };
245
+
246
+ /**
247
+ * Setup connection with credentials
248
+ */
249
+ const setupConnection = async (provider, option) => {
250
+ const boxWidth = getLogoWidth();
251
+ const W = boxWidth - 2;
252
+
253
+ const makeLine = (content) => {
254
+ const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
255
+ const padding = W - plainLen;
256
+ return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
257
+ };
258
+
259
+ console.clear();
260
+ drawBoxHeader(`CONNECT TO ${provider.name}`, boxWidth);
261
+
262
+ // Show instructions
263
+ if (option.url) {
264
+ console.log(makeLine(chalk.white('GET YOUR CREDENTIALS:')));
265
+ console.log(makeLine(chalk.cyan(option.url)));
266
+ console.log(makeLine(''));
267
+ }
268
+
269
+ drawBoxFooter(boxWidth);
270
+ console.log();
271
+
272
+ // Collect credentials based on fields
273
+ const credentials = {};
274
+
275
+ for (const field of option.fields) {
276
+ let value;
277
+
278
+ switch (field) {
279
+ case 'apiKey':
280
+ value = await prompts.passwordInput('ENTER API KEY:');
281
+ if (!value) return await selectProviderOption(provider);
282
+ credentials.apiKey = value;
283
+ break;
284
+
285
+ case 'sessionKey':
286
+ value = await prompts.passwordInput('ENTER SESSION KEY:');
287
+ if (!value) return await selectProviderOption(provider);
288
+ credentials.sessionKey = value;
289
+ break;
290
+
291
+ case 'accessToken':
292
+ value = await prompts.passwordInput('ENTER ACCESS TOKEN:');
293
+ if (!value) return await selectProviderOption(provider);
294
+ credentials.accessToken = value;
295
+ break;
296
+
297
+ case 'endpoint':
298
+ const defaultEndpoint = option.defaultEndpoint || '';
299
+ value = await prompts.textInput(`ENDPOINT [${defaultEndpoint || 'required'}]:`);
300
+ credentials.endpoint = value || defaultEndpoint;
301
+ if (!credentials.endpoint) return await selectProviderOption(provider);
302
+ break;
303
+
304
+ case 'model':
305
+ value = await prompts.textInput('MODEL NAME:');
306
+ if (!value) return await selectProviderOption(provider);
307
+ credentials.model = value;
308
+ break;
309
+ }
310
+ }
311
+
312
+ // Validate connection
313
+ const spinner = ora({ text: 'VALIDATING CONNECTION...', color: 'cyan' }).start();
314
+
315
+ const validation = await aiService.validateConnection(provider.id, option.id, credentials);
316
+
317
+ if (!validation.valid) {
318
+ spinner.fail(`CONNECTION FAILED: ${validation.error}`);
319
+ await prompts.waitForEnter();
320
+ return await selectProviderOption(provider);
321
+ }
322
+
323
+ // Save connection
324
+ try {
325
+ const model = credentials.model || provider.defaultModel;
326
+ await aiService.connect(provider.id, option.id, credentials, model);
327
+ spinner.succeed(`CONNECTED TO ${provider.name}`);
328
+
329
+ // Show available models for local providers
330
+ if (validation.models && validation.models.length > 0) {
331
+ console.log(chalk.gray(` AVAILABLE MODELS: ${validation.models.slice(0, 5).join(', ')}`));
332
+ }
333
+
334
+ console.log(chalk.gray(` USING MODEL: ${model}`));
335
+ } catch (error) {
336
+ spinner.fail(`FAILED TO SAVE: ${error.message}`);
337
+ }
338
+
339
+ await prompts.waitForEnter();
340
+ return await aiAgentMenu();
341
+ };
342
+
343
+ /**
344
+ * Select/change model for current provider
345
+ */
346
+ const selectModel = async (provider) => {
347
+ const boxWidth = getLogoWidth();
348
+ const W = boxWidth - 2;
349
+
350
+ const makeLine = (content) => {
351
+ const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
352
+ const padding = W - plainLen;
353
+ return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
354
+ };
355
+
356
+ console.clear();
357
+ drawBoxHeader('SELECT MODEL', boxWidth);
358
+
359
+ const models = provider.models || [];
360
+
361
+ if (models.length === 0) {
362
+ console.log(makeLine(chalk.gray('No predefined models. Enter model name manually.')));
363
+ drawBoxFooter(boxWidth);
364
+
365
+ const model = await prompts.textInput('ENTER MODEL NAME:');
366
+ if (model) {
367
+ const settings = aiService.getAISettings();
368
+ settings.model = model;
369
+ aiService.saveAISettings(settings);
370
+ console.log(chalk.green(`\n MODEL CHANGED TO: ${model}`));
371
+ }
372
+ await prompts.waitForEnter();
373
+ return await aiAgentMenu();
374
+ }
375
+
376
+ models.forEach((model, index) => {
377
+ console.log(makeLine(chalk.cyan(`[${index + 1}] ${model}`)));
378
+ });
379
+
380
+ console.log(makeLine(''));
381
+ console.log(makeLine(chalk.gray('[<] BACK')));
382
+
383
+ drawBoxFooter(boxWidth);
384
+
385
+ const choice = await prompts.textInput(chalk.cyan('SELECT MODEL:'));
386
+
387
+ if (choice === '<' || choice?.toLowerCase() === 'b') {
388
+ return await aiAgentMenu();
389
+ }
390
+
391
+ const index = parseInt(choice) - 1;
392
+ if (isNaN(index) || index < 0 || index >= models.length) {
393
+ return await aiAgentMenu();
394
+ }
395
+
396
+ const selectedModel = models[index];
397
+ const settings = aiService.getAISettings();
398
+ settings.model = selectedModel;
399
+ aiService.saveAISettings(settings);
400
+
401
+ console.log(chalk.green(`\n MODEL CHANGED TO: ${selectedModel}`));
402
+ await prompts.waitForEnter();
403
+ return await aiAgentMenu();
404
+ };
405
+
406
+ module.exports = { aiAgentMenu };
@@ -10,6 +10,7 @@ const { connections } = require('../services');
10
10
  const { getLogoWidth, centerText, prepareStdin } = require('../ui');
11
11
  const { getCachedStats } = require('../services/stats-cache');
12
12
  const { prompts } = require('../utils');
13
+ const aiService = require('../services/ai');
13
14
 
14
15
  /**
15
16
  * Dashboard menu after login
@@ -60,9 +61,18 @@ const dashboardMenu = async (service) => {
60
61
  pnlDisplay = '--';
61
62
  }
62
63
 
64
+ // AI status
65
+ const aiConnection = aiService.getConnection();
66
+ const aiStatus = aiConnection
67
+ ? aiConnection.provider.name.split(' ')[0] // Just "CLAUDE" or "OPENAI"
68
+ : null;
69
+
63
70
  // Yellow icons: ✔ for each stat
64
71
  const icon = chalk.yellow('✔ ');
65
- const statsPlain = `✔ CONNECTIONS: ${statsInfo.connections} ACCOUNTS: ${statsInfo.accounts} ✔ BALANCE: ${balStr} ✔ P&L: ${pnlDisplay}`;
72
+ const aiIcon = aiStatus ? chalk.magenta('') : chalk.gray('○ ');
73
+ const aiText = aiStatus ? chalk.magenta(aiStatus) : chalk.gray('NONE');
74
+
75
+ const statsPlain = `✔ CONNECTIONS: ${statsInfo.connections} ✔ ACCOUNTS: ${statsInfo.accounts} ✔ BALANCE: ${balStr} AI: ${aiStatus || 'NONE'}`;
66
76
  const statsLeftPad = Math.max(0, Math.floor((W - statsPlain.length) / 2));
67
77
  const statsRightPad = Math.max(0, W - statsPlain.length - statsLeftPad);
68
78
 
@@ -70,7 +80,7 @@ const dashboardMenu = async (service) => {
70
80
  icon + chalk.white(`CONNECTIONS: ${statsInfo.connections}`) + ' ' +
71
81
  icon + chalk.white(`ACCOUNTS: ${statsInfo.accounts}`) + ' ' +
72
82
  icon + chalk.white('BALANCE: ') + balColor(balStr) + ' ' +
73
- icon + chalk.white('P&L: ') + pnlColor(pnlDisplay) +
83
+ aiIcon + chalk.white('AI: ') + aiText +
74
84
  ' '.repeat(Math.max(0, statsRightPad)) + chalk.cyan('║'));
75
85
  }
76
86
 
@@ -87,19 +97,21 @@ const dashboardMenu = async (service) => {
87
97
  };
88
98
 
89
99
  menuRow(chalk.cyan('[1] VIEW ACCOUNTS'), chalk.cyan('[2] VIEW STATS'));
90
- menuRow(chalk.cyan('[+] ADD PROP-ACCOUNT'), chalk.magenta('[A] ALGO-TRADING'));
91
- menuRow(chalk.yellow('[U] UPDATE HQX'), chalk.red('[X] DISCONNECT'));
100
+ menuRow(chalk.cyan('[+] ADD PROP-ACCOUNT'), chalk.magenta('[A] ALGO TRADING'));
101
+ menuRow(chalk.magenta('[I] AI AGENT'), chalk.yellow('[U] UPDATE HQX'));
102
+ menuRow(chalk.red('[X] DISCONNECT'), '');
92
103
 
93
104
  console.log(chalk.cyan('╚' + '═'.repeat(W) + '╝'));
94
105
 
95
106
  // Simple input - no duplicate menu
96
- const input = await prompts.textInput(chalk.cyan('SELECT (1/2/+/A/U/X)'));
107
+ const input = await prompts.textInput(chalk.cyan('SELECT (1/2/+/A/I/U/X)'));
97
108
 
98
109
  const actionMap = {
99
110
  '1': 'accounts',
100
111
  '2': 'stats',
101
112
  '+': 'add_prop_account',
102
113
  'a': 'algotrading',
114
+ 'i': 'ai_agent',
103
115
  'u': 'update',
104
116
  'x': 'disconnect'
105
117
  };