@appkit/llamacpp-cli 1.9.0 → 1.10.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/CHANGELOG.md +28 -0
- package/README.md +171 -42
- package/dist/cli.js +75 -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 +1 -0
- package/dist/commands/router/config.d.ts.map +1 -1
- package/dist/commands/router/config.js +7 -2
- package/dist/commands/router/config.js.map +1 -1
- 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/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.map +1 -1
- package/dist/lib/router-manager.js +1 -0
- package/dist/lib/router-manager.js.map +1 -1
- package/dist/lib/router-server.d.ts +9 -0
- package/dist/lib/router-server.d.ts.map +1 -1
- package/dist/lib/router-server.js +169 -57
- package/dist/lib/router-server.js.map +1 -1
- 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 +1 -0
- package/dist/types/router-config.d.ts.map +1 -1
- package/dist/utils/log-parser.d.ts +14 -1
- package/dist/utils/log-parser.d.ts.map +1 -1
- package/dist/utils/log-parser.js +57 -26
- package/dist/utils/log-parser.js.map +1 -1
- package/package.json +1 -1
- package/src/cli.ts +41 -10
- package/src/commands/monitor.ts +1 -1
- package/src/commands/ps.ts +44 -133
- package/src/commands/router/config.ts +9 -2
- package/src/commands/router/logs.ts +256 -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 +1 -0
- package/src/lib/router-server.ts +193 -62
- 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 +1 -0
- package/src/utils/log-parser.ts +61 -25
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
export declare class LogParser {
|
|
5
5
|
private buffer;
|
|
6
6
|
private isBuffering;
|
|
7
|
+
/**
|
|
8
|
+
* Check if line is a request status line (contains method/endpoint/status, no JSON)
|
|
9
|
+
* Handles both old and new formats:
|
|
10
|
+
* - Old: log_server_r: request: POST /v1/chat/completions 127.0.0.1 200
|
|
11
|
+
* - New: log_server_r: done request: POST /v1/messages 172.16.0.114 200
|
|
12
|
+
*/
|
|
13
|
+
private isRequestStatusLine;
|
|
7
14
|
/**
|
|
8
15
|
* Process log lines and output compact format
|
|
9
16
|
*/
|
|
@@ -15,11 +22,14 @@ export declare class LogParser {
|
|
|
15
22
|
flush(callback: (compactLine: string) => void): void;
|
|
16
23
|
/**
|
|
17
24
|
* Parse simple single-line format (non-verbose mode)
|
|
18
|
-
*
|
|
25
|
+
* Handles both old and new formats:
|
|
26
|
+
* - Old: srv log_server_r: request: POST /v1/chat/completions 127.0.0.1 200
|
|
27
|
+
* - New: srv log_server_r: done request: POST /v1/messages 172.16.0.114 200
|
|
19
28
|
*/
|
|
20
29
|
private parseSimpleFormat;
|
|
21
30
|
/**
|
|
22
31
|
* Consolidate buffered request/response lines into single line
|
|
32
|
+
* Handles both old and new llama.cpp log formats
|
|
23
33
|
*/
|
|
24
34
|
private consolidateRequest;
|
|
25
35
|
/**
|
|
@@ -32,6 +42,9 @@ export declare class LogParser {
|
|
|
32
42
|
private extractJson;
|
|
33
43
|
/**
|
|
34
44
|
* Extract first user message from request JSON
|
|
45
|
+
* Handles both string content and array content formats:
|
|
46
|
+
* - String: {"role":"user","content":"Hello"}
|
|
47
|
+
* - Array: {"role":"user","content":[{"type":"text","text":"Hello"}]}
|
|
35
48
|
*/
|
|
36
49
|
private extractUserMessage;
|
|
37
50
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-parser.d.ts","sourceRoot":"","sources":["../../src/utils/log-parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,WAAW,CAAS;IAE5B;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAsCxE;;;OAGG;IACH,KAAK,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAcpD
|
|
1
|
+
{"version":3,"file":"log-parser.d.ts","sourceRoot":"","sources":["../../src/utils/log-parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,WAAW,CAAS;IAE5B;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAQ3B;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAsCxE;;;OAGG;IACH,KAAK,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAcpD;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAgBzB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAsD1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;IACH,OAAO,CAAC,WAAW;IAYnB;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAoB1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAoB3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAa1B;AAGD,eAAO,MAAM,SAAS,WAAkB,CAAC"}
|
package/dist/utils/log-parser.js
CHANGED
|
@@ -9,13 +9,24 @@ class LogParser {
|
|
|
9
9
|
this.buffer = [];
|
|
10
10
|
this.isBuffering = false;
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Check if line is a request status line (contains method/endpoint/status, no JSON)
|
|
14
|
+
* Handles both old and new formats:
|
|
15
|
+
* - Old: log_server_r: request: POST /v1/chat/completions 127.0.0.1 200
|
|
16
|
+
* - New: log_server_r: done request: POST /v1/messages 172.16.0.114 200
|
|
17
|
+
*/
|
|
18
|
+
isRequestStatusLine(line) {
|
|
19
|
+
return ((line.includes('log_server_r: request:') || line.includes('log_server_r: done request:')) &&
|
|
20
|
+
!line.includes('{') &&
|
|
21
|
+
/(?:done )?request: (POST|GET|PUT|DELETE)/.test(line));
|
|
22
|
+
}
|
|
12
23
|
/**
|
|
13
24
|
* Process log lines and output compact format
|
|
14
25
|
*/
|
|
15
26
|
processLine(line, callback) {
|
|
16
|
-
// Check if this is a
|
|
17
|
-
//
|
|
18
|
-
if (
|
|
27
|
+
// Check if this is a request status line (no JSON, has method/endpoint/status)
|
|
28
|
+
// Handles both old format (request:) and new format (done request:)
|
|
29
|
+
if (this.isRequestStatusLine(line)) {
|
|
19
30
|
// Check if this is the start of verbose format (status line before JSON)
|
|
20
31
|
// or a simple single-line log
|
|
21
32
|
if (this.isBuffering) {
|
|
@@ -65,12 +76,15 @@ class LogParser {
|
|
|
65
76
|
}
|
|
66
77
|
/**
|
|
67
78
|
* Parse simple single-line format (non-verbose mode)
|
|
68
|
-
*
|
|
79
|
+
* Handles both old and new formats:
|
|
80
|
+
* - Old: srv log_server_r: request: POST /v1/chat/completions 127.0.0.1 200
|
|
81
|
+
* - New: srv log_server_r: done request: POST /v1/messages 172.16.0.114 200
|
|
69
82
|
*/
|
|
70
83
|
parseSimpleFormat(line) {
|
|
71
84
|
try {
|
|
72
85
|
const timestamp = this.extractTimestamp(line);
|
|
73
|
-
|
|
86
|
+
// Match both "request:" and "done request:" formats
|
|
87
|
+
const requestMatch = line.match(/(?:done )?request: (POST|GET|PUT|DELETE) ([^\s]+) ([^\s]+) (\d+)/);
|
|
74
88
|
if (!requestMatch)
|
|
75
89
|
return null;
|
|
76
90
|
const [, method, endpoint, ip, status] = requestMatch;
|
|
@@ -83,36 +97,41 @@ class LogParser {
|
|
|
83
97
|
}
|
|
84
98
|
/**
|
|
85
99
|
* Consolidate buffered request/response lines into single line
|
|
100
|
+
* Handles both old and new llama.cpp log formats
|
|
86
101
|
*/
|
|
87
102
|
consolidateRequest(lines) {
|
|
88
103
|
try {
|
|
89
104
|
// Parse first line: timestamp and request info
|
|
105
|
+
// Match both "request:" and "done request:" formats
|
|
90
106
|
const firstLine = lines[0];
|
|
91
107
|
const timestamp = this.extractTimestamp(firstLine);
|
|
92
|
-
const requestMatch = firstLine.match(/request: (POST|GET|PUT|DELETE) (\/[^\s]+) ([^\s]+) (\d+)/);
|
|
108
|
+
const requestMatch = firstLine.match(/(?:done )?request: (POST|GET|PUT|DELETE) (\/[^\s]+) ([^\s]+) (\d+)/);
|
|
93
109
|
if (!requestMatch)
|
|
94
110
|
return null;
|
|
95
111
|
const [, method, endpoint, ip, status] = requestMatch;
|
|
96
|
-
// Parse request JSON (
|
|
112
|
+
// Parse request JSON (line with JSON body)
|
|
97
113
|
const requestLine = lines.find((l) => l.includes('log_server_r: request:') && l.includes('{'));
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
114
|
+
let userMessage = '';
|
|
115
|
+
if (requestLine) {
|
|
116
|
+
const requestJson = this.extractJson(requestLine);
|
|
117
|
+
if (requestJson) {
|
|
118
|
+
userMessage = this.extractUserMessage(requestJson);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Parse response JSON (may be empty in new format)
|
|
105
122
|
const responseLine = lines.find((l) => l.includes('log_server_r: response:'));
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
123
|
+
let tokensIn = 0;
|
|
124
|
+
let tokensOut = 0;
|
|
125
|
+
let responseTimeMs = 0;
|
|
126
|
+
if (responseLine) {
|
|
127
|
+
const responseJson = this.extractJson(responseLine);
|
|
128
|
+
if (responseJson) {
|
|
129
|
+
tokensIn = responseJson.usage?.prompt_tokens || 0;
|
|
130
|
+
tokensOut = responseJson.usage?.completion_tokens || 0;
|
|
131
|
+
responseTimeMs = this.extractResponseTime(responseJson);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Format compact line (works even without response data)
|
|
116
135
|
return this.formatCompactLine({
|
|
117
136
|
timestamp,
|
|
118
137
|
method,
|
|
@@ -159,14 +178,26 @@ class LogParser {
|
|
|
159
178
|
}
|
|
160
179
|
/**
|
|
161
180
|
* Extract first user message from request JSON
|
|
181
|
+
* Handles both string content and array content formats:
|
|
182
|
+
* - String: {"role":"user","content":"Hello"}
|
|
183
|
+
* - Array: {"role":"user","content":[{"type":"text","text":"Hello"}]}
|
|
162
184
|
*/
|
|
163
185
|
extractUserMessage(requestJson) {
|
|
164
186
|
const messages = requestJson.messages || [];
|
|
165
187
|
const userMsg = messages.find((m) => m.role === 'user');
|
|
166
188
|
if (!userMsg || !userMsg.content)
|
|
167
189
|
return '';
|
|
168
|
-
|
|
169
|
-
|
|
190
|
+
let content;
|
|
191
|
+
// Handle array format (e.g., Claude/Anthropic API style)
|
|
192
|
+
if (Array.isArray(userMsg.content)) {
|
|
193
|
+
const textPart = userMsg.content.find((p) => p.type === 'text');
|
|
194
|
+
content = textPart?.text || '';
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
content = userMsg.content;
|
|
198
|
+
}
|
|
199
|
+
// Clean and truncate to first 50 characters
|
|
200
|
+
content = content.replace(/\n/g, ' ').replace(/\s+/g, ' ').trim();
|
|
170
201
|
return content.length > 50 ? content.substring(0, 47) + '...' : content;
|
|
171
202
|
}
|
|
172
203
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-parser.js","sourceRoot":"","sources":["../../src/utils/log-parser.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAcH,MAAa,SAAS;IAAtB;QACU,WAAM,GAAa,EAAE,CAAC;QACtB,gBAAW,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"log-parser.js","sourceRoot":"","sources":["../../src/utils/log-parser.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -24,6 +24,7 @@ import { routerStopCommand } from './commands/router/stop';
|
|
|
24
24
|
import { routerStatusCommand } from './commands/router/status';
|
|
25
25
|
import { routerRestartCommand } from './commands/router/restart';
|
|
26
26
|
import { routerConfigCommand } from './commands/router/config';
|
|
27
|
+
import { routerLogsCommand } from './commands/router/logs';
|
|
27
28
|
import packageJson from '../package.json';
|
|
28
29
|
|
|
29
30
|
const program = new Command();
|
|
@@ -31,7 +32,17 @@ const program = new Command();
|
|
|
31
32
|
program
|
|
32
33
|
.name('llamacpp')
|
|
33
34
|
.description('CLI tool to manage local llama.cpp servers on macOS')
|
|
34
|
-
.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
|
+
});
|
|
35
46
|
|
|
36
47
|
// List models
|
|
37
48
|
program
|
|
@@ -46,14 +57,13 @@ program
|
|
|
46
57
|
}
|
|
47
58
|
});
|
|
48
59
|
|
|
49
|
-
// List
|
|
60
|
+
// List servers (static table)
|
|
50
61
|
program
|
|
51
|
-
.command('ps
|
|
52
|
-
.description('
|
|
53
|
-
.
|
|
54
|
-
.action(async (identifier?: string, options?: { table?: boolean }) => {
|
|
62
|
+
.command('ps')
|
|
63
|
+
.description('List all servers with status (static table)')
|
|
64
|
+
.action(async () => {
|
|
55
65
|
try {
|
|
56
|
-
await psCommand(
|
|
66
|
+
await psCommand();
|
|
57
67
|
} catch (error) {
|
|
58
68
|
console.error(chalk.red('❌ Error:'), (error as Error).message);
|
|
59
69
|
process.exit(1);
|
|
@@ -298,14 +308,14 @@ server
|
|
|
298
308
|
}
|
|
299
309
|
});
|
|
300
310
|
|
|
301
|
-
// Monitor server (deprecated - redirects to
|
|
311
|
+
// Monitor server (deprecated - redirects to TUI)
|
|
302
312
|
server
|
|
303
313
|
.command('monitor [identifier]')
|
|
304
|
-
.description('Monitor server with real-time metrics TUI (deprecated: use "llamacpp
|
|
314
|
+
.description('Monitor server with real-time metrics TUI (deprecated: use "llamacpp" instead)')
|
|
305
315
|
.action(async (identifier?: string) => {
|
|
306
316
|
try {
|
|
307
317
|
console.log(chalk.yellow('⚠️ The "monitor" command is deprecated and will be removed in a future version.'));
|
|
308
|
-
console.log(chalk.dim(' Please use "llamacpp
|
|
318
|
+
console.log(chalk.dim(' Please use "llamacpp" instead for the same functionality.\n'));
|
|
309
319
|
await monitorCommand(identifier);
|
|
310
320
|
} catch (error) {
|
|
311
321
|
console.error(chalk.red('❌ Error:'), (error as Error).message);
|
|
@@ -378,6 +388,7 @@ router
|
|
|
378
388
|
.option('-h, --host <address>', 'Update bind address')
|
|
379
389
|
.option('--timeout <ms>', 'Update request timeout (milliseconds)', parseInt)
|
|
380
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')
|
|
381
392
|
.option('-r, --restart', 'Automatically restart router if running')
|
|
382
393
|
.action(async (options) => {
|
|
383
394
|
try {
|
|
@@ -388,5 +399,25 @@ router
|
|
|
388
399
|
}
|
|
389
400
|
});
|
|
390
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
|
+
|
|
391
422
|
// Parse arguments
|
|
392
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
|
-
}
|
|
@@ -6,6 +6,7 @@ interface ConfigOptions {
|
|
|
6
6
|
host?: string;
|
|
7
7
|
timeout?: number;
|
|
8
8
|
healthInterval?: number;
|
|
9
|
+
verbose?: boolean;
|
|
9
10
|
restart?: boolean;
|
|
10
11
|
}
|
|
11
12
|
|
|
@@ -18,9 +19,9 @@ export async function routerConfigCommand(options: ConfigOptions): Promise<void>
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
// Check if any options were provided
|
|
21
|
-
const hasOptions = options.port || options.host || options.timeout || options.healthInterval;
|
|
22
|
+
const hasOptions = options.port || options.host || options.timeout || options.healthInterval || options.verbose !== undefined;
|
|
22
23
|
if (!hasOptions) {
|
|
23
|
-
throw new Error('No configuration options provided. Use --port, --host, --timeout,
|
|
24
|
+
throw new Error('No configuration options provided. Use --port, --host, --timeout, --health-interval, or --verbose');
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
const isRunning = config.status === 'running';
|
|
@@ -55,6 +56,12 @@ export async function routerConfigCommand(options: ConfigOptions): Promise<void>
|
|
|
55
56
|
updates.healthCheckInterval = options.healthInterval;
|
|
56
57
|
}
|
|
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
|
+
|
|
58
65
|
// Display changes
|
|
59
66
|
console.log(chalk.blue('📝 Configuration changes:'));
|
|
60
67
|
console.log();
|