hedgequantx 2.6.163 → 2.7.1
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 +15 -88
- package/bin/cli.js +0 -11
- package/dist/lib/api.jsc +0 -0
- package/dist/lib/api2.jsc +0 -0
- package/dist/lib/core.jsc +0 -0
- package/dist/lib/core2.jsc +0 -0
- package/dist/lib/data.js +1 -1
- package/dist/lib/data.jsc +0 -0
- package/dist/lib/data2.jsc +0 -0
- package/dist/lib/decoder.jsc +0 -0
- package/dist/lib/m/mod1.jsc +0 -0
- package/dist/lib/m/mod2.jsc +0 -0
- package/dist/lib/n/r1.jsc +0 -0
- package/dist/lib/n/r2.jsc +0 -0
- package/dist/lib/n/r3.jsc +0 -0
- package/dist/lib/n/r4.jsc +0 -0
- package/dist/lib/n/r5.jsc +0 -0
- package/dist/lib/n/r6.jsc +0 -0
- package/dist/lib/n/r7.jsc +0 -0
- package/dist/lib/o/util1.jsc +0 -0
- package/dist/lib/o/util2.jsc +0 -0
- package/package.json +8 -5
- package/src/app.js +40 -162
- package/src/config/constants.js +31 -33
- package/src/config/propfirms.js +13 -217
- package/src/config/settings.js +0 -43
- package/src/lib/api.js +198 -0
- package/src/lib/api2.js +353 -0
- package/src/lib/core.js +539 -0
- package/src/lib/core2.js +341 -0
- package/src/lib/data.js +555 -0
- package/src/lib/data2.js +492 -0
- package/src/lib/decoder.js +599 -0
- package/src/lib/m/s1.js +804 -0
- package/src/lib/m/s2.js +34 -0
- package/src/lib/n/r1.js +454 -0
- package/src/lib/n/r2.js +514 -0
- package/src/lib/n/r3.js +631 -0
- package/src/lib/n/r4.js +401 -0
- package/src/lib/n/r5.js +335 -0
- package/src/lib/n/r6.js +425 -0
- package/src/lib/n/r7.js +530 -0
- package/src/lib/o/l1.js +44 -0
- package/src/lib/o/l2.js +427 -0
- package/src/lib/python-bridge.js +206 -0
- package/src/menus/connect.js +14 -176
- package/src/menus/dashboard.js +65 -110
- package/src/pages/accounts.js +18 -18
- package/src/pages/algo/copy-trading.js +210 -240
- package/src/pages/algo/index.js +41 -104
- package/src/pages/algo/one-account.js +386 -33
- package/src/pages/algo/ui.js +312 -151
- package/src/pages/orders.js +3 -3
- package/src/pages/positions.js +3 -3
- package/src/pages/stats/chart.js +74 -0
- package/src/pages/stats/display.js +228 -0
- package/src/pages/stats/index.js +236 -0
- package/src/pages/stats/metrics.js +213 -0
- package/src/pages/user.js +6 -6
- package/src/services/hqx-server/constants.js +55 -0
- package/src/services/hqx-server/index.js +401 -0
- package/src/services/hqx-server/latency.js +81 -0
- package/src/services/index.js +12 -3
- package/src/services/rithmic/accounts.js +7 -32
- package/src/services/rithmic/connection.js +1 -204
- package/src/services/rithmic/contracts.js +116 -99
- package/src/services/rithmic/handlers.js +21 -196
- package/src/services/rithmic/index.js +63 -120
- package/src/services/rithmic/market.js +31 -0
- package/src/services/rithmic/orders.js +5 -111
- package/src/services/rithmic/protobuf.js +384 -138
- package/src/services/session.js +22 -173
- package/src/ui/box.js +10 -18
- package/src/ui/index.js +1 -3
- package/src/ui/menu.js +1 -1
- package/src/utils/prompts.js +2 -2
- package/dist/lib/m/s1.js +0 -1
- package/src/menus/ai-agent-connect.js +0 -181
- package/src/menus/ai-agent-models.js +0 -219
- package/src/menus/ai-agent-oauth.js +0 -292
- package/src/menus/ai-agent-ui.js +0 -141
- package/src/menus/ai-agent.js +0 -484
- package/src/pages/algo/algo-config.js +0 -195
- package/src/pages/algo/algo-multi.js +0 -801
- package/src/pages/algo/algo-utils.js +0 -58
- package/src/pages/algo/copy-engine.js +0 -449
- package/src/pages/algo/custom-strategy.js +0 -459
- package/src/pages/algo/logger.js +0 -245
- package/src/pages/algo/smart-logs-data.js +0 -218
- package/src/pages/algo/smart-logs.js +0 -387
- package/src/pages/algo/ui-constants.js +0 -144
- package/src/pages/algo/ui-summary.js +0 -184
- package/src/pages/stats-calculations.js +0 -191
- package/src/pages/stats-ui.js +0 -381
- package/src/pages/stats.js +0 -339
- package/src/services/ai/client-analysis.js +0 -194
- package/src/services/ai/client-models.js +0 -333
- package/src/services/ai/client.js +0 -343
- package/src/services/ai/index.js +0 -384
- package/src/services/ai/oauth-anthropic.js +0 -265
- package/src/services/ai/oauth-gemini.js +0 -223
- package/src/services/ai/oauth-iflow.js +0 -269
- package/src/services/ai/oauth-openai.js +0 -233
- package/src/services/ai/oauth-qwen.js +0 -279
- package/src/services/ai/providers/direct-providers.js +0 -323
- package/src/services/ai/providers/index.js +0 -62
- package/src/services/ai/providers/other-providers.js +0 -104
- package/src/services/ai/proxy-install.js +0 -249
- package/src/services/ai/proxy-manager.js +0 -494
- package/src/services/ai/proxy-remote.js +0 -161
- package/src/services/ai/strategy-supervisor.js +0 -1312
- package/src/services/ai/supervisor-data.js +0 -195
- package/src/services/ai/supervisor-optimize.js +0 -215
- package/src/services/ai/supervisor-sync.js +0 -178
- package/src/services/ai/supervisor-utils.js +0 -158
- package/src/services/ai/supervisor.js +0 -484
- package/src/services/ai/validation.js +0 -250
- package/src/services/hqx-server-events.js +0 -110
- package/src/services/hqx-server-handlers.js +0 -217
- package/src/services/hqx-server-latency.js +0 -136
- package/src/services/hqx-server.js +0 -403
- package/src/services/position-constants.js +0 -28
- package/src/services/position-exit-logic.js +0 -174
- package/src/services/position-manager.js +0 -438
- package/src/services/position-momentum.js +0 -206
- package/src/services/projectx/accounts.js +0 -142
- package/src/services/projectx/index.js +0 -443
- package/src/services/projectx/market.js +0 -172
- package/src/services/projectx/stats.js +0 -110
- package/src/services/projectx/trading.js +0 -180
- package/src/services/rithmic/latency-tracker.js +0 -182
- package/src/services/rithmic/market-data-decoders.js +0 -229
- package/src/services/rithmic/market-data.js +0 -272
- package/src/services/rithmic/orders-fast.js +0 -246
- package/src/services/rithmic/proto-decoders.js +0 -403
- package/src/services/rithmic/specs.js +0 -146
- package/src/services/rithmic/trade-history.js +0 -254
- package/src/services/session-history.js +0 -475
- package/src/services/strategy/hft-signal-calc.js +0 -147
- package/src/services/strategy/hft-tick.js +0 -407
- package/src/services/strategy/recovery-math.js +0 -402
- package/src/services/tradovate/constants.js +0 -109
- package/src/services/tradovate/index.js +0 -392
- package/src/services/tradovate/market.js +0 -47
- package/src/services/tradovate/orders.js +0 -145
- package/src/services/tradovate/websocket.js +0 -97
package/src/menus/ai-agent-ui.js
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AI Agent UI Helpers
|
|
3
|
-
* Shared UI functions for AI agent menu
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const chalk = require('chalk');
|
|
7
|
-
const { getLogoWidth } = require('../ui');
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Create a line with padding for box display
|
|
11
|
-
* @param {number} W - Box inner width
|
|
12
|
-
* @param {string} content - Content to display
|
|
13
|
-
* @param {string} align - Alignment: 'left' or 'center'
|
|
14
|
-
* @returns {string} Formatted line
|
|
15
|
-
*/
|
|
16
|
-
const makeLine = (W, content, align = 'left') => {
|
|
17
|
-
const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
18
|
-
const padding = W - plainLen;
|
|
19
|
-
if (align === 'center') {
|
|
20
|
-
const leftPad = Math.floor(padding / 2);
|
|
21
|
-
return chalk.cyan('║') + ' '.repeat(leftPad) + content + ' '.repeat(padding - leftPad) + chalk.cyan('║');
|
|
22
|
-
}
|
|
23
|
-
return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Create a 2-column row for box display
|
|
28
|
-
* @param {number} W - Box inner width
|
|
29
|
-
* @param {string} left - Left column content
|
|
30
|
-
* @param {string} right - Right column content
|
|
31
|
-
* @returns {string} Formatted line
|
|
32
|
-
*/
|
|
33
|
-
const make2ColRow = (W, left, right) => {
|
|
34
|
-
const col1Width = Math.floor(W / 2);
|
|
35
|
-
const leftPlain = left.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
36
|
-
const rightPlain = right.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
37
|
-
const leftPadded = ' ' + left + ' '.repeat(Math.max(0, col1Width - leftPlain - 1));
|
|
38
|
-
const rightPadded = right + ' '.repeat(Math.max(0, W - col1Width - rightPlain));
|
|
39
|
-
return chalk.cyan('║') + leftPadded + rightPadded + chalk.cyan('║');
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Create a menu row with 2 columns centered
|
|
44
|
-
* @param {number} W - Box inner width
|
|
45
|
-
* @param {string} col1 - First column content
|
|
46
|
-
* @param {string} col2 - Second column content
|
|
47
|
-
* @returns {string} Formatted line
|
|
48
|
-
*/
|
|
49
|
-
const menuRow2 = (W, col1, col2 = '') => {
|
|
50
|
-
const colWidth = Math.floor(W / 2);
|
|
51
|
-
const c1Plain = col1.replace(/\x1b\[[0-9;]*m/g, '');
|
|
52
|
-
const c2Plain = col2.replace(/\x1b\[[0-9;]*m/g, '');
|
|
53
|
-
|
|
54
|
-
const pad1Left = Math.floor((colWidth - c1Plain.length) / 2);
|
|
55
|
-
const pad1Right = colWidth - c1Plain.length - pad1Left;
|
|
56
|
-
|
|
57
|
-
const col2Width = W - colWidth;
|
|
58
|
-
const pad2Left = Math.floor((col2Width - c2Plain.length) / 2);
|
|
59
|
-
const pad2Right = col2Width - c2Plain.length - pad2Left;
|
|
60
|
-
|
|
61
|
-
const line =
|
|
62
|
-
' '.repeat(pad1Left) + col1 + ' '.repeat(pad1Right) +
|
|
63
|
-
' '.repeat(pad2Left) + col2 + ' '.repeat(pad2Right);
|
|
64
|
-
|
|
65
|
-
return chalk.cyan('║') + line + chalk.cyan('║');
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Create a menu item with key and label
|
|
70
|
-
* @param {string} key - Key to press
|
|
71
|
-
* @param {string} label - Label to display
|
|
72
|
-
* @param {Function} color - Chalk color function
|
|
73
|
-
* @returns {string} Formatted menu item
|
|
74
|
-
*/
|
|
75
|
-
const menuItem = (key, label, color) => {
|
|
76
|
-
const text = `[${key}] ${label.padEnd(14)}`;
|
|
77
|
-
return color(text);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Get provider color based on provider ID
|
|
82
|
-
* @param {string} providerId - Provider identifier
|
|
83
|
-
* @returns {Function} Chalk color function
|
|
84
|
-
*/
|
|
85
|
-
const getProviderColor = (providerId) => {
|
|
86
|
-
if (providerId === 'anthropic') return chalk.magenta;
|
|
87
|
-
if (providerId === 'openai') return chalk.green;
|
|
88
|
-
if (providerId === 'openrouter') return chalk.yellow;
|
|
89
|
-
return chalk.cyan;
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Get box dimensions
|
|
94
|
-
* @returns {Object} { boxWidth, W }
|
|
95
|
-
*/
|
|
96
|
-
const getBoxDimensions = () => {
|
|
97
|
-
const boxWidth = getLogoWidth();
|
|
98
|
-
const W = boxWidth - 2;
|
|
99
|
-
return { boxWidth, W };
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Open URL in default browser
|
|
104
|
-
* @param {string} url - URL to open
|
|
105
|
-
* @returns {Promise<boolean>} true if browser opened, false if failed
|
|
106
|
-
*/
|
|
107
|
-
const openBrowser = (url) => {
|
|
108
|
-
return new Promise((resolve) => {
|
|
109
|
-
const { exec } = require('child_process');
|
|
110
|
-
const platform = process.platform;
|
|
111
|
-
|
|
112
|
-
let cmd;
|
|
113
|
-
if (platform === 'darwin') cmd = `open "${url}"`;
|
|
114
|
-
else if (platform === 'win32') cmd = `start "" "${url}"`;
|
|
115
|
-
else cmd = `xdg-open "${url}"`;
|
|
116
|
-
|
|
117
|
-
exec(cmd, (err) => {
|
|
118
|
-
resolve(!err);
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Check if running on remote/VPS (SSH)
|
|
125
|
-
* @returns {boolean} true if remote
|
|
126
|
-
*/
|
|
127
|
-
const isRemoteEnvironment = () => {
|
|
128
|
-
return process.env.SSH_CONNECTION || process.env.SSH_CLIENT ||
|
|
129
|
-
(process.env.DISPLAY === undefined && process.platform === 'linux');
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
module.exports = {
|
|
133
|
-
makeLine,
|
|
134
|
-
make2ColRow,
|
|
135
|
-
menuRow2,
|
|
136
|
-
menuItem,
|
|
137
|
-
getProviderColor,
|
|
138
|
-
getBoxDimensions,
|
|
139
|
-
openBrowser,
|
|
140
|
-
isRemoteEnvironment
|
|
141
|
-
};
|
package/src/menus/ai-agent.js
DELETED
|
@@ -1,484 +0,0 @@
|
|
|
1
|
-
/** AI Agent Menu - Configure multiple AI provider connections */
|
|
2
|
-
const chalk = require('chalk');
|
|
3
|
-
const { getLogoWidth, drawBoxHeaderContinue, drawBoxFooter, displayBanner } = require('../ui');
|
|
4
|
-
const { prompts } = require('../utils');
|
|
5
|
-
const aiService = require('../services/ai');
|
|
6
|
-
const { getCategories, getProvidersByCategory } = require('../services/ai/providers');
|
|
7
|
-
const { makeLine, make2ColRow, menuRow2, menuItem, getProviderColor, getBoxDimensions } = require('./ai-agent-ui');
|
|
8
|
-
const { setupOAuthConnection, getOAuthConfig } = require('./ai-agent-oauth');
|
|
9
|
-
const { selectModelFromList, selectModel } = require('./ai-agent-models');
|
|
10
|
-
const { collectCredentials, validateAndFetchModels, addConnectedAgent } = require('./ai-agent-connect');
|
|
11
|
-
|
|
12
|
-
/** Main AI Agent menu */
|
|
13
|
-
const aiAgentMenu = async () => {
|
|
14
|
-
const { boxWidth, W } = getBoxDimensions();
|
|
15
|
-
|
|
16
|
-
console.clear();
|
|
17
|
-
displayBanner();
|
|
18
|
-
drawBoxHeaderContinue('AI AGENTS', boxWidth);
|
|
19
|
-
|
|
20
|
-
// Get all connected agents
|
|
21
|
-
const agents = aiService.getAgents();
|
|
22
|
-
const agentCount = agents.length;
|
|
23
|
-
|
|
24
|
-
if (agentCount === 0) {
|
|
25
|
-
console.log(makeLine(W, chalk.white('STATUS: NO AGENTS CONNECTED')));
|
|
26
|
-
} else {
|
|
27
|
-
console.log(makeLine(W, chalk.green(`STATUS: ${agentCount} AGENT${agentCount > 1 ? 'S' : ''} CONNECTED`)));
|
|
28
|
-
console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
|
|
29
|
-
|
|
30
|
-
// List all agents
|
|
31
|
-
for (let i = 0; i < agents.length; i++) {
|
|
32
|
-
const agent = agents[i];
|
|
33
|
-
const isActive = agent.isActive || agents.length === 1;
|
|
34
|
-
const activeMarker = isActive ? ' [ACTIVE]' : '';
|
|
35
|
-
const providerColor = getProviderColor(agent.providerId);
|
|
36
|
-
|
|
37
|
-
const prefix = `[${i + 1}] `;
|
|
38
|
-
const suffix = ` - ${agent.model || 'N/A'}`;
|
|
39
|
-
const maxNameLen = W - prefix.length - activeMarker.length - suffix.length - 2;
|
|
40
|
-
|
|
41
|
-
const displayName = agent.name.length > maxNameLen
|
|
42
|
-
? agent.name.substring(0, maxNameLen - 3) + '...'
|
|
43
|
-
: agent.name;
|
|
44
|
-
|
|
45
|
-
console.log(makeLine(W,
|
|
46
|
-
chalk.white(prefix) +
|
|
47
|
-
providerColor(displayName) +
|
|
48
|
-
chalk.green(activeMarker) +
|
|
49
|
-
chalk.white(suffix)
|
|
50
|
-
));
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
|
|
55
|
-
|
|
56
|
-
// Menu options in 2 columns
|
|
57
|
-
if (agentCount > 0) {
|
|
58
|
-
if (agentCount > 1) {
|
|
59
|
-
console.log(menuRow2(W, menuItem('+', 'ADD AGENT', chalk.green), menuItem('S', 'SET ACTIVE', chalk.cyan)));
|
|
60
|
-
console.log(menuRow2(W, menuItem('M', 'CHANGE MODEL', chalk.yellow), menuItem('R', 'REMOVE AGENT', chalk.red)));
|
|
61
|
-
console.log(menuRow2(W, menuItem('X', 'REMOVE ALL', chalk.red), menuItem('<', 'BACK', chalk.white)));
|
|
62
|
-
} else {
|
|
63
|
-
console.log(menuRow2(W, menuItem('+', 'ADD AGENT', chalk.green), menuItem('M', 'CHANGE MODEL', chalk.yellow)));
|
|
64
|
-
console.log(menuRow2(W, menuItem('R', 'REMOVE AGENT', chalk.red), menuItem('<', 'BACK', chalk.white)));
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
console.log(menuRow2(W, menuItem('+', 'ADD AGENT', chalk.green), menuItem('<', 'BACK', chalk.white)));
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
drawBoxFooter(boxWidth);
|
|
71
|
-
|
|
72
|
-
const choice = await prompts.textInput(chalk.cyan('SELECT:'));
|
|
73
|
-
const input = (choice || '').toLowerCase();
|
|
74
|
-
|
|
75
|
-
// Handle number input (select agent for details)
|
|
76
|
-
const num = parseInt(choice);
|
|
77
|
-
if (!isNaN(num) && num >= 1 && num <= agentCount) {
|
|
78
|
-
return await showAgentDetails(agents[num - 1]);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
switch (input) {
|
|
82
|
-
case '+':
|
|
83
|
-
return await selectCategory();
|
|
84
|
-
case 's':
|
|
85
|
-
if (agentCount > 1) return await selectActiveAgent();
|
|
86
|
-
return await aiAgentMenu();
|
|
87
|
-
case 'm':
|
|
88
|
-
if (agentCount > 0) return await selectAgentForModelChange();
|
|
89
|
-
return await aiAgentMenu();
|
|
90
|
-
case 'r':
|
|
91
|
-
if (agentCount > 0) return await selectAgentToRemove();
|
|
92
|
-
return await aiAgentMenu();
|
|
93
|
-
case 'x':
|
|
94
|
-
if (agentCount > 1) {
|
|
95
|
-
aiService.disconnectAll();
|
|
96
|
-
console.log(chalk.yellow('\n ALL AGENTS REMOVED'));
|
|
97
|
-
await prompts.waitForEnter();
|
|
98
|
-
}
|
|
99
|
-
return await aiAgentMenu();
|
|
100
|
-
case '<':
|
|
101
|
-
case 'b':
|
|
102
|
-
return;
|
|
103
|
-
default:
|
|
104
|
-
return await aiAgentMenu();
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
/** Show agent details */
|
|
109
|
-
const showAgentDetails = async (agent) => {
|
|
110
|
-
const { boxWidth, W } = getBoxDimensions();
|
|
111
|
-
|
|
112
|
-
console.clear();
|
|
113
|
-
displayBanner();
|
|
114
|
-
drawBoxHeaderContinue('AGENT DETAILS', boxWidth);
|
|
115
|
-
|
|
116
|
-
const providerColor = getProviderColor(agent.providerId);
|
|
117
|
-
|
|
118
|
-
console.log(makeLine(W, chalk.white('NAME: ') + providerColor(agent.name)));
|
|
119
|
-
console.log(makeLine(W, chalk.white('PROVIDER: ') + chalk.white(agent.provider?.name || agent.providerId)));
|
|
120
|
-
console.log(makeLine(W, chalk.white('MODEL: ') + chalk.white(agent.model || 'N/A')));
|
|
121
|
-
console.log(makeLine(W, chalk.white('STATUS: ') + (agent.isActive ? chalk.green('ACTIVE') : chalk.white('STANDBY'))));
|
|
122
|
-
|
|
123
|
-
console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
|
|
124
|
-
|
|
125
|
-
if (!agent.isActive) {
|
|
126
|
-
console.log(menuRow2(W, chalk.cyan('[A] SET AS ACTIVE'), chalk.yellow('[M] CHANGE MODEL')));
|
|
127
|
-
console.log(menuRow2(W, chalk.red('[R] REMOVE'), chalk.white('[<] BACK')));
|
|
128
|
-
} else {
|
|
129
|
-
console.log(menuRow2(W, chalk.yellow('[M] CHANGE MODEL'), chalk.red('[R] REMOVE')));
|
|
130
|
-
console.log(menuRow2(W, chalk.white('[<] BACK'), ''));
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
drawBoxFooter(boxWidth);
|
|
134
|
-
|
|
135
|
-
const choice = await prompts.textInput(chalk.cyan('SELECT:'));
|
|
136
|
-
const agentDisplayName = agent.model ? `${agent.name} (${agent.model})` : agent.name;
|
|
137
|
-
|
|
138
|
-
switch ((choice || '').toLowerCase()) {
|
|
139
|
-
case 'a':
|
|
140
|
-
if (!agent.isActive) {
|
|
141
|
-
aiService.setActiveAgent(agent.id);
|
|
142
|
-
console.log(chalk.green(`\n ${agentDisplayName} IS NOW ACTIVE`));
|
|
143
|
-
await prompts.waitForEnter();
|
|
144
|
-
}
|
|
145
|
-
return await aiAgentMenu();
|
|
146
|
-
case 'm':
|
|
147
|
-
return await selectModel(agent, aiAgentMenu);
|
|
148
|
-
case 'r':
|
|
149
|
-
aiService.removeAgent(agent.id);
|
|
150
|
-
console.log(chalk.yellow(`\n ${agentDisplayName} REMOVED`));
|
|
151
|
-
await prompts.waitForEnter();
|
|
152
|
-
return await aiAgentMenu();
|
|
153
|
-
case '<':
|
|
154
|
-
case 'b':
|
|
155
|
-
return await aiAgentMenu();
|
|
156
|
-
default:
|
|
157
|
-
return await aiAgentMenu();
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
/** Select active agent */
|
|
162
|
-
const selectActiveAgent = async () => {
|
|
163
|
-
const { boxWidth, W } = getBoxDimensions();
|
|
164
|
-
|
|
165
|
-
console.clear();
|
|
166
|
-
displayBanner();
|
|
167
|
-
drawBoxHeaderContinue('SET ACTIVE AGENT', boxWidth);
|
|
168
|
-
|
|
169
|
-
const agents = aiService.getAgents();
|
|
170
|
-
|
|
171
|
-
for (let i = 0; i < agents.length; i++) {
|
|
172
|
-
const agent = agents[i];
|
|
173
|
-
const activeMarker = agent.isActive ? chalk.yellow(' (CURRENT)') : '';
|
|
174
|
-
const providerColor = getProviderColor(agent.providerId);
|
|
175
|
-
const modelDisplay = agent.model ? chalk.gray(` (${agent.model})`) : '';
|
|
176
|
-
console.log(makeLine(W, chalk.white(`[${i + 1}] `) + providerColor(agent.name) + modelDisplay + activeMarker));
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
console.log(makeLine(W, ''));
|
|
180
|
-
console.log(makeLine(W, chalk.white('[<] BACK')));
|
|
181
|
-
|
|
182
|
-
drawBoxFooter(boxWidth);
|
|
183
|
-
|
|
184
|
-
const choice = await prompts.textInput(chalk.cyan('SELECT AGENT:'));
|
|
185
|
-
|
|
186
|
-
if (!choice || choice.trim() === '' || choice === '<' || choice?.toLowerCase() === 'b') {
|
|
187
|
-
return await aiAgentMenu();
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const index = parseInt(choice) - 1;
|
|
191
|
-
if (isNaN(index) || index < 0 || index >= agents.length) {
|
|
192
|
-
return await aiAgentMenu();
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
aiService.setActiveAgent(agents[index].id);
|
|
196
|
-
const selectedAgent = agents[index];
|
|
197
|
-
const modelInfo = selectedAgent.model ? ` (${selectedAgent.model})` : '';
|
|
198
|
-
console.log(chalk.green(`\n ${selectedAgent.name}${modelInfo} IS NOW ACTIVE`));
|
|
199
|
-
await prompts.waitForEnter();
|
|
200
|
-
return await aiAgentMenu();
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
/** Select agent to change model */
|
|
204
|
-
const selectAgentForModelChange = async () => {
|
|
205
|
-
const agents = aiService.getAgents();
|
|
206
|
-
|
|
207
|
-
if (agents.length === 1) {
|
|
208
|
-
return await selectModel(agents[0], aiAgentMenu);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const { boxWidth, W } = getBoxDimensions();
|
|
212
|
-
|
|
213
|
-
console.clear();
|
|
214
|
-
displayBanner();
|
|
215
|
-
drawBoxHeaderContinue('SELECT AGENT TO CHANGE MODEL', boxWidth);
|
|
216
|
-
|
|
217
|
-
for (let i = 0; i < agents.length; i++) {
|
|
218
|
-
const agent = agents[i];
|
|
219
|
-
console.log(makeLine(W, chalk.white(`[${i + 1}] `) + chalk.cyan(agent.name) + chalk.white(` - ${agent.model}`)));
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
console.log(makeLine(W, ''));
|
|
223
|
-
console.log(makeLine(W, chalk.white('[<] BACK')));
|
|
224
|
-
|
|
225
|
-
drawBoxFooter(boxWidth);
|
|
226
|
-
|
|
227
|
-
const choice = await prompts.textInput(chalk.cyan('SELECT AGENT:'));
|
|
228
|
-
|
|
229
|
-
if (!choice || choice.trim() === '' || choice === '<' || choice?.toLowerCase() === 'b') {
|
|
230
|
-
return await aiAgentMenu();
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const index = parseInt(choice) - 1;
|
|
234
|
-
if (isNaN(index) || index < 0 || index >= agents.length) {
|
|
235
|
-
return await aiAgentMenu();
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return await selectModel(agents[index], aiAgentMenu);
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
/** Select agent to remove */
|
|
242
|
-
const selectAgentToRemove = async () => {
|
|
243
|
-
const agents = aiService.getAgents();
|
|
244
|
-
|
|
245
|
-
if (agents.length === 1) {
|
|
246
|
-
aiService.removeAgent(agents[0].id);
|
|
247
|
-
console.log(chalk.yellow(`\n ${agents[0].name} REMOVED`));
|
|
248
|
-
await prompts.waitForEnter();
|
|
249
|
-
return await aiAgentMenu();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const { boxWidth, W } = getBoxDimensions();
|
|
253
|
-
|
|
254
|
-
console.clear();
|
|
255
|
-
displayBanner();
|
|
256
|
-
drawBoxHeaderContinue('SELECT AGENT TO REMOVE', boxWidth);
|
|
257
|
-
|
|
258
|
-
for (let i = 0; i < agents.length; i++) {
|
|
259
|
-
const agent = agents[i];
|
|
260
|
-
const modelDisplay = agent.model ? chalk.gray(` (${agent.model})`) : '';
|
|
261
|
-
console.log(makeLine(W, chalk.white(`[${i + 1}] `) + chalk.red(agent.name) + modelDisplay));
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
console.log(makeLine(W, ''));
|
|
265
|
-
console.log(makeLine(W, chalk.white('[<] BACK')));
|
|
266
|
-
|
|
267
|
-
drawBoxFooter(boxWidth);
|
|
268
|
-
|
|
269
|
-
const choice = await prompts.textInput(chalk.cyan('SELECT AGENT TO REMOVE:'));
|
|
270
|
-
|
|
271
|
-
if (!choice || choice.trim() === '' || choice === '<' || choice?.toLowerCase() === 'b') {
|
|
272
|
-
return await aiAgentMenu();
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const index = parseInt(choice) - 1;
|
|
276
|
-
if (isNaN(index) || index < 0 || index >= agents.length) {
|
|
277
|
-
return await aiAgentMenu();
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const removedAgent = agents[index];
|
|
281
|
-
const modelInfo = removedAgent.model ? ` (${removedAgent.model})` : '';
|
|
282
|
-
aiService.removeAgent(removedAgent.id);
|
|
283
|
-
console.log(chalk.yellow(`\n ${removedAgent.name}${modelInfo} REMOVED`));
|
|
284
|
-
await prompts.waitForEnter();
|
|
285
|
-
return await aiAgentMenu();
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
/** Select provider category */
|
|
289
|
-
const selectCategory = async () => {
|
|
290
|
-
const { boxWidth, W } = getBoxDimensions();
|
|
291
|
-
|
|
292
|
-
console.clear();
|
|
293
|
-
displayBanner();
|
|
294
|
-
drawBoxHeaderContinue('SELECT PROVIDER TYPE', boxWidth);
|
|
295
|
-
|
|
296
|
-
const categories = getCategories();
|
|
297
|
-
|
|
298
|
-
console.log(make2ColRow(W,
|
|
299
|
-
chalk.cyan('[1]') + chalk.yellow(' UNIFIED (RECOMMENDED)'),
|
|
300
|
-
chalk.cyan('[2]') + chalk.yellow(' DIRECT PROVIDERS')
|
|
301
|
-
));
|
|
302
|
-
console.log(make2ColRow(W, chalk.white(' 1 API = 100+ models'), chalk.white(' Connect to each provider')));
|
|
303
|
-
console.log(makeLine(W, ''));
|
|
304
|
-
console.log(make2ColRow(W,
|
|
305
|
-
chalk.cyan('[3]') + chalk.yellow(' LOCAL (FREE)'),
|
|
306
|
-
chalk.cyan('[4]') + chalk.yellow(' CUSTOM')
|
|
307
|
-
));
|
|
308
|
-
console.log(make2ColRow(W, chalk.white(' Run on your machine'), chalk.white(' Self-hosted solutions')));
|
|
309
|
-
|
|
310
|
-
drawBoxFooter(boxWidth);
|
|
311
|
-
|
|
312
|
-
const choice = await prompts.textInput(chalk.cyan('SELECT (1-4):'));
|
|
313
|
-
|
|
314
|
-
if (!choice || choice.trim() === '' || choice === '<' || choice?.toLowerCase() === 'b') {
|
|
315
|
-
return await aiAgentMenu();
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const index = parseInt(choice) - 1;
|
|
319
|
-
if (isNaN(index) || index < 0 || index >= categories.length) {
|
|
320
|
-
return await aiAgentMenu();
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
return await selectProvider(categories[index].id);
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
/** Select AI provider from category */
|
|
327
|
-
const selectProvider = async (categoryId) => {
|
|
328
|
-
const { boxWidth, W } = getBoxDimensions();
|
|
329
|
-
const col1Width = Math.floor(W / 2);
|
|
330
|
-
|
|
331
|
-
console.clear();
|
|
332
|
-
displayBanner();
|
|
333
|
-
|
|
334
|
-
const categories = getCategories();
|
|
335
|
-
const category = categories.find(c => c.id === categoryId);
|
|
336
|
-
drawBoxHeaderContinue(category.name, boxWidth);
|
|
337
|
-
|
|
338
|
-
const providers = getProvidersByCategory(categoryId);
|
|
339
|
-
|
|
340
|
-
if (providers.length === 0) {
|
|
341
|
-
console.log(makeLine(W, chalk.white('NO PROVIDERS IN THIS CATEGORY')));
|
|
342
|
-
drawBoxFooter(boxWidth);
|
|
343
|
-
await prompts.waitForEnter();
|
|
344
|
-
return await selectCategory();
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// Display providers in 2 columns
|
|
348
|
-
for (let i = 0; i < providers.length; i += 2) {
|
|
349
|
-
const left = providers[i];
|
|
350
|
-
const right = providers[i + 1];
|
|
351
|
-
|
|
352
|
-
const leftNum = `[${i + 1}]`;
|
|
353
|
-
const rightNum = right ? `[${i + 2}]` : '';
|
|
354
|
-
const leftName = ` ${left.name}`;
|
|
355
|
-
const rightName = right ? ` ${right.name}` : '';
|
|
356
|
-
|
|
357
|
-
console.log(make2ColRow(W,
|
|
358
|
-
chalk.cyan(leftNum) + chalk.yellow(leftName.length > col1Width - leftNum.length - 3 ? leftName.substring(0, col1Width - leftNum.length - 6) + '...' : leftName),
|
|
359
|
-
right ? chalk.cyan(rightNum) + chalk.yellow(rightName.length > col1Width - rightNum.length - 3 ? rightName.substring(0, col1Width - rightNum.length - 6) + '...' : rightName) : ''
|
|
360
|
-
));
|
|
361
|
-
|
|
362
|
-
const leftDesc = ' ' + left.description;
|
|
363
|
-
const rightDesc = right ? ' ' + right.description : '';
|
|
364
|
-
|
|
365
|
-
console.log(make2ColRow(W,
|
|
366
|
-
chalk.white(leftDesc.length > col1Width - 3 ? leftDesc.substring(0, col1Width - 6) + '...' : leftDesc),
|
|
367
|
-
chalk.white(rightDesc.length > col1Width - 3 ? rightDesc.substring(0, col1Width - 6) + '...' : rightDesc)
|
|
368
|
-
));
|
|
369
|
-
|
|
370
|
-
console.log(makeLine(W, ''));
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
drawBoxFooter(boxWidth);
|
|
374
|
-
|
|
375
|
-
const choice = await prompts.textInput(chalk.cyan(`SELECT (1-${providers.length}):`));
|
|
376
|
-
|
|
377
|
-
if (!choice || choice.trim() === '' || choice === '<' || choice?.toLowerCase() === 'b') {
|
|
378
|
-
return await selectCategory();
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
const index = parseInt(choice) - 1;
|
|
382
|
-
if (isNaN(index) || index < 0 || index >= providers.length) {
|
|
383
|
-
return await selectCategory();
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
return await selectProviderOption(providers[index]);
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
/** Select connection option for provider */
|
|
390
|
-
const selectProviderOption = async (provider) => {
|
|
391
|
-
const { boxWidth, W } = getBoxDimensions();
|
|
392
|
-
const col1Width = Math.floor(W / 2);
|
|
393
|
-
|
|
394
|
-
// If only one option, skip selection
|
|
395
|
-
if (provider.options.length === 1) {
|
|
396
|
-
return await setupConnection(provider, provider.options[0]);
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
console.clear();
|
|
400
|
-
displayBanner();
|
|
401
|
-
drawBoxHeaderContinue(provider.name, boxWidth);
|
|
402
|
-
|
|
403
|
-
console.log(makeLine(W, chalk.white('SELECT CONNECTION METHOD:')));
|
|
404
|
-
console.log(makeLine(W, ''));
|
|
405
|
-
|
|
406
|
-
// Display options in 2 columns
|
|
407
|
-
for (let i = 0; i < provider.options.length; i += 2) {
|
|
408
|
-
const left = provider.options[i];
|
|
409
|
-
const right = provider.options[i + 1];
|
|
410
|
-
|
|
411
|
-
console.log(make2ColRow(W,
|
|
412
|
-
chalk.cyan(`[${i + 1}]`) + chalk.yellow(` ${left.label}`),
|
|
413
|
-
right ? chalk.cyan(`[${i + 2}]`) + chalk.yellow(` ${right.label}`) : ''
|
|
414
|
-
));
|
|
415
|
-
|
|
416
|
-
const leftDesc1 = left.description[0] ? ' ' + left.description[0] : '';
|
|
417
|
-
const rightDesc1 = right?.description[0] ? ' ' + right.description[0] : '';
|
|
418
|
-
console.log(make2ColRow(W,
|
|
419
|
-
chalk.white(leftDesc1.length > col1Width - 2 ? leftDesc1.substring(0, col1Width - 5) + '...' : leftDesc1),
|
|
420
|
-
chalk.white(rightDesc1.length > col1Width - 2 ? rightDesc1.substring(0, col1Width - 5) + '...' : rightDesc1)
|
|
421
|
-
));
|
|
422
|
-
|
|
423
|
-
const leftDesc2 = left.description[1] ? ' ' + left.description[1] : '';
|
|
424
|
-
const rightDesc2 = right?.description[1] ? ' ' + right.description[1] : '';
|
|
425
|
-
if (leftDesc2 || rightDesc2) {
|
|
426
|
-
console.log(make2ColRow(W,
|
|
427
|
-
chalk.white(leftDesc2.length > col1Width - 2 ? leftDesc2.substring(0, col1Width - 5) + '...' : leftDesc2),
|
|
428
|
-
chalk.white(rightDesc2.length > col1Width - 2 ? rightDesc2.substring(0, col1Width - 5) + '...' : rightDesc2)
|
|
429
|
-
));
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
console.log(makeLine(W, ''));
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
drawBoxFooter(boxWidth);
|
|
436
|
-
|
|
437
|
-
const choice = await prompts.textInput(chalk.cyan('SELECT:'));
|
|
438
|
-
|
|
439
|
-
if (!choice || choice.trim() === '' || choice === '<' || choice?.toLowerCase() === 'b') {
|
|
440
|
-
return await selectProvider(provider.category);
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
const index = parseInt(choice) - 1;
|
|
444
|
-
if (isNaN(index) || index < 0 || index >= provider.options.length) {
|
|
445
|
-
return await selectProvider(provider.category);
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
return await setupConnection(provider, provider.options[index]);
|
|
449
|
-
};
|
|
450
|
-
|
|
451
|
-
/** Setup connection with credentials */
|
|
452
|
-
const setupConnection = async (provider, option) => {
|
|
453
|
-
// Handle OAuth flow separately
|
|
454
|
-
if (option.authType === 'oauth') {
|
|
455
|
-
return await setupOAuthConnection(provider, selectProviderOption, selectModelFromList, aiAgentMenu);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// Collect credentials
|
|
459
|
-
const credentials = await collectCredentials(provider, option);
|
|
460
|
-
if (!credentials) {
|
|
461
|
-
return await selectProviderOption(provider);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
// Validate and fetch models
|
|
465
|
-
const result = await validateAndFetchModels(provider, option, credentials);
|
|
466
|
-
if (!result.valid) {
|
|
467
|
-
await prompts.waitForEnter();
|
|
468
|
-
return await selectProviderOption(provider);
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// Let user select a model
|
|
472
|
-
const selectedModel = await selectModelFromList(result.models, provider.name);
|
|
473
|
-
if (!selectedModel) {
|
|
474
|
-
return await selectProviderOption(provider);
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
// Add as new agent with selected model
|
|
478
|
-
await addConnectedAgent(provider, option, credentials, selectedModel);
|
|
479
|
-
|
|
480
|
-
await prompts.waitForEnter();
|
|
481
|
-
return await aiAgentMenu();
|
|
482
|
-
};
|
|
483
|
-
|
|
484
|
-
module.exports = { aiAgentMenu };
|