hedgequantx 2.5.12 → 2.5.14
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 +1 -1
- package/src/app.js +9 -3
- package/src/menus/ai-agent.js +297 -50
- package/src/menus/dashboard.js +9 -13
- package/src/pages/algo/index.js +230 -35
- package/src/services/ai/index.js +304 -61
- package/src/services/ai/supervisor.js +713 -0
- package/src/services/ai/token-scanner.js +27 -4
package/package.json
CHANGED
package/src/app.js
CHANGED
|
@@ -235,13 +235,14 @@ const mainMenu = async () => {
|
|
|
235
235
|
console.log(chalk.cyan('╠' + '═'.repeat(innerWidth) + '╣'));
|
|
236
236
|
|
|
237
237
|
menuRow(chalk.cyan('[1] ProjectX'), chalk.cyan('[2] Rithmic'));
|
|
238
|
-
menuRow(chalk.cyan('[3] Tradovate'), chalk.
|
|
238
|
+
menuRow(chalk.cyan('[3] Tradovate'), chalk.magenta('[I] AI Agent'));
|
|
239
|
+
menuRow(chalk.red('[X] Exit'), '');
|
|
239
240
|
|
|
240
241
|
console.log(chalk.cyan('╚' + '═'.repeat(innerWidth) + '╝'));
|
|
241
242
|
|
|
242
|
-
const input = await prompts.textInput(chalk.cyan('Select (1/2/3/X)'));
|
|
243
|
+
const input = await prompts.textInput(chalk.cyan('Select (1/2/3/I/X)'));
|
|
243
244
|
|
|
244
|
-
const actions = { '1': 'projectx', '2': 'rithmic', '3': 'tradovate', 'x': 'exit' };
|
|
245
|
+
const actions = { '1': 'projectx', '2': 'rithmic', '3': 'tradovate', 'i': 'ai_agent', 'x': 'exit' };
|
|
245
246
|
return actions[(input || '').toLowerCase()] || 'exit';
|
|
246
247
|
};
|
|
247
248
|
|
|
@@ -282,6 +283,11 @@ const run = async () => {
|
|
|
282
283
|
process.exit(0);
|
|
283
284
|
}
|
|
284
285
|
|
|
286
|
+
if (choice === 'ai_agent') {
|
|
287
|
+
await aiAgentMenu();
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
|
|
285
291
|
let service = null;
|
|
286
292
|
if (choice === 'projectx') service = await projectXMenu();
|
|
287
293
|
else if (choice === 'rithmic') service = await rithmicMenu();
|
package/src/menus/ai-agent.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AI Agent Menu
|
|
3
|
-
* Configure AI provider
|
|
3
|
+
* Configure multiple AI provider connections
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const chalk = require('chalk');
|
|
@@ -31,62 +31,311 @@ const aiAgentMenu = async () => {
|
|
|
31
31
|
|
|
32
32
|
console.clear();
|
|
33
33
|
displayBanner();
|
|
34
|
-
drawBoxHeaderContinue('AI
|
|
34
|
+
drawBoxHeaderContinue('AI AGENTS', boxWidth);
|
|
35
35
|
|
|
36
|
-
//
|
|
37
|
-
const
|
|
36
|
+
// Get all connected agents
|
|
37
|
+
const agents = aiService.getAgents();
|
|
38
|
+
const agentCount = agents.length;
|
|
38
39
|
|
|
39
|
-
if (
|
|
40
|
-
console.log(makeLine(chalk.
|
|
41
|
-
console.log(makeLine(chalk.white(`PROVIDER: ${connection.provider.name}`), 'left'));
|
|
42
|
-
console.log(makeLine(chalk.white(`MODEL: ${connection.model}`), 'left'));
|
|
40
|
+
if (agentCount === 0) {
|
|
41
|
+
console.log(makeLine(chalk.gray('STATUS: NO AGENTS CONNECTED'), 'left'));
|
|
43
42
|
} else {
|
|
44
|
-
console.log(makeLine(chalk.
|
|
43
|
+
console.log(makeLine(chalk.green(`STATUS: ${agentCount} AGENT${agentCount > 1 ? 'S' : ''} CONNECTED`), 'left'));
|
|
44
|
+
console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
|
|
45
|
+
|
|
46
|
+
// List all agents
|
|
47
|
+
for (let i = 0; i < agents.length; i++) {
|
|
48
|
+
const agent = agents[i];
|
|
49
|
+
const activeMarker = agent.isActive ? chalk.yellow(' *') : '';
|
|
50
|
+
const providerColor = agent.providerId === 'anthropic' ? chalk.magenta :
|
|
51
|
+
agent.providerId === 'openai' ? chalk.green :
|
|
52
|
+
agent.providerId === 'openrouter' ? chalk.yellow : chalk.cyan;
|
|
53
|
+
|
|
54
|
+
console.log(makeLine(
|
|
55
|
+
chalk.white(`[${i + 1}] `) +
|
|
56
|
+
providerColor(agent.name) +
|
|
57
|
+
activeMarker +
|
|
58
|
+
chalk.gray(` - ${agent.model}`)
|
|
59
|
+
));
|
|
60
|
+
}
|
|
45
61
|
}
|
|
46
62
|
|
|
47
63
|
console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
|
|
48
64
|
|
|
49
65
|
// Menu options
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
66
|
+
console.log(makeLine(chalk.green('[+] ADD NEW AGENT')));
|
|
67
|
+
|
|
68
|
+
if (agentCount > 0) {
|
|
69
|
+
console.log(makeLine(chalk.cyan('[S] SET ACTIVE AGENT')));
|
|
70
|
+
console.log(makeLine(chalk.yellow('[M] CHANGE MODEL')));
|
|
71
|
+
console.log(makeLine(chalk.red('[R] REMOVE AGENT')));
|
|
72
|
+
if (agentCount > 1) {
|
|
73
|
+
console.log(makeLine(chalk.red('[X] REMOVE ALL')));
|
|
74
|
+
}
|
|
58
75
|
}
|
|
59
|
-
options.push({ label: chalk.gray('[<] BACK'), value: 'back' });
|
|
60
76
|
|
|
61
|
-
|
|
62
|
-
console.log(makeLine(opt.label, 'left'));
|
|
63
|
-
}
|
|
77
|
+
console.log(makeLine(chalk.gray('[<] BACK')));
|
|
64
78
|
|
|
65
79
|
drawBoxFooter(boxWidth);
|
|
66
80
|
|
|
67
81
|
const choice = await prompts.textInput(chalk.cyan('SELECT:'));
|
|
82
|
+
const input = (choice || '').toLowerCase();
|
|
68
83
|
|
|
69
|
-
|
|
70
|
-
|
|
84
|
+
// Handle number input (select agent for details)
|
|
85
|
+
const num = parseInt(choice);
|
|
86
|
+
if (!isNaN(num) && num >= 1 && num <= agentCount) {
|
|
87
|
+
return await showAgentDetails(agents[num - 1]);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
switch (input) {
|
|
91
|
+
case '+':
|
|
71
92
|
return await showExistingTokens();
|
|
72
|
-
case '
|
|
73
|
-
if (
|
|
74
|
-
return await
|
|
93
|
+
case 's':
|
|
94
|
+
if (agentCount > 1) {
|
|
95
|
+
return await selectActiveAgent();
|
|
75
96
|
}
|
|
76
|
-
return;
|
|
77
|
-
case '
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
|
|
97
|
+
return await aiAgentMenu();
|
|
98
|
+
case 'm':
|
|
99
|
+
if (agentCount > 0) {
|
|
100
|
+
return await selectAgentForModelChange();
|
|
101
|
+
}
|
|
102
|
+
return await aiAgentMenu();
|
|
103
|
+
case 'r':
|
|
104
|
+
if (agentCount > 0) {
|
|
105
|
+
return await selectAgentToRemove();
|
|
106
|
+
}
|
|
107
|
+
return await aiAgentMenu();
|
|
108
|
+
case 'x':
|
|
109
|
+
if (agentCount > 1) {
|
|
110
|
+
aiService.disconnectAll();
|
|
111
|
+
console.log(chalk.yellow('\n ALL AGENTS REMOVED'));
|
|
81
112
|
await prompts.waitForEnter();
|
|
82
113
|
}
|
|
83
|
-
return;
|
|
114
|
+
return await aiAgentMenu();
|
|
84
115
|
case '<':
|
|
85
116
|
case 'b':
|
|
86
117
|
return;
|
|
87
118
|
default:
|
|
88
|
-
return;
|
|
119
|
+
return await aiAgentMenu();
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Show agent details
|
|
125
|
+
*/
|
|
126
|
+
const showAgentDetails = async (agent) => {
|
|
127
|
+
const boxWidth = getLogoWidth();
|
|
128
|
+
const W = boxWidth - 2;
|
|
129
|
+
|
|
130
|
+
const makeLine = (content) => {
|
|
131
|
+
const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
132
|
+
const padding = W - plainLen;
|
|
133
|
+
return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
console.clear();
|
|
137
|
+
displayBanner();
|
|
138
|
+
drawBoxHeaderContinue('AGENT DETAILS', boxWidth);
|
|
139
|
+
|
|
140
|
+
const providerColor = agent.providerId === 'anthropic' ? chalk.magenta :
|
|
141
|
+
agent.providerId === 'openai' ? chalk.green :
|
|
142
|
+
agent.providerId === 'openrouter' ? chalk.yellow : chalk.cyan;
|
|
143
|
+
|
|
144
|
+
console.log(makeLine(chalk.white('NAME: ') + providerColor(agent.name)));
|
|
145
|
+
console.log(makeLine(chalk.white('PROVIDER: ') + chalk.gray(agent.provider?.name || agent.providerId)));
|
|
146
|
+
console.log(makeLine(chalk.white('MODEL: ') + chalk.gray(agent.model)));
|
|
147
|
+
console.log(makeLine(chalk.white('STATUS: ') + (agent.isActive ? chalk.green('ACTIVE') : chalk.gray('STANDBY'))));
|
|
148
|
+
|
|
149
|
+
console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
|
|
150
|
+
|
|
151
|
+
if (!agent.isActive) {
|
|
152
|
+
console.log(makeLine(chalk.cyan('[A] SET AS ACTIVE')));
|
|
153
|
+
}
|
|
154
|
+
console.log(makeLine(chalk.yellow('[M] CHANGE MODEL')));
|
|
155
|
+
console.log(makeLine(chalk.red('[R] REMOVE')));
|
|
156
|
+
console.log(makeLine(chalk.gray('[<] BACK')));
|
|
157
|
+
|
|
158
|
+
drawBoxFooter(boxWidth);
|
|
159
|
+
|
|
160
|
+
const choice = await prompts.textInput(chalk.cyan('SELECT:'));
|
|
161
|
+
|
|
162
|
+
switch ((choice || '').toLowerCase()) {
|
|
163
|
+
case 'a':
|
|
164
|
+
if (!agent.isActive) {
|
|
165
|
+
aiService.setActiveAgent(agent.id);
|
|
166
|
+
console.log(chalk.green(`\n ${agent.name} IS NOW ACTIVE`));
|
|
167
|
+
await prompts.waitForEnter();
|
|
168
|
+
}
|
|
169
|
+
return await aiAgentMenu();
|
|
170
|
+
case 'm':
|
|
171
|
+
return await selectModel(agent);
|
|
172
|
+
case 'r':
|
|
173
|
+
aiService.removeAgent(agent.id);
|
|
174
|
+
console.log(chalk.yellow(`\n ${agent.name} REMOVED`));
|
|
175
|
+
await prompts.waitForEnter();
|
|
176
|
+
return await aiAgentMenu();
|
|
177
|
+
case '<':
|
|
178
|
+
case 'b':
|
|
179
|
+
return await aiAgentMenu();
|
|
180
|
+
default:
|
|
181
|
+
return await aiAgentMenu();
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Select active agent
|
|
187
|
+
*/
|
|
188
|
+
const selectActiveAgent = async () => {
|
|
189
|
+
const boxWidth = getLogoWidth();
|
|
190
|
+
const W = boxWidth - 2;
|
|
191
|
+
|
|
192
|
+
const makeLine = (content) => {
|
|
193
|
+
const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
194
|
+
const padding = W - plainLen;
|
|
195
|
+
return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
console.clear();
|
|
199
|
+
displayBanner();
|
|
200
|
+
drawBoxHeaderContinue('SET ACTIVE AGENT', boxWidth);
|
|
201
|
+
|
|
202
|
+
const agents = aiService.getAgents();
|
|
203
|
+
|
|
204
|
+
for (let i = 0; i < agents.length; i++) {
|
|
205
|
+
const agent = agents[i];
|
|
206
|
+
const activeMarker = agent.isActive ? chalk.yellow(' (CURRENT)') : '';
|
|
207
|
+
const providerColor = agent.providerId === 'anthropic' ? chalk.magenta :
|
|
208
|
+
agent.providerId === 'openai' ? chalk.green : chalk.cyan;
|
|
209
|
+
|
|
210
|
+
console.log(makeLine(
|
|
211
|
+
chalk.white(`[${i + 1}] `) + providerColor(agent.name) + activeMarker
|
|
212
|
+
));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
console.log(makeLine(''));
|
|
216
|
+
console.log(makeLine(chalk.gray('[<] BACK')));
|
|
217
|
+
|
|
218
|
+
drawBoxFooter(boxWidth);
|
|
219
|
+
|
|
220
|
+
const choice = await prompts.textInput(chalk.cyan('SELECT AGENT:'));
|
|
221
|
+
|
|
222
|
+
if (choice === '<' || choice?.toLowerCase() === 'b') {
|
|
223
|
+
return await aiAgentMenu();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const index = parseInt(choice) - 1;
|
|
227
|
+
if (isNaN(index) || index < 0 || index >= agents.length) {
|
|
228
|
+
return await aiAgentMenu();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
aiService.setActiveAgent(agents[index].id);
|
|
232
|
+
console.log(chalk.green(`\n ${agents[index].name} IS NOW ACTIVE`));
|
|
233
|
+
await prompts.waitForEnter();
|
|
234
|
+
return await aiAgentMenu();
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Select agent to change model
|
|
239
|
+
*/
|
|
240
|
+
const selectAgentForModelChange = async () => {
|
|
241
|
+
const agents = aiService.getAgents();
|
|
242
|
+
|
|
243
|
+
if (agents.length === 1) {
|
|
244
|
+
return await selectModel(agents[0]);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const boxWidth = getLogoWidth();
|
|
248
|
+
const W = boxWidth - 2;
|
|
249
|
+
|
|
250
|
+
const makeLine = (content) => {
|
|
251
|
+
const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
252
|
+
const padding = W - plainLen;
|
|
253
|
+
return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
console.clear();
|
|
257
|
+
displayBanner();
|
|
258
|
+
drawBoxHeaderContinue('SELECT AGENT TO CHANGE MODEL', boxWidth);
|
|
259
|
+
|
|
260
|
+
for (let i = 0; i < agents.length; i++) {
|
|
261
|
+
const agent = agents[i];
|
|
262
|
+
console.log(makeLine(
|
|
263
|
+
chalk.white(`[${i + 1}] `) + chalk.cyan(agent.name) + chalk.gray(` - ${agent.model}`)
|
|
264
|
+
));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
console.log(makeLine(''));
|
|
268
|
+
console.log(makeLine(chalk.gray('[<] BACK')));
|
|
269
|
+
|
|
270
|
+
drawBoxFooter(boxWidth);
|
|
271
|
+
|
|
272
|
+
const choice = await prompts.textInput(chalk.cyan('SELECT AGENT:'));
|
|
273
|
+
|
|
274
|
+
if (choice === '<' || choice?.toLowerCase() === 'b') {
|
|
275
|
+
return await aiAgentMenu();
|
|
89
276
|
}
|
|
277
|
+
|
|
278
|
+
const index = parseInt(choice) - 1;
|
|
279
|
+
if (isNaN(index) || index < 0 || index >= agents.length) {
|
|
280
|
+
return await aiAgentMenu();
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return await selectModel(agents[index]);
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Select agent to remove
|
|
288
|
+
*/
|
|
289
|
+
const selectAgentToRemove = async () => {
|
|
290
|
+
const agents = aiService.getAgents();
|
|
291
|
+
|
|
292
|
+
if (agents.length === 1) {
|
|
293
|
+
aiService.removeAgent(agents[0].id);
|
|
294
|
+
console.log(chalk.yellow(`\n ${agents[0].name} REMOVED`));
|
|
295
|
+
await prompts.waitForEnter();
|
|
296
|
+
return await aiAgentMenu();
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const boxWidth = getLogoWidth();
|
|
300
|
+
const W = boxWidth - 2;
|
|
301
|
+
|
|
302
|
+
const makeLine = (content) => {
|
|
303
|
+
const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
304
|
+
const padding = W - plainLen;
|
|
305
|
+
return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
console.clear();
|
|
309
|
+
displayBanner();
|
|
310
|
+
drawBoxHeaderContinue('SELECT AGENT TO REMOVE', boxWidth);
|
|
311
|
+
|
|
312
|
+
for (let i = 0; i < agents.length; i++) {
|
|
313
|
+
const agent = agents[i];
|
|
314
|
+
console.log(makeLine(
|
|
315
|
+
chalk.white(`[${i + 1}] `) + chalk.red(agent.name)
|
|
316
|
+
));
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
console.log(makeLine(''));
|
|
320
|
+
console.log(makeLine(chalk.gray('[<] BACK')));
|
|
321
|
+
|
|
322
|
+
drawBoxFooter(boxWidth);
|
|
323
|
+
|
|
324
|
+
const choice = await prompts.textInput(chalk.cyan('SELECT AGENT TO REMOVE:'));
|
|
325
|
+
|
|
326
|
+
if (choice === '<' || choice?.toLowerCase() === 'b') {
|
|
327
|
+
return await aiAgentMenu();
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const index = parseInt(choice) - 1;
|
|
331
|
+
if (isNaN(index) || index < 0 || index >= agents.length) {
|
|
332
|
+
return await aiAgentMenu();
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
aiService.removeAgent(agents[index].id);
|
|
336
|
+
console.log(chalk.yellow(`\n ${agents[index].name} REMOVED`));
|
|
337
|
+
await prompts.waitForEnter();
|
|
338
|
+
return await aiAgentMenu();
|
|
90
339
|
};
|
|
91
340
|
|
|
92
341
|
// Cache for scanned tokens (avoid multiple Keychain prompts)
|
|
@@ -217,11 +466,12 @@ const showExistingTokens = async () => {
|
|
|
217
466
|
return await showExistingTokens();
|
|
218
467
|
}
|
|
219
468
|
|
|
220
|
-
//
|
|
469
|
+
// Add as new agent
|
|
221
470
|
const model = provider.defaultModel;
|
|
222
|
-
|
|
471
|
+
const agentName = `${provider.name} (${selectedToken.source})`;
|
|
472
|
+
await aiService.addAgent(selectedToken.provider, 'api_key', credentials, model, agentName);
|
|
223
473
|
|
|
224
|
-
spinner.succeed(`
|
|
474
|
+
spinner.succeed(`AGENT ADDED: ${provider.name}`);
|
|
225
475
|
console.log(chalk.gray(` SOURCE: ${selectedToken.source}`));
|
|
226
476
|
console.log(chalk.gray(` MODEL: ${model}`));
|
|
227
477
|
|
|
@@ -644,11 +894,11 @@ const setupConnection = async (provider, option) => {
|
|
|
644
894
|
return await selectProviderOption(provider);
|
|
645
895
|
}
|
|
646
896
|
|
|
647
|
-
//
|
|
897
|
+
// Add as new agent
|
|
648
898
|
try {
|
|
649
899
|
const model = credentials.model || provider.defaultModel;
|
|
650
|
-
await aiService.
|
|
651
|
-
spinner.succeed(`
|
|
900
|
+
await aiService.addAgent(provider.id, option.id, credentials, model, provider.name);
|
|
901
|
+
spinner.succeed(`AGENT ADDED: ${provider.name}`);
|
|
652
902
|
|
|
653
903
|
// Show available models for local providers
|
|
654
904
|
if (validation.models && validation.models.length > 0) {
|
|
@@ -665,9 +915,9 @@ const setupConnection = async (provider, option) => {
|
|
|
665
915
|
};
|
|
666
916
|
|
|
667
917
|
/**
|
|
668
|
-
* Select/change model for
|
|
918
|
+
* Select/change model for an agent
|
|
669
919
|
*/
|
|
670
|
-
const selectModel = async (
|
|
920
|
+
const selectModel = async (agent) => {
|
|
671
921
|
const boxWidth = getLogoWidth();
|
|
672
922
|
const W = boxWidth - 2;
|
|
673
923
|
|
|
@@ -679,9 +929,9 @@ const selectModel = async (provider) => {
|
|
|
679
929
|
|
|
680
930
|
console.clear();
|
|
681
931
|
displayBanner();
|
|
682
|
-
drawBoxHeaderContinue(
|
|
932
|
+
drawBoxHeaderContinue(`SELECT MODEL - ${agent.name}`, boxWidth);
|
|
683
933
|
|
|
684
|
-
const models = provider
|
|
934
|
+
const models = agent.provider?.models || [];
|
|
685
935
|
|
|
686
936
|
if (models.length === 0) {
|
|
687
937
|
console.log(makeLine(chalk.gray('NO PREDEFINED MODELS. ENTER MODEL NAME MANUALLY.')));
|
|
@@ -693,9 +943,7 @@ const selectModel = async (provider) => {
|
|
|
693
943
|
if (!model || model === '<') {
|
|
694
944
|
return await aiAgentMenu();
|
|
695
945
|
}
|
|
696
|
-
|
|
697
|
-
settings.model = model;
|
|
698
|
-
aiService.saveAISettings(settings);
|
|
946
|
+
aiService.updateAgent(agent.id, { model });
|
|
699
947
|
console.log(chalk.green(`\n MODEL CHANGED TO: ${model}`));
|
|
700
948
|
await prompts.waitForEnter();
|
|
701
949
|
return await aiAgentMenu();
|
|
@@ -704,7 +952,8 @@ const selectModel = async (provider) => {
|
|
|
704
952
|
models.forEach((model, index) => {
|
|
705
953
|
// Truncate long model names
|
|
706
954
|
const displayModel = model.length > W - 10 ? model.substring(0, W - 13) + '...' : model;
|
|
707
|
-
|
|
955
|
+
const currentMarker = model === agent.model ? chalk.yellow(' (CURRENT)') : '';
|
|
956
|
+
console.log(makeLine(chalk.cyan(`[${index + 1}] ${displayModel}`) + currentMarker));
|
|
708
957
|
});
|
|
709
958
|
|
|
710
959
|
console.log(makeLine(''));
|
|
@@ -724,9 +973,7 @@ const selectModel = async (provider) => {
|
|
|
724
973
|
}
|
|
725
974
|
|
|
726
975
|
const selectedModel = models[index];
|
|
727
|
-
|
|
728
|
-
settings.model = selectedModel;
|
|
729
|
-
aiService.saveAISettings(settings);
|
|
976
|
+
aiService.updateAgent(agent.id, { model: selectedModel });
|
|
730
977
|
|
|
731
978
|
console.log(chalk.green(`\n MODEL CHANGED TO: ${selectedModel}`));
|
|
732
979
|
await prompts.waitForEnter();
|
package/src/menus/dashboard.js
CHANGED
|
@@ -12,6 +12,7 @@ const { getCachedStats } = require('../services/stats-cache');
|
|
|
12
12
|
const { prompts } = require('../utils');
|
|
13
13
|
const aiService = require('../services/ai');
|
|
14
14
|
|
|
15
|
+
|
|
15
16
|
/**
|
|
16
17
|
* Dashboard menu after login
|
|
17
18
|
*/
|
|
@@ -49,32 +50,27 @@ const dashboardMenu = async (service) => {
|
|
|
49
50
|
if (statsInfo) {
|
|
50
51
|
console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
|
|
51
52
|
|
|
52
|
-
|
|
53
|
+
const balStr = statsInfo.balance !== null ? `$${statsInfo.balance.toLocaleString()}` : '--';
|
|
53
54
|
const balColor = statsInfo.balance !== null ? chalk.green : chalk.gray;
|
|
54
55
|
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
: null;
|
|
60
|
-
|
|
61
|
-
// Build plain text for length calculation (unicode ✔ and ○ are 1 char width each)
|
|
62
|
-
// Format: "✔ CONNECTIONS: X ✔ ACCOUNTS: X ✔ BALANCE: $X ○ AI: NONE"
|
|
63
|
-
const plainText = `* CONNECTIONS: ${statsInfo.connections} * ACCOUNTS: ${statsInfo.accounts} * BALANCE: ${balStr} * AI: ${aiStatus || 'NONE'}`;
|
|
56
|
+
// Build plain text for length calculation
|
|
57
|
+
// Format: "✔ CONNECTIONS: X ✔ ACCOUNTS: X ✔ BALANCE: $X ✔ AI: CONNECTED"
|
|
58
|
+
const aiText = aiConnected ? 'CONNECTED' : 'NONE';
|
|
59
|
+
const plainText = `* CONNECTIONS: ${statsInfo.connections} * ACCOUNTS: ${statsInfo.accounts} * BALANCE: ${balStr} * AI: ${aiText}`;
|
|
64
60
|
const statsLen = plainText.length;
|
|
65
61
|
const statsLeftPad = Math.max(0, Math.floor((W - statsLen) / 2));
|
|
66
62
|
const statsRightPad = Math.max(0, W - statsLen - statsLeftPad);
|
|
67
63
|
|
|
68
64
|
// Build with unicode icons and colors
|
|
69
65
|
const checkIcon = chalk.yellow('✔ ');
|
|
70
|
-
const aiIcon =
|
|
71
|
-
const
|
|
66
|
+
const aiIcon = aiConnected ? chalk.magenta('✔ ') : chalk.gray('○ ');
|
|
67
|
+
const aiTextColored = aiConnected ? chalk.magenta('CONNECTED') : chalk.gray('NONE');
|
|
72
68
|
|
|
73
69
|
console.log(chalk.cyan('║') + ' '.repeat(statsLeftPad) +
|
|
74
70
|
checkIcon + chalk.white(`CONNECTIONS: ${statsInfo.connections}`) + ' ' +
|
|
75
71
|
checkIcon + chalk.white(`ACCOUNTS: ${statsInfo.accounts}`) + ' ' +
|
|
76
72
|
checkIcon + chalk.white('BALANCE: ') + balColor(balStr) + ' ' +
|
|
77
|
-
aiIcon + chalk.white('AI: ') +
|
|
73
|
+
aiIcon + chalk.white('AI: ') + aiTextColored +
|
|
78
74
|
' '.repeat(statsRightPad) + chalk.cyan('║'));
|
|
79
75
|
}
|
|
80
76
|
|