@appkit/llamacpp-cli 1.8.0 → 1.10.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/CHANGELOG.md +58 -0
- package/README.md +249 -40
- package/dist/cli.js +154 -10
- package/dist/cli.js.map +1 -1
- package/dist/commands/completion.d.ts +9 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +83 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/monitor.js +1 -1
- package/dist/commands/monitor.js.map +1 -1
- package/dist/commands/ps.d.ts +1 -3
- package/dist/commands/ps.d.ts.map +1 -1
- package/dist/commands/ps.js +36 -115
- package/dist/commands/ps.js.map +1 -1
- package/dist/commands/router/config.d.ts +11 -0
- package/dist/commands/router/config.d.ts.map +1 -0
- package/dist/commands/router/config.js +100 -0
- package/dist/commands/router/config.js.map +1 -0
- package/dist/commands/router/logs.d.ts +12 -0
- package/dist/commands/router/logs.d.ts.map +1 -0
- package/dist/commands/router/logs.js +238 -0
- package/dist/commands/router/logs.js.map +1 -0
- package/dist/commands/router/restart.d.ts +2 -0
- package/dist/commands/router/restart.d.ts.map +1 -0
- package/dist/commands/router/restart.js +39 -0
- package/dist/commands/router/restart.js.map +1 -0
- package/dist/commands/router/start.d.ts +2 -0
- package/dist/commands/router/start.d.ts.map +1 -0
- package/dist/commands/router/start.js +60 -0
- package/dist/commands/router/start.js.map +1 -0
- package/dist/commands/router/status.d.ts +2 -0
- package/dist/commands/router/status.d.ts.map +1 -0
- package/dist/commands/router/status.js +116 -0
- package/dist/commands/router/status.js.map +1 -0
- package/dist/commands/router/stop.d.ts +2 -0
- package/dist/commands/router/stop.d.ts.map +1 -0
- package/dist/commands/router/stop.js +36 -0
- package/dist/commands/router/stop.js.map +1 -0
- package/dist/commands/tui.d.ts +2 -0
- package/dist/commands/tui.d.ts.map +1 -0
- package/dist/commands/tui.js +27 -0
- package/dist/commands/tui.js.map +1 -0
- package/dist/lib/completion.d.ts +5 -0
- package/dist/lib/completion.d.ts.map +1 -0
- package/dist/lib/completion.js +195 -0
- package/dist/lib/completion.js.map +1 -0
- package/dist/lib/model-downloader.d.ts +5 -1
- package/dist/lib/model-downloader.d.ts.map +1 -1
- package/dist/lib/model-downloader.js +53 -20
- package/dist/lib/model-downloader.js.map +1 -1
- package/dist/lib/router-logger.d.ts +61 -0
- package/dist/lib/router-logger.d.ts.map +1 -0
- package/dist/lib/router-logger.js +200 -0
- package/dist/lib/router-logger.js.map +1 -0
- package/dist/lib/router-manager.d.ts +103 -0
- package/dist/lib/router-manager.d.ts.map +1 -0
- package/dist/lib/router-manager.js +394 -0
- package/dist/lib/router-manager.js.map +1 -0
- package/dist/lib/router-server.d.ts +61 -0
- package/dist/lib/router-server.d.ts.map +1 -0
- package/dist/lib/router-server.js +485 -0
- package/dist/lib/router-server.js.map +1 -0
- package/dist/tui/ConfigApp.d.ts +7 -0
- package/dist/tui/ConfigApp.d.ts.map +1 -0
- package/dist/tui/ConfigApp.js +1002 -0
- package/dist/tui/ConfigApp.js.map +1 -0
- package/dist/tui/HistoricalMonitorApp.d.ts.map +1 -1
- package/dist/tui/HistoricalMonitorApp.js +85 -49
- package/dist/tui/HistoricalMonitorApp.js.map +1 -1
- package/dist/tui/ModelsApp.d.ts +7 -0
- package/dist/tui/ModelsApp.d.ts.map +1 -0
- package/dist/tui/ModelsApp.js +362 -0
- package/dist/tui/ModelsApp.js.map +1 -0
- package/dist/tui/MultiServerMonitorApp.d.ts +6 -1
- package/dist/tui/MultiServerMonitorApp.d.ts.map +1 -1
- package/dist/tui/MultiServerMonitorApp.js +1038 -122
- package/dist/tui/MultiServerMonitorApp.js.map +1 -1
- package/dist/tui/RootNavigator.d.ts +7 -0
- package/dist/tui/RootNavigator.d.ts.map +1 -0
- package/dist/tui/RootNavigator.js +55 -0
- package/dist/tui/RootNavigator.js.map +1 -0
- package/dist/tui/SearchApp.d.ts +6 -0
- package/dist/tui/SearchApp.d.ts.map +1 -0
- package/dist/tui/SearchApp.js +451 -0
- package/dist/tui/SearchApp.js.map +1 -0
- package/dist/tui/SplashScreen.d.ts +16 -0
- package/dist/tui/SplashScreen.d.ts.map +1 -0
- package/dist/tui/SplashScreen.js +129 -0
- package/dist/tui/SplashScreen.js.map +1 -0
- package/dist/types/router-config.d.ts +19 -0
- package/dist/types/router-config.d.ts.map +1 -0
- package/dist/types/router-config.js +3 -0
- package/dist/types/router-config.js.map +1 -0
- package/package.json +1 -1
- package/src/cli.ts +121 -10
- package/src/commands/monitor.ts +1 -1
- package/src/commands/ps.ts +44 -133
- package/src/commands/router/config.ts +116 -0
- package/src/commands/router/logs.ts +256 -0
- package/src/commands/router/restart.ts +36 -0
- package/src/commands/router/start.ts +60 -0
- package/src/commands/router/status.ts +119 -0
- package/src/commands/router/stop.ts +33 -0
- package/src/commands/tui.ts +25 -0
- package/src/lib/model-downloader.ts +57 -20
- package/src/lib/router-logger.ts +201 -0
- package/src/lib/router-manager.ts +414 -0
- package/src/lib/router-server.ts +538 -0
- package/src/tui/ConfigApp.ts +1085 -0
- package/src/tui/HistoricalMonitorApp.ts +88 -49
- package/src/tui/ModelsApp.ts +368 -0
- package/src/tui/MultiServerMonitorApp.ts +1163 -122
- package/src/tui/RootNavigator.ts +74 -0
- package/src/tui/SearchApp.ts +511 -0
- package/src/tui/SplashScreen.ts +149 -0
- package/src/types/router-config.ts +25 -0
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -19,6 +19,12 @@ import { serverShowCommand } from './commands/server-show';
|
|
|
19
19
|
import { serverConfigCommand } from './commands/config';
|
|
20
20
|
import { configGlobalCommand } from './commands/config-global';
|
|
21
21
|
import { monitorCommand } from './commands/monitor';
|
|
22
|
+
import { routerStartCommand } from './commands/router/start';
|
|
23
|
+
import { routerStopCommand } from './commands/router/stop';
|
|
24
|
+
import { routerStatusCommand } from './commands/router/status';
|
|
25
|
+
import { routerRestartCommand } from './commands/router/restart';
|
|
26
|
+
import { routerConfigCommand } from './commands/router/config';
|
|
27
|
+
import { routerLogsCommand } from './commands/router/logs';
|
|
22
28
|
import packageJson from '../package.json';
|
|
23
29
|
|
|
24
30
|
const program = new Command();
|
|
@@ -26,7 +32,17 @@ const program = new Command();
|
|
|
26
32
|
program
|
|
27
33
|
.name('llamacpp')
|
|
28
34
|
.description('CLI tool to manage local llama.cpp servers on macOS')
|
|
29
|
-
.version(packageJson.version, '-v, --version', 'Output the version number')
|
|
35
|
+
.version(packageJson.version, '-v, --version', 'Output the version number')
|
|
36
|
+
.action(async () => {
|
|
37
|
+
// Default action: launch TUI when no command provided
|
|
38
|
+
try {
|
|
39
|
+
const { tuiCommand } = await import('./commands/tui');
|
|
40
|
+
await tuiCommand();
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error(chalk.red('❌ Error:'), (error as Error).message);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
30
46
|
|
|
31
47
|
// List models
|
|
32
48
|
program
|
|
@@ -41,14 +57,13 @@ program
|
|
|
41
57
|
}
|
|
42
58
|
});
|
|
43
59
|
|
|
44
|
-
// List
|
|
60
|
+
// List servers (static table)
|
|
45
61
|
program
|
|
46
|
-
.command('ps
|
|
47
|
-
.description('
|
|
48
|
-
.
|
|
49
|
-
.action(async (identifier?: string, options?: { table?: boolean }) => {
|
|
62
|
+
.command('ps')
|
|
63
|
+
.description('List all servers with status (static table)')
|
|
64
|
+
.action(async () => {
|
|
50
65
|
try {
|
|
51
|
-
await psCommand(
|
|
66
|
+
await psCommand();
|
|
52
67
|
} catch (error) {
|
|
53
68
|
console.error(chalk.red('❌ Error:'), (error as Error).message);
|
|
54
69
|
process.exit(1);
|
|
@@ -293,14 +308,14 @@ server
|
|
|
293
308
|
}
|
|
294
309
|
});
|
|
295
310
|
|
|
296
|
-
// Monitor server (deprecated - redirects to
|
|
311
|
+
// Monitor server (deprecated - redirects to TUI)
|
|
297
312
|
server
|
|
298
313
|
.command('monitor [identifier]')
|
|
299
|
-
.description('Monitor server with real-time metrics TUI (deprecated: use "llamacpp
|
|
314
|
+
.description('Monitor server with real-time metrics TUI (deprecated: use "llamacpp" instead)')
|
|
300
315
|
.action(async (identifier?: string) => {
|
|
301
316
|
try {
|
|
302
317
|
console.log(chalk.yellow('⚠️ The "monitor" command is deprecated and will be removed in a future version.'));
|
|
303
|
-
console.log(chalk.dim(' Please use "llamacpp
|
|
318
|
+
console.log(chalk.dim(' Please use "llamacpp" instead for the same functionality.\n'));
|
|
304
319
|
await monitorCommand(identifier);
|
|
305
320
|
} catch (error) {
|
|
306
321
|
console.error(chalk.red('❌ Error:'), (error as Error).message);
|
|
@@ -308,5 +323,101 @@ server
|
|
|
308
323
|
}
|
|
309
324
|
});
|
|
310
325
|
|
|
326
|
+
// Router management commands
|
|
327
|
+
const router = program
|
|
328
|
+
.command('router')
|
|
329
|
+
.description('Manage the unified router endpoint');
|
|
330
|
+
|
|
331
|
+
// Start router
|
|
332
|
+
router
|
|
333
|
+
.command('start')
|
|
334
|
+
.description('Start the router service')
|
|
335
|
+
.action(async () => {
|
|
336
|
+
try {
|
|
337
|
+
await routerStartCommand();
|
|
338
|
+
} catch (error) {
|
|
339
|
+
console.error(chalk.red('❌ Error:'), (error as Error).message);
|
|
340
|
+
process.exit(1);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// Stop router
|
|
345
|
+
router
|
|
346
|
+
.command('stop')
|
|
347
|
+
.description('Stop the router service')
|
|
348
|
+
.action(async () => {
|
|
349
|
+
try {
|
|
350
|
+
await routerStopCommand();
|
|
351
|
+
} catch (error) {
|
|
352
|
+
console.error(chalk.red('❌ Error:'), (error as Error).message);
|
|
353
|
+
process.exit(1);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
// Show router status
|
|
358
|
+
router
|
|
359
|
+
.command('status')
|
|
360
|
+
.description('Show router status and configuration')
|
|
361
|
+
.action(async () => {
|
|
362
|
+
try {
|
|
363
|
+
await routerStatusCommand();
|
|
364
|
+
} catch (error) {
|
|
365
|
+
console.error(chalk.red('❌ Error:'), (error as Error).message);
|
|
366
|
+
process.exit(1);
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
// Restart router
|
|
371
|
+
router
|
|
372
|
+
.command('restart')
|
|
373
|
+
.description('Restart the router service')
|
|
374
|
+
.action(async () => {
|
|
375
|
+
try {
|
|
376
|
+
await routerRestartCommand();
|
|
377
|
+
} catch (error) {
|
|
378
|
+
console.error(chalk.red('❌ Error:'), (error as Error).message);
|
|
379
|
+
process.exit(1);
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// Configure router
|
|
384
|
+
router
|
|
385
|
+
.command('config')
|
|
386
|
+
.description('Update router configuration')
|
|
387
|
+
.option('-p, --port <number>', 'Update port number', parseInt)
|
|
388
|
+
.option('-h, --host <address>', 'Update bind address')
|
|
389
|
+
.option('--timeout <ms>', 'Update request timeout (milliseconds)', parseInt)
|
|
390
|
+
.option('--health-interval <ms>', 'Update health check interval (milliseconds)', parseInt)
|
|
391
|
+
.option('-v, --verbose [boolean]', 'Enable/disable verbose logging to file (true/false)', (val) => val === 'true' || val === '1')
|
|
392
|
+
.option('-r, --restart', 'Automatically restart router if running')
|
|
393
|
+
.action(async (options) => {
|
|
394
|
+
try {
|
|
395
|
+
await routerConfigCommand(options);
|
|
396
|
+
} catch (error) {
|
|
397
|
+
console.error(chalk.red('❌ Error:'), (error as Error).message);
|
|
398
|
+
process.exit(1);
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
// Router logs
|
|
403
|
+
router
|
|
404
|
+
.command('logs')
|
|
405
|
+
.description('View router logs')
|
|
406
|
+
.option('-f, --follow', 'Follow logs in real-time (like tail -f)')
|
|
407
|
+
.option('-n, --lines <number>', 'Number of lines to show (default: 50)', parseInt)
|
|
408
|
+
.option('--stderr', 'Show system logs (stderr) instead of activity logs (stdout)')
|
|
409
|
+
.option('-v, --verbose', 'Show verbose JSON log file (if enabled)')
|
|
410
|
+
.option('--clear', 'Clear the log file')
|
|
411
|
+
.option('--rotate', 'Rotate the log file with timestamp')
|
|
412
|
+
.option('--clear-all', 'Clear all router logs (activity, system, verbose)')
|
|
413
|
+
.action(async (options) => {
|
|
414
|
+
try {
|
|
415
|
+
await routerLogsCommand(options);
|
|
416
|
+
} catch (error) {
|
|
417
|
+
console.error(chalk.red('❌ Error:'), (error as Error).message);
|
|
418
|
+
process.exit(1);
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
|
|
311
422
|
// Parse arguments
|
|
312
423
|
program.parse();
|
package/src/commands/monitor.ts
CHANGED
|
@@ -31,7 +31,7 @@ export async function monitorCommand(identifier?: string): Promise<void> {
|
|
|
31
31
|
screen.destroy();
|
|
32
32
|
throw new Error(
|
|
33
33
|
`Server not found: ${identifier}\n\n` +
|
|
34
|
-
`Use: llamacpp ps\n` +
|
|
34
|
+
`Use: llamacpp ps (to list servers)\n` +
|
|
35
35
|
`Or create a new server: llamacpp server create <model>`
|
|
36
36
|
);
|
|
37
37
|
}
|
package/src/commands/ps.ts
CHANGED
|
@@ -1,14 +1,32 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import Table from 'cli-table3';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { getProcessMemory } from '../utils/process-utils';
|
|
8
|
-
import { createMultiServerMonitorUI } from '../tui/MultiServerMonitorApp.js';
|
|
3
|
+
import { stateManager } from '../lib/state-manager.js';
|
|
4
|
+
import { statusChecker } from '../lib/status-checker.js';
|
|
5
|
+
import { formatUptime, formatBytes } from '../utils/format-utils.js';
|
|
6
|
+
import { getProcessMemory } from '../utils/process-utils.js';
|
|
9
7
|
import { ServerConfig } from '../types/server-config.js';
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
const STATUS_CONFIG = {
|
|
10
|
+
running: { text: '✅ RUNNING', color: chalk.green },
|
|
11
|
+
crashed: { text: '❌ CRASHED', color: chalk.red },
|
|
12
|
+
stopped: { text: '⚠️ STOPPED', color: chalk.yellow },
|
|
13
|
+
} as const;
|
|
14
|
+
|
|
15
|
+
async function getServerMemory(server: ServerConfig): Promise<string> {
|
|
16
|
+
if (server.status !== 'running' || !server.pid) {
|
|
17
|
+
return '-';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const cpuMemoryBytes = await getProcessMemory(server.pid);
|
|
21
|
+
if (cpuMemoryBytes === null) {
|
|
22
|
+
return '-';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const metalMemoryBytes = server.metalMemoryMB ? server.metalMemoryMB * 1024 * 1024 : 0;
|
|
26
|
+
return formatBytes(cpuMemoryBytes + metalMemoryBytes);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function psCommand(): Promise<void> {
|
|
12
30
|
const servers = await stateManager.getAllServers();
|
|
13
31
|
|
|
14
32
|
if (servers.length === 0) {
|
|
@@ -17,60 +35,31 @@ async function showStaticTable(): Promise<void> {
|
|
|
17
35
|
return;
|
|
18
36
|
}
|
|
19
37
|
|
|
20
|
-
// Update all server statuses
|
|
21
38
|
console.log(chalk.dim('Checking server statuses...\n'));
|
|
22
|
-
const
|
|
39
|
+
const serversWithStatus = await statusChecker.updateAllServerStatuses();
|
|
23
40
|
|
|
24
41
|
const table = new Table({
|
|
25
42
|
head: ['SERVER ID', 'MODEL', 'PORT', 'STATUS', 'PID', 'MEMORY', 'UPTIME'],
|
|
26
43
|
});
|
|
27
44
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
runningCount++;
|
|
41
|
-
break;
|
|
42
|
-
case 'crashed':
|
|
43
|
-
statusText = '❌ CRASHED';
|
|
44
|
-
statusColor = chalk.red;
|
|
45
|
-
crashedCount++;
|
|
46
|
-
break;
|
|
47
|
-
default:
|
|
48
|
-
statusText = '⚠️ STOPPED';
|
|
49
|
-
statusColor = chalk.yellow;
|
|
50
|
-
stoppedCount++;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const uptime =
|
|
54
|
-
server.status === 'running' && server.lastStarted
|
|
55
|
-
? formatUptime(server.lastStarted)
|
|
56
|
-
: '-';
|
|
57
|
-
|
|
58
|
-
// Get memory usage for running servers (CPU + Metal GPU memory)
|
|
59
|
-
let memoryText = '-';
|
|
60
|
-
if (server.status === 'running' && server.pid) {
|
|
61
|
-
const cpuMemoryBytes = await getProcessMemory(server.pid);
|
|
62
|
-
if (cpuMemoryBytes !== null) {
|
|
63
|
-
const metalMemoryBytes = server.metalMemoryMB ? server.metalMemoryMB * 1024 * 1024 : 0;
|
|
64
|
-
const totalMemoryBytes = cpuMemoryBytes + metalMemoryBytes;
|
|
65
|
-
memoryText = formatBytes(totalMemoryBytes);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
45
|
+
const counts = { running: 0, stopped: 0, crashed: 0 };
|
|
46
|
+
|
|
47
|
+
for (const server of serversWithStatus) {
|
|
48
|
+
const status = server.status || 'stopped';
|
|
49
|
+
const config = STATUS_CONFIG[status] || STATUS_CONFIG.stopped;
|
|
50
|
+
counts[status]++;
|
|
51
|
+
|
|
52
|
+
const uptime = server.status === 'running' && server.lastStarted
|
|
53
|
+
? formatUptime(server.lastStarted)
|
|
54
|
+
: '-';
|
|
55
|
+
|
|
56
|
+
const memoryText = await getServerMemory(server);
|
|
68
57
|
|
|
69
58
|
table.push([
|
|
70
59
|
server.id,
|
|
71
60
|
server.modelName,
|
|
72
61
|
server.port.toString(),
|
|
73
|
-
|
|
62
|
+
config.color(config.text),
|
|
74
63
|
server.pid?.toString() || '-',
|
|
75
64
|
memoryText,
|
|
76
65
|
uptime,
|
|
@@ -80,94 +69,16 @@ async function showStaticTable(): Promise<void> {
|
|
|
80
69
|
console.log(table.toString());
|
|
81
70
|
|
|
82
71
|
const summary = [
|
|
83
|
-
chalk.green(`${
|
|
84
|
-
chalk.yellow(`${
|
|
72
|
+
chalk.green(`${counts.running} running`),
|
|
73
|
+
chalk.yellow(`${counts.stopped} stopped`),
|
|
85
74
|
];
|
|
86
|
-
if (
|
|
87
|
-
summary.push(chalk.red(`${
|
|
75
|
+
if (counts.crashed > 0) {
|
|
76
|
+
summary.push(chalk.red(`${counts.crashed} crashed`));
|
|
88
77
|
}
|
|
89
78
|
|
|
90
79
|
console.log(chalk.dim(`\nTotal: ${servers.length} servers (${summary.join(', ')})`));
|
|
91
80
|
|
|
92
|
-
if (
|
|
81
|
+
if (counts.crashed > 0) {
|
|
93
82
|
console.log(chalk.red('\n⚠️ Some servers have crashed. Check logs with: llamacpp server logs <id> --errors'));
|
|
94
83
|
}
|
|
95
84
|
}
|
|
96
|
-
|
|
97
|
-
export async function psCommand(identifier?: string, options?: { table?: boolean }): Promise<void> {
|
|
98
|
-
// If --table flag is set, show static table (backward compatibility)
|
|
99
|
-
if (options?.table) {
|
|
100
|
-
await showStaticTable();
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Get all servers and update their statuses
|
|
105
|
-
const servers = await stateManager.getAllServers();
|
|
106
|
-
|
|
107
|
-
if (servers.length === 0) {
|
|
108
|
-
console.log(chalk.yellow('No servers configured.'));
|
|
109
|
-
console.log(chalk.dim('\nCreate a server: llamacpp server create <model-filename>'));
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Update all server statuses
|
|
114
|
-
const updated = await statusChecker.updateAllServerStatuses();
|
|
115
|
-
|
|
116
|
-
// If identifier is provided, find the server and jump to detail view
|
|
117
|
-
if (identifier) {
|
|
118
|
-
const server = await findServer(identifier, updated);
|
|
119
|
-
if (!server) {
|
|
120
|
-
console.log(chalk.red(`❌ Server not found: ${identifier}`));
|
|
121
|
-
console.log(chalk.dim('\nAvailable servers:'));
|
|
122
|
-
updated.forEach((s: ServerConfig) => {
|
|
123
|
-
console.log(chalk.dim(` - ${s.id} (port ${s.port})`));
|
|
124
|
-
});
|
|
125
|
-
process.exit(1);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Find the server index for direct jump
|
|
129
|
-
const serverIndex = updated.findIndex(s => s.id === server.id);
|
|
130
|
-
|
|
131
|
-
// Launch multi-server TUI with direct jump to detail view
|
|
132
|
-
const screen = blessed.screen({
|
|
133
|
-
smartCSR: true,
|
|
134
|
-
title: 'llama.cpp Multi-Server Monitor',
|
|
135
|
-
fullUnicode: true,
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
await createMultiServerMonitorUI(screen, updated, true, serverIndex); // fromPs = true, directJumpIndex
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// No identifier - launch multi-server TUI
|
|
143
|
-
const runningServers = updated.filter((s: ServerConfig) => s.status === 'running');
|
|
144
|
-
|
|
145
|
-
// Launch multi-server TUI (shows all servers, not just running ones)
|
|
146
|
-
const screen = blessed.screen({
|
|
147
|
-
smartCSR: true,
|
|
148
|
-
title: 'llama.cpp Multi-Server Monitor',
|
|
149
|
-
fullUnicode: true,
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
await createMultiServerMonitorUI(screen, updated, true); // fromPs = true
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Helper function to find server by identifier
|
|
156
|
-
async function findServer(identifier: string, servers: ServerConfig[]): Promise<ServerConfig | null> {
|
|
157
|
-
// Try by port
|
|
158
|
-
const port = parseInt(identifier);
|
|
159
|
-
if (!isNaN(port)) {
|
|
160
|
-
const server = servers.find(s => s.port === port);
|
|
161
|
-
if (server) return server;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Try by exact ID
|
|
165
|
-
const byId = servers.find(s => s.id === identifier);
|
|
166
|
-
if (byId) return byId;
|
|
167
|
-
|
|
168
|
-
// Try by partial model name
|
|
169
|
-
const byModel = servers.find(s => s.modelName.toLowerCase().includes(identifier.toLowerCase()));
|
|
170
|
-
if (byModel) return byModel;
|
|
171
|
-
|
|
172
|
-
return null;
|
|
173
|
-
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { routerManager } from '../../lib/router-manager';
|
|
3
|
+
|
|
4
|
+
interface ConfigOptions {
|
|
5
|
+
port?: number;
|
|
6
|
+
host?: string;
|
|
7
|
+
timeout?: number;
|
|
8
|
+
healthInterval?: number;
|
|
9
|
+
verbose?: boolean;
|
|
10
|
+
restart?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function routerConfigCommand(options: ConfigOptions): Promise<void> {
|
|
14
|
+
try {
|
|
15
|
+
// Check if router exists
|
|
16
|
+
const config = await routerManager.loadConfig();
|
|
17
|
+
if (!config) {
|
|
18
|
+
throw new Error('Router configuration not found. Use "llamacpp router start" to create it.');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Check if any options were provided
|
|
22
|
+
const hasOptions = options.port || options.host || options.timeout || options.healthInterval || options.verbose !== undefined;
|
|
23
|
+
if (!hasOptions) {
|
|
24
|
+
throw new Error('No configuration options provided. Use --port, --host, --timeout, --health-interval, or --verbose');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const isRunning = config.status === 'running';
|
|
28
|
+
|
|
29
|
+
// Warn if running and no restart flag
|
|
30
|
+
if (isRunning && !options.restart) {
|
|
31
|
+
console.log(chalk.yellow('⚠️ Router is running. Changes will take effect after restart.'));
|
|
32
|
+
console.log(chalk.dim(' Use --restart flag to apply changes immediately.\n'));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Prepare updates
|
|
36
|
+
const updates: any = {};
|
|
37
|
+
const changes: string[] = [];
|
|
38
|
+
|
|
39
|
+
if (options.port !== undefined) {
|
|
40
|
+
changes.push(`Port: ${config.port} → ${options.port}`);
|
|
41
|
+
updates.port = options.port;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (options.host !== undefined) {
|
|
45
|
+
changes.push(`Host: ${config.host} → ${options.host}`);
|
|
46
|
+
updates.host = options.host;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (options.timeout !== undefined) {
|
|
50
|
+
changes.push(`Request Timeout: ${config.requestTimeout}ms → ${options.timeout}ms`);
|
|
51
|
+
updates.requestTimeout = options.timeout;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (options.healthInterval !== undefined) {
|
|
55
|
+
changes.push(`Health Check Interval: ${config.healthCheckInterval}ms → ${options.healthInterval}ms`);
|
|
56
|
+
updates.healthCheckInterval = options.healthInterval;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (options.verbose !== undefined) {
|
|
60
|
+
const verboseStr = (val: boolean) => val ? 'enabled' : 'disabled';
|
|
61
|
+
changes.push(`Verbose Logging: ${verboseStr(config.verbose)} → ${verboseStr(options.verbose)}`);
|
|
62
|
+
updates.verbose = options.verbose;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Display changes
|
|
66
|
+
console.log(chalk.blue('📝 Configuration changes:'));
|
|
67
|
+
console.log();
|
|
68
|
+
changes.forEach(change => {
|
|
69
|
+
console.log(chalk.dim(` ${change}`));
|
|
70
|
+
});
|
|
71
|
+
console.log();
|
|
72
|
+
|
|
73
|
+
// Apply changes
|
|
74
|
+
if (isRunning && options.restart) {
|
|
75
|
+
console.log(chalk.blue('⏹️ Stopping router...'));
|
|
76
|
+
await routerManager.stop();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Update config
|
|
80
|
+
await routerManager.updateConfig(updates);
|
|
81
|
+
|
|
82
|
+
// Regenerate plist if port or host changed
|
|
83
|
+
if (options.port !== undefined || options.host !== undefined) {
|
|
84
|
+
const updatedConfig = await routerManager.loadConfig();
|
|
85
|
+
if (updatedConfig) {
|
|
86
|
+
await routerManager.createPlist(updatedConfig);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Restart if requested
|
|
91
|
+
if (isRunning && options.restart) {
|
|
92
|
+
console.log(chalk.blue('▶️ Starting router...'));
|
|
93
|
+
await routerManager.start();
|
|
94
|
+
|
|
95
|
+
const finalConfig = await routerManager.loadConfig();
|
|
96
|
+
console.log();
|
|
97
|
+
console.log(chalk.green('✅ Router restarted with new configuration'));
|
|
98
|
+
console.log();
|
|
99
|
+
console.log(chalk.dim(`Endpoint: http://${finalConfig?.host}:${finalConfig?.port}`));
|
|
100
|
+
} else {
|
|
101
|
+
console.log(chalk.green('✅ Configuration updated'));
|
|
102
|
+
|
|
103
|
+
if (isRunning) {
|
|
104
|
+
console.log();
|
|
105
|
+
console.log(chalk.yellow('⚠️ Restart required to apply changes:'));
|
|
106
|
+
console.log(chalk.dim(' llamacpp router restart'));
|
|
107
|
+
} else {
|
|
108
|
+
console.log();
|
|
109
|
+
console.log(chalk.dim('Start router to use new configuration:'));
|
|
110
|
+
console.log(chalk.dim(' llamacpp router start'));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} catch (error) {
|
|
114
|
+
throw new Error(`Failed to update router configuration: ${(error as Error).message}`);
|
|
115
|
+
}
|
|
116
|
+
}
|