hedgequantx 2.7.28 → 2.7.29
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/pages/ai-agents.js +12 -6
- package/src/services/cliproxy/manager.js +34 -18
package/package.json
CHANGED
package/src/pages/ai-agents.js
CHANGED
|
@@ -11,12 +11,18 @@ const path = require('path');
|
|
|
11
11
|
const fs = require('fs');
|
|
12
12
|
const ora = require('ora');
|
|
13
13
|
|
|
14
|
-
const { getLogoWidth } = require('../ui');
|
|
14
|
+
const { getLogoWidth, displayBanner } = require('../ui');
|
|
15
15
|
const { prompts } = require('../utils');
|
|
16
16
|
const { fetchModelsFromApi } = require('./ai-models');
|
|
17
17
|
const { drawProvidersTable, drawModelsTable, drawProviderWindow } = require('./ai-agents-ui');
|
|
18
18
|
const cliproxy = require('../services/cliproxy');
|
|
19
19
|
|
|
20
|
+
/** Clear screen and show banner */
|
|
21
|
+
const clearWithBanner = () => {
|
|
22
|
+
console.clear();
|
|
23
|
+
displayBanner();
|
|
24
|
+
};
|
|
25
|
+
|
|
20
26
|
// Config file path
|
|
21
27
|
const CONFIG_DIR = path.join(os.homedir(), '.hqx');
|
|
22
28
|
const CONFIG_FILE = path.join(CONFIG_DIR, 'ai-config.json');
|
|
@@ -57,7 +63,7 @@ const saveConfig = (config) => {
|
|
|
57
63
|
/** Select a model from a pre-fetched list */
|
|
58
64
|
const selectModelFromList = async (provider, models, boxWidth) => {
|
|
59
65
|
while (true) {
|
|
60
|
-
|
|
66
|
+
clearWithBanner();
|
|
61
67
|
drawModelsTable(provider, models, boxWidth);
|
|
62
68
|
|
|
63
69
|
const input = await prompts.textInput(chalk.cyan('Select model: '));
|
|
@@ -216,7 +222,7 @@ const handleCliProxyConnection = async (provider, config, boxWidth) => {
|
|
|
216
222
|
|
|
217
223
|
/** Handle API Key connection */
|
|
218
224
|
const handleApiKeyConnection = async (provider, config) => {
|
|
219
|
-
|
|
225
|
+
clearWithBanner();
|
|
220
226
|
console.log(chalk.yellow(`\n Enter your ${provider.name} API key:`));
|
|
221
227
|
console.log(chalk.gray(' (Press Enter to cancel)\n'));
|
|
222
228
|
|
|
@@ -259,7 +265,7 @@ const handleProviderConfig = async (provider, config) => {
|
|
|
259
265
|
const boxWidth = getLogoWidth();
|
|
260
266
|
|
|
261
267
|
while (true) {
|
|
262
|
-
|
|
268
|
+
clearWithBanner();
|
|
263
269
|
drawProviderWindow(provider, config, boxWidth);
|
|
264
270
|
|
|
265
271
|
const input = await prompts.textInput(chalk.cyan('Select option: '));
|
|
@@ -313,7 +319,7 @@ const getActiveAgentCount = () => getActiveProvider() ? 1 : 0;
|
|
|
313
319
|
|
|
314
320
|
/** Show CLIProxy status */
|
|
315
321
|
const showCliProxyStatus = async () => {
|
|
316
|
-
|
|
322
|
+
clearWithBanner();
|
|
317
323
|
console.log(chalk.yellow('\n CLIProxyAPI Status\n'));
|
|
318
324
|
|
|
319
325
|
const installed = cliproxy.isInstalled();
|
|
@@ -337,7 +343,7 @@ const aiAgentsMenu = async () => {
|
|
|
337
343
|
const boxWidth = getLogoWidth();
|
|
338
344
|
|
|
339
345
|
while (true) {
|
|
340
|
-
|
|
346
|
+
clearWithBanner();
|
|
341
347
|
const status = await cliproxy.isRunning();
|
|
342
348
|
const statusText = status.running ? `localhost:${cliproxy.DEFAULT_PORT}` : 'Not running';
|
|
343
349
|
drawProvidersTable(AI_PROVIDERS, config, boxWidth, statusText);
|
|
@@ -388,48 +388,64 @@ const ensureRunning = async (onProgress = null) => {
|
|
|
388
388
|
/**
|
|
389
389
|
* Get OAuth login URL for a provider
|
|
390
390
|
* @param {string} provider - Provider ID (anthropic, openai, google, etc.)
|
|
391
|
-
* @returns {Promise<Object>} { success, url, error }
|
|
391
|
+
* @returns {Promise<Object>} { success, url, childProcess, error }
|
|
392
392
|
*/
|
|
393
393
|
const getLoginUrl = async (provider) => {
|
|
394
394
|
const providerFlags = {
|
|
395
|
-
anthropic: '
|
|
396
|
-
openai: '
|
|
397
|
-
google: '
|
|
398
|
-
qwen: '
|
|
395
|
+
anthropic: '-claude-login',
|
|
396
|
+
openai: '-codex-login',
|
|
397
|
+
google: '-gemini-login',
|
|
398
|
+
qwen: '-qwen-login'
|
|
399
399
|
};
|
|
400
400
|
|
|
401
401
|
const flag = providerFlags[provider];
|
|
402
402
|
if (!flag) {
|
|
403
|
-
return { success: false, url: null, error: 'Provider not supported for OAuth' };
|
|
403
|
+
return { success: false, url: null, childProcess: null, error: 'Provider not supported for OAuth' };
|
|
404
404
|
}
|
|
405
405
|
|
|
406
|
-
// For headless/VPS, use
|
|
406
|
+
// For headless/VPS, use -no-browser flag
|
|
407
407
|
return new Promise((resolve) => {
|
|
408
|
-
const args = [flag, '
|
|
408
|
+
const args = [flag, '-no-browser'];
|
|
409
409
|
const child = spawn(BINARY_PATH, args, {
|
|
410
|
-
cwd: INSTALL_DIR
|
|
411
|
-
env: { ...process.env, AUTH_DIR: AUTH_DIR }
|
|
410
|
+
cwd: INSTALL_DIR
|
|
412
411
|
});
|
|
413
412
|
|
|
414
413
|
let output = '';
|
|
414
|
+
let resolved = false;
|
|
415
|
+
|
|
416
|
+
const checkForUrl = () => {
|
|
417
|
+
if (resolved) return;
|
|
418
|
+
const urlMatch = output.match(/https?:\/\/[^\s]+/);
|
|
419
|
+
if (urlMatch) {
|
|
420
|
+
resolved = true;
|
|
421
|
+
// Return child process so caller can wait for auth completion
|
|
422
|
+
resolve({ success: true, url: urlMatch[0], childProcess: child, error: null });
|
|
423
|
+
}
|
|
424
|
+
};
|
|
415
425
|
|
|
416
426
|
child.stdout.on('data', (data) => {
|
|
417
427
|
output += data.toString();
|
|
428
|
+
checkForUrl();
|
|
418
429
|
});
|
|
419
430
|
|
|
420
431
|
child.stderr.on('data', (data) => {
|
|
421
432
|
output += data.toString();
|
|
433
|
+
checkForUrl();
|
|
422
434
|
});
|
|
423
435
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
resolve({ success: true, url: urlMatch[0], error: null });
|
|
429
|
-
} else {
|
|
430
|
-
resolve({ success: false, url: null, error: 'Could not get login URL' });
|
|
436
|
+
child.on('error', (err) => {
|
|
437
|
+
if (!resolved) {
|
|
438
|
+
resolved = true;
|
|
439
|
+
resolve({ success: false, url: null, childProcess: null, error: err.message });
|
|
431
440
|
}
|
|
432
|
-
}
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
child.on('close', (code) => {
|
|
444
|
+
if (!resolved) {
|
|
445
|
+
resolved = true;
|
|
446
|
+
resolve({ success: false, url: null, childProcess: null, error: `Process exited with code ${code}` });
|
|
447
|
+
}
|
|
448
|
+
});
|
|
433
449
|
});
|
|
434
450
|
};
|
|
435
451
|
|