@appkit/llamacpp-cli 1.11.0 → 1.12.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 +572 -170
- package/dist/cli.js +99 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/admin/config.d.ts +10 -0
- package/dist/commands/admin/config.d.ts.map +1 -0
- package/dist/commands/admin/config.js +100 -0
- package/dist/commands/admin/config.js.map +1 -0
- package/dist/commands/admin/logs.d.ts +10 -0
- package/dist/commands/admin/logs.d.ts.map +1 -0
- package/dist/commands/admin/logs.js +114 -0
- package/dist/commands/admin/logs.js.map +1 -0
- package/dist/commands/admin/restart.d.ts +2 -0
- package/dist/commands/admin/restart.d.ts.map +1 -0
- package/dist/commands/admin/restart.js +29 -0
- package/dist/commands/admin/restart.js.map +1 -0
- package/dist/commands/admin/start.d.ts +2 -0
- package/dist/commands/admin/start.d.ts.map +1 -0
- package/dist/commands/admin/start.js +30 -0
- package/dist/commands/admin/start.js.map +1 -0
- package/dist/commands/admin/status.d.ts +2 -0
- package/dist/commands/admin/status.d.ts.map +1 -0
- package/dist/commands/admin/status.js +82 -0
- package/dist/commands/admin/status.js.map +1 -0
- package/dist/commands/admin/stop.d.ts +2 -0
- package/dist/commands/admin/stop.d.ts.map +1 -0
- package/dist/commands/admin/stop.js +21 -0
- package/dist/commands/admin/stop.js.map +1 -0
- package/dist/commands/logs.d.ts +1 -0
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +22 -0
- package/dist/commands/logs.js.map +1 -1
- package/dist/lib/admin-manager.d.ts +111 -0
- package/dist/lib/admin-manager.d.ts.map +1 -0
- package/dist/lib/admin-manager.js +413 -0
- package/dist/lib/admin-manager.js.map +1 -0
- package/dist/lib/admin-server.d.ts +148 -0
- package/dist/lib/admin-server.d.ts.map +1 -0
- package/dist/lib/admin-server.js +1161 -0
- package/dist/lib/admin-server.js.map +1 -0
- package/dist/lib/download-job-manager.d.ts +64 -0
- package/dist/lib/download-job-manager.d.ts.map +1 -0
- package/dist/lib/download-job-manager.js +164 -0
- package/dist/lib/download-job-manager.js.map +1 -0
- package/dist/tui/MultiServerMonitorApp.js +1 -1
- package/dist/types/admin-config.d.ts +19 -0
- package/dist/types/admin-config.d.ts.map +1 -0
- package/dist/types/admin-config.js +3 -0
- package/dist/types/admin-config.js.map +1 -0
- package/dist/utils/log-parser.d.ts +9 -0
- package/dist/utils/log-parser.d.ts.map +1 -1
- package/dist/utils/log-parser.js +11 -0
- package/dist/utils/log-parser.js.map +1 -1
- package/package.json +10 -2
- package/web/README.md +429 -0
- package/web/dist/assets/index-Bin89Lwr.css +1 -0
- package/web/dist/assets/index-CVmonw3T.js +17 -0
- package/web/dist/index.html +14 -0
- package/web/dist/vite.svg +1 -0
- package/.versionrc.json +0 -16
- package/CHANGELOG.md +0 -203
- package/MONITORING-ACCURACY-FIX.md +0 -199
- package/PER-PROCESS-METRICS.md +0 -190
- package/docs/images/.gitkeep +0 -1
- package/src/cli.ts +0 -423
- package/src/commands/config-global.ts +0 -38
- package/src/commands/config.ts +0 -323
- package/src/commands/create.ts +0 -183
- package/src/commands/delete.ts +0 -74
- package/src/commands/list.ts +0 -37
- package/src/commands/logs-all.ts +0 -251
- package/src/commands/logs.ts +0 -321
- package/src/commands/monitor.ts +0 -110
- package/src/commands/ps.ts +0 -84
- package/src/commands/pull.ts +0 -44
- package/src/commands/rm.ts +0 -107
- package/src/commands/router/config.ts +0 -116
- package/src/commands/router/logs.ts +0 -256
- package/src/commands/router/restart.ts +0 -36
- package/src/commands/router/start.ts +0 -60
- package/src/commands/router/status.ts +0 -119
- package/src/commands/router/stop.ts +0 -33
- package/src/commands/run.ts +0 -233
- package/src/commands/search.ts +0 -107
- package/src/commands/server-show.ts +0 -161
- package/src/commands/show.ts +0 -207
- package/src/commands/start.ts +0 -101
- package/src/commands/stop.ts +0 -39
- package/src/commands/tui.ts +0 -25
- package/src/lib/config-generator.ts +0 -130
- package/src/lib/history-manager.ts +0 -172
- package/src/lib/launchctl-manager.ts +0 -225
- package/src/lib/metrics-aggregator.ts +0 -257
- package/src/lib/model-downloader.ts +0 -328
- package/src/lib/model-scanner.ts +0 -157
- package/src/lib/model-search.ts +0 -114
- package/src/lib/models-dir-setup.ts +0 -46
- package/src/lib/port-manager.ts +0 -80
- package/src/lib/router-logger.ts +0 -201
- package/src/lib/router-manager.ts +0 -414
- package/src/lib/router-server.ts +0 -538
- package/src/lib/state-manager.ts +0 -206
- package/src/lib/status-checker.ts +0 -113
- package/src/lib/system-collector.ts +0 -315
- package/src/tui/ConfigApp.ts +0 -1085
- package/src/tui/HistoricalMonitorApp.ts +0 -587
- package/src/tui/ModelsApp.ts +0 -368
- package/src/tui/MonitorApp.ts +0 -386
- package/src/tui/MultiServerMonitorApp.ts +0 -1833
- package/src/tui/RootNavigator.ts +0 -74
- package/src/tui/SearchApp.ts +0 -511
- package/src/tui/SplashScreen.ts +0 -149
- package/src/types/global-config.ts +0 -26
- package/src/types/history-types.ts +0 -39
- package/src/types/model-info.ts +0 -8
- package/src/types/monitor-types.ts +0 -162
- package/src/types/router-config.ts +0 -25
- package/src/types/server-config.ts +0 -46
- package/src/utils/downsample-utils.ts +0 -128
- package/src/utils/file-utils.ts +0 -146
- package/src/utils/format-utils.ts +0 -98
- package/src/utils/log-parser.ts +0 -271
- package/src/utils/log-utils.ts +0 -178
- package/src/utils/process-utils.ts +0 -316
- package/src/utils/prompt-utils.ts +0 -47
- package/test-load.sh +0 -100
- package/tsconfig.json +0 -20
package/src/commands/logs-all.ts
DELETED
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import Table from 'cli-table3';
|
|
3
|
-
import { stateManager } from '../lib/state-manager';
|
|
4
|
-
import { fileExists } from '../utils/file-utils';
|
|
5
|
-
import {
|
|
6
|
-
getFileSize,
|
|
7
|
-
formatFileSize,
|
|
8
|
-
getArchivedLogInfo,
|
|
9
|
-
clearLogFile,
|
|
10
|
-
rotateLogFile,
|
|
11
|
-
deleteArchivedLogs,
|
|
12
|
-
} from '../utils/log-utils';
|
|
13
|
-
|
|
14
|
-
interface LogsAllOptions {
|
|
15
|
-
clear?: boolean;
|
|
16
|
-
clearArchived?: boolean;
|
|
17
|
-
clearAll?: boolean;
|
|
18
|
-
rotate?: boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export async function logsAllCommand(options: LogsAllOptions): Promise<void> {
|
|
22
|
-
// Get all servers
|
|
23
|
-
const servers = await stateManager.getAllServers();
|
|
24
|
-
|
|
25
|
-
if (servers.length === 0) {
|
|
26
|
-
console.log(chalk.yellow('⚠️ No servers found'));
|
|
27
|
-
console.log(chalk.dim('\nCreate a server: llamacpp server create <model-filename>'));
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Handle batch operations
|
|
32
|
-
if (options.clear || options.clearArchived || options.clearAll || options.rotate) {
|
|
33
|
-
await handleBatchOperation(servers, options);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Show table of log information
|
|
38
|
-
await showLogsTable(servers);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async function showLogsTable(servers: any[]): Promise<void> {
|
|
42
|
-
const table = new Table({
|
|
43
|
-
head: [
|
|
44
|
-
chalk.bold('Server ID'),
|
|
45
|
-
chalk.bold('Current Stderr'),
|
|
46
|
-
chalk.bold('Current Stdout'),
|
|
47
|
-
chalk.bold('Archived'),
|
|
48
|
-
chalk.bold('Total'),
|
|
49
|
-
],
|
|
50
|
-
colWidths: [30, 18, 18, 18, 18],
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
let totalCurrent = 0;
|
|
54
|
-
let totalArchived = 0;
|
|
55
|
-
|
|
56
|
-
for (const server of servers) {
|
|
57
|
-
// Get current log sizes
|
|
58
|
-
const stderrSize = (await fileExists(server.stderrPath))
|
|
59
|
-
? await getFileSize(server.stderrPath)
|
|
60
|
-
: 0;
|
|
61
|
-
const stdoutSize = (await fileExists(server.stdoutPath))
|
|
62
|
-
? await getFileSize(server.stdoutPath)
|
|
63
|
-
: 0;
|
|
64
|
-
|
|
65
|
-
// Get archived info
|
|
66
|
-
const archivedInfo = await getArchivedLogInfo(server.id);
|
|
67
|
-
|
|
68
|
-
const currentTotal = stderrSize + stdoutSize;
|
|
69
|
-
const total = currentTotal + archivedInfo.totalSize;
|
|
70
|
-
|
|
71
|
-
totalCurrent += currentTotal;
|
|
72
|
-
totalArchived += archivedInfo.totalSize;
|
|
73
|
-
|
|
74
|
-
table.push([
|
|
75
|
-
server.id,
|
|
76
|
-
formatFileSize(stderrSize),
|
|
77
|
-
formatFileSize(stdoutSize),
|
|
78
|
-
archivedInfo.count > 0
|
|
79
|
-
? `${formatFileSize(archivedInfo.totalSize)} (${archivedInfo.count})`
|
|
80
|
-
: formatFileSize(0),
|
|
81
|
-
formatFileSize(total),
|
|
82
|
-
]);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
console.log(chalk.bold('\nServer Logs Overview:'));
|
|
86
|
-
console.log(table.toString());
|
|
87
|
-
|
|
88
|
-
console.log(chalk.dim('\nTotals:'));
|
|
89
|
-
console.log(chalk.dim(` Current logs: ${formatFileSize(totalCurrent)}`));
|
|
90
|
-
console.log(chalk.dim(` Archived logs: ${formatFileSize(totalArchived)}`));
|
|
91
|
-
console.log(chalk.dim(` Grand total: ${formatFileSize(totalCurrent + totalArchived)}`));
|
|
92
|
-
|
|
93
|
-
console.log(chalk.dim('\nBatch operations:'));
|
|
94
|
-
console.log(chalk.dim(' llamacpp logs --clear Clear all current logs'));
|
|
95
|
-
console.log(chalk.dim(' llamacpp logs --clear-archived Delete only archived logs'));
|
|
96
|
-
console.log(chalk.dim(' llamacpp logs --clear-all Clear current + delete archives'));
|
|
97
|
-
console.log(chalk.dim(' llamacpp logs --rotate Rotate all logs with timestamps'));
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async function handleBatchOperation(
|
|
101
|
-
servers: any[],
|
|
102
|
-
options: LogsAllOptions
|
|
103
|
-
): Promise<void> {
|
|
104
|
-
if (options.clearArchived) {
|
|
105
|
-
console.log(chalk.blue('🗑️ Deleting archived logs for all servers...'));
|
|
106
|
-
console.log();
|
|
107
|
-
|
|
108
|
-
let totalFreed = 0;
|
|
109
|
-
let totalFiles = 0;
|
|
110
|
-
let serversProcessed = 0;
|
|
111
|
-
|
|
112
|
-
for (const server of servers) {
|
|
113
|
-
const archivedInfo = await deleteArchivedLogs(server.id);
|
|
114
|
-
|
|
115
|
-
if (archivedInfo.count > 0) {
|
|
116
|
-
console.log(chalk.dim(` ${server.id}: ${formatFileSize(archivedInfo.totalSize)} (${archivedInfo.count} file${archivedInfo.count !== 1 ? 's' : ''})`));
|
|
117
|
-
totalFreed += archivedInfo.totalSize;
|
|
118
|
-
totalFiles += archivedInfo.count;
|
|
119
|
-
serversProcessed++;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
console.log();
|
|
124
|
-
if (serversProcessed === 0) {
|
|
125
|
-
console.log(chalk.yellow('⚠️ No archived logs found'));
|
|
126
|
-
console.log(chalk.dim(' Archived logs are created via --rotate or automatic rotation'));
|
|
127
|
-
} else {
|
|
128
|
-
console.log(chalk.green(`✅ Deleted archived logs for ${serversProcessed} server${serversProcessed !== 1 ? 's' : ''}`));
|
|
129
|
-
console.log(chalk.dim(` Files deleted: ${totalFiles}`));
|
|
130
|
-
console.log(chalk.dim(` Total freed: ${formatFileSize(totalFreed)}`));
|
|
131
|
-
console.log(chalk.dim(` Current logs preserved`));
|
|
132
|
-
}
|
|
133
|
-
} else if (options.clearAll) {
|
|
134
|
-
console.log(chalk.blue('🗑️ Clearing all logs (current + archived) for all servers...'));
|
|
135
|
-
console.log();
|
|
136
|
-
|
|
137
|
-
let totalFreed = 0;
|
|
138
|
-
let serversProcessed = 0;
|
|
139
|
-
|
|
140
|
-
for (const server of servers) {
|
|
141
|
-
let serverTotal = 0;
|
|
142
|
-
|
|
143
|
-
// Clear current stderr
|
|
144
|
-
if (await fileExists(server.stderrPath)) {
|
|
145
|
-
serverTotal += await getFileSize(server.stderrPath);
|
|
146
|
-
await clearLogFile(server.stderrPath);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Clear current stdout
|
|
150
|
-
if (await fileExists(server.stdoutPath)) {
|
|
151
|
-
serverTotal += await getFileSize(server.stdoutPath);
|
|
152
|
-
await clearLogFile(server.stdoutPath);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Delete archived logs
|
|
156
|
-
const archivedInfo = await deleteArchivedLogs(server.id);
|
|
157
|
-
serverTotal += archivedInfo.totalSize;
|
|
158
|
-
|
|
159
|
-
if (serverTotal > 0) {
|
|
160
|
-
console.log(chalk.dim(` ${server.id}: ${formatFileSize(serverTotal)}`));
|
|
161
|
-
totalFreed += serverTotal;
|
|
162
|
-
serversProcessed++;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
console.log();
|
|
167
|
-
console.log(chalk.green(`✅ Cleared all logs for ${serversProcessed} server${serversProcessed !== 1 ? 's' : ''}`));
|
|
168
|
-
console.log(chalk.dim(` Total freed: ${formatFileSize(totalFreed)}`));
|
|
169
|
-
} else if (options.clear) {
|
|
170
|
-
console.log(chalk.blue('🗑️ Clearing current logs for all servers...'));
|
|
171
|
-
console.log();
|
|
172
|
-
|
|
173
|
-
let totalFreed = 0;
|
|
174
|
-
let serversProcessed = 0;
|
|
175
|
-
|
|
176
|
-
for (const server of servers) {
|
|
177
|
-
let serverTotal = 0;
|
|
178
|
-
|
|
179
|
-
// Clear current stderr
|
|
180
|
-
if (await fileExists(server.stderrPath)) {
|
|
181
|
-
serverTotal += await getFileSize(server.stderrPath);
|
|
182
|
-
await clearLogFile(server.stderrPath);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Clear current stdout
|
|
186
|
-
if (await fileExists(server.stdoutPath)) {
|
|
187
|
-
serverTotal += await getFileSize(server.stdoutPath);
|
|
188
|
-
await clearLogFile(server.stdoutPath);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (serverTotal > 0) {
|
|
192
|
-
console.log(chalk.dim(` ${server.id}: ${formatFileSize(serverTotal)}`));
|
|
193
|
-
totalFreed += serverTotal;
|
|
194
|
-
serversProcessed++;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
console.log();
|
|
199
|
-
console.log(chalk.green(`✅ Cleared current logs for ${serversProcessed} server${serversProcessed !== 1 ? 's' : ''}`));
|
|
200
|
-
console.log(chalk.dim(` Total freed: ${formatFileSize(totalFreed)}`));
|
|
201
|
-
console.log(chalk.dim(` Archived logs preserved`));
|
|
202
|
-
} else if (options.rotate) {
|
|
203
|
-
console.log(chalk.blue('🔄 Rotating logs for all servers...'));
|
|
204
|
-
console.log();
|
|
205
|
-
|
|
206
|
-
let totalRotated = 0;
|
|
207
|
-
let filesRotated = 0;
|
|
208
|
-
|
|
209
|
-
for (const server of servers) {
|
|
210
|
-
const rotatedFiles: string[] = [];
|
|
211
|
-
|
|
212
|
-
// Rotate stderr if it has content
|
|
213
|
-
if (await fileExists(server.stderrPath)) {
|
|
214
|
-
const size = await getFileSize(server.stderrPath);
|
|
215
|
-
if (size > 0) {
|
|
216
|
-
try {
|
|
217
|
-
const archivedPath = await rotateLogFile(server.stderrPath);
|
|
218
|
-
rotatedFiles.push(archivedPath);
|
|
219
|
-
totalRotated += size;
|
|
220
|
-
filesRotated++;
|
|
221
|
-
} catch {
|
|
222
|
-
// Ignore empty files
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// Rotate stdout if it has content
|
|
228
|
-
if (await fileExists(server.stdoutPath)) {
|
|
229
|
-
const size = await getFileSize(server.stdoutPath);
|
|
230
|
-
if (size > 0) {
|
|
231
|
-
try {
|
|
232
|
-
const archivedPath = await rotateLogFile(server.stdoutPath);
|
|
233
|
-
rotatedFiles.push(archivedPath);
|
|
234
|
-
totalRotated += size;
|
|
235
|
-
filesRotated++;
|
|
236
|
-
} catch {
|
|
237
|
-
// Ignore empty files
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (rotatedFiles.length > 0) {
|
|
243
|
-
console.log(chalk.dim(` ${server.id}: ${rotatedFiles.length} file${rotatedFiles.length !== 1 ? 's' : ''}`));
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
console.log();
|
|
248
|
-
console.log(chalk.green(`✅ Rotated ${filesRotated} log file${filesRotated !== 1 ? 's' : ''}`));
|
|
249
|
-
console.log(chalk.dim(` Total archived: ${formatFileSize(totalRotated)}`));
|
|
250
|
-
}
|
|
251
|
-
}
|
package/src/commands/logs.ts
DELETED
|
@@ -1,321 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import { spawn } from 'child_process';
|
|
3
|
-
import * as readline from 'readline';
|
|
4
|
-
import * as fs from 'fs';
|
|
5
|
-
import { stateManager } from '../lib/state-manager';
|
|
6
|
-
import { fileExists } from '../utils/file-utils';
|
|
7
|
-
import { execCommand } from '../utils/process-utils';
|
|
8
|
-
import { logParser } from '../utils/log-parser';
|
|
9
|
-
import {
|
|
10
|
-
getFileSize,
|
|
11
|
-
formatFileSize,
|
|
12
|
-
rotateLogFile,
|
|
13
|
-
clearLogFile,
|
|
14
|
-
getArchivedLogInfo,
|
|
15
|
-
deleteArchivedLogs,
|
|
16
|
-
} from '../utils/log-utils';
|
|
17
|
-
|
|
18
|
-
interface LogsOptions {
|
|
19
|
-
follow?: boolean;
|
|
20
|
-
lines?: number;
|
|
21
|
-
errors?: boolean;
|
|
22
|
-
verbose?: boolean;
|
|
23
|
-
http?: boolean;
|
|
24
|
-
stdout?: boolean;
|
|
25
|
-
filter?: string;
|
|
26
|
-
clear?: boolean;
|
|
27
|
-
rotate?: boolean;
|
|
28
|
-
clearArchived?: boolean;
|
|
29
|
-
clearAll?: boolean;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export async function logsCommand(identifier: string, options: LogsOptions): Promise<void> {
|
|
33
|
-
// Find server
|
|
34
|
-
const server = await stateManager.findServer(identifier);
|
|
35
|
-
if (!server) {
|
|
36
|
-
throw new Error(`Server not found: ${identifier}\n\nUse: llamacpp ps`);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Determine log file (default to stderr where verbose logs go)
|
|
40
|
-
const logPath = options.stdout ? server.stdoutPath : server.stderrPath;
|
|
41
|
-
const logType = options.stdout ? 'stdout' : 'stderr';
|
|
42
|
-
|
|
43
|
-
// Handle --clear-archived option (deletes only archived logs)
|
|
44
|
-
if (options.clearArchived) {
|
|
45
|
-
const archivedInfo = await deleteArchivedLogs(server.id);
|
|
46
|
-
|
|
47
|
-
if (archivedInfo.count === 0) {
|
|
48
|
-
console.log(chalk.yellow(`⚠️ No archived logs found for ${server.modelName}`));
|
|
49
|
-
console.log(chalk.dim(` Archived logs are created via --rotate or automatic rotation`));
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
console.log(chalk.green(`✅ Deleted archived logs for ${server.modelName}`));
|
|
54
|
-
console.log(chalk.dim(` Files deleted: ${archivedInfo.count}`));
|
|
55
|
-
console.log(chalk.dim(` Space freed: ${formatFileSize(archivedInfo.totalSize)}`));
|
|
56
|
-
console.log(chalk.dim(` Current logs preserved`));
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Handle --clear-all option (clears both current and archived logs)
|
|
61
|
-
if (options.clearAll) {
|
|
62
|
-
let totalFreed = 0;
|
|
63
|
-
let currentSize = 0;
|
|
64
|
-
let archivedSize = 0;
|
|
65
|
-
|
|
66
|
-
// Clear current stderr
|
|
67
|
-
if (await fileExists(server.stderrPath)) {
|
|
68
|
-
currentSize += await getFileSize(server.stderrPath);
|
|
69
|
-
await clearLogFile(server.stderrPath);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Clear current stdout
|
|
73
|
-
if (await fileExists(server.stdoutPath)) {
|
|
74
|
-
currentSize += await getFileSize(server.stdoutPath);
|
|
75
|
-
await clearLogFile(server.stdoutPath);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Delete all archived logs
|
|
79
|
-
const archivedInfo = await deleteArchivedLogs(server.id);
|
|
80
|
-
archivedSize = archivedInfo.totalSize;
|
|
81
|
-
|
|
82
|
-
totalFreed = currentSize + archivedSize;
|
|
83
|
-
|
|
84
|
-
console.log(chalk.green(`✅ Cleared all logs for ${server.modelName}`));
|
|
85
|
-
if (currentSize > 0) {
|
|
86
|
-
console.log(chalk.dim(` Current logs: ${formatFileSize(currentSize)}`));
|
|
87
|
-
}
|
|
88
|
-
if (archivedSize > 0) {
|
|
89
|
-
console.log(chalk.dim(` Archived logs: ${formatFileSize(archivedSize)} (${archivedInfo.count} file${archivedInfo.count > 1 ? 's' : ''})`));
|
|
90
|
-
}
|
|
91
|
-
console.log(chalk.dim(` Total freed: ${formatFileSize(totalFreed)}`));
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Handle --clear option
|
|
96
|
-
if (options.clear) {
|
|
97
|
-
if (!(await fileExists(logPath))) {
|
|
98
|
-
console.log(chalk.yellow(`⚠️ No ${logType} found for ${server.modelName}`));
|
|
99
|
-
console.log(chalk.dim(` Log file does not exist: ${logPath}`));
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const sizeBefore = await getFileSize(logPath);
|
|
104
|
-
await clearLogFile(logPath);
|
|
105
|
-
|
|
106
|
-
console.log(chalk.green(`✅ Cleared ${logType} for ${server.modelName}`));
|
|
107
|
-
console.log(chalk.dim(` Freed: ${formatFileSize(sizeBefore)}`));
|
|
108
|
-
console.log(chalk.dim(` ${logPath}`));
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Handle --rotate option
|
|
113
|
-
if (options.rotate) {
|
|
114
|
-
if (!(await fileExists(logPath))) {
|
|
115
|
-
console.log(chalk.yellow(`⚠️ No ${logType} found for ${server.modelName}`));
|
|
116
|
-
console.log(chalk.dim(` Log file does not exist: ${logPath}`));
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
try {
|
|
121
|
-
const archivedPath = await rotateLogFile(logPath);
|
|
122
|
-
const size = await getFileSize(archivedPath);
|
|
123
|
-
|
|
124
|
-
console.log(chalk.green(`✅ Rotated ${logType} for ${server.modelName}`));
|
|
125
|
-
console.log(chalk.dim(` Archived: ${formatFileSize(size)}`));
|
|
126
|
-
console.log(chalk.dim(` → ${archivedPath}`));
|
|
127
|
-
} catch (error) {
|
|
128
|
-
throw new Error(`Failed to rotate log: ${(error as Error).message}`);
|
|
129
|
-
}
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Check if log file exists
|
|
134
|
-
if (!(await fileExists(logPath))) {
|
|
135
|
-
console.log(chalk.yellow(`⚠️ No ${logType} found for ${server.modelName}`));
|
|
136
|
-
console.log(chalk.dim(` Log file does not exist: ${logPath}`));
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Determine filter pattern and mode
|
|
141
|
-
let filterPattern: string | null = null;
|
|
142
|
-
let filterDesc = '';
|
|
143
|
-
let useCompactMode = false;
|
|
144
|
-
|
|
145
|
-
if (options.verbose) {
|
|
146
|
-
// Show everything (no filter)
|
|
147
|
-
filterDesc = ' (all messages)';
|
|
148
|
-
} else if (options.errors) {
|
|
149
|
-
// Show only errors
|
|
150
|
-
filterPattern = 'error|Error|ERROR|failed|Failed|FAILED';
|
|
151
|
-
filterDesc = ' (errors only)';
|
|
152
|
-
} else if (options.http) {
|
|
153
|
-
// Full HTTP JSON logs
|
|
154
|
-
filterPattern = 'log_server_r';
|
|
155
|
-
filterDesc = ' (HTTP JSON)';
|
|
156
|
-
} else if (options.filter) {
|
|
157
|
-
// Custom filter
|
|
158
|
-
filterPattern = options.filter;
|
|
159
|
-
filterDesc = ` (filter: ${options.filter})`;
|
|
160
|
-
} else {
|
|
161
|
-
// Default: Compact one-liner format
|
|
162
|
-
filterPattern = 'log_server_r';
|
|
163
|
-
filterDesc = ' (compact)';
|
|
164
|
-
useCompactMode = true;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
console.log(chalk.blue(`📋 Logs for ${server.modelName} (${logType}${filterDesc})`));
|
|
168
|
-
console.log(chalk.dim(` ${logPath}`));
|
|
169
|
-
|
|
170
|
-
// Show log size information
|
|
171
|
-
const currentSize = await getFileSize(logPath);
|
|
172
|
-
const archivedInfo = await getArchivedLogInfo(server.id);
|
|
173
|
-
|
|
174
|
-
if (archivedInfo.count > 0) {
|
|
175
|
-
console.log(chalk.dim(` Current: ${formatFileSize(currentSize)} | Archived: ${formatFileSize(archivedInfo.totalSize)} (${archivedInfo.count} file${archivedInfo.count > 1 ? 's' : ''})`));
|
|
176
|
-
} else {
|
|
177
|
-
console.log(chalk.dim(` Current: ${formatFileSize(currentSize)}`));
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Show subtle note if verbose logging is not enabled
|
|
181
|
-
if (!server.verbose && !options.verbose && !options.errors && !options.http && !options.filter) {
|
|
182
|
-
console.log(chalk.dim(` verbosity is disabled`));
|
|
183
|
-
}
|
|
184
|
-
console.log();
|
|
185
|
-
|
|
186
|
-
if (options.follow) {
|
|
187
|
-
// Follow logs in real-time with optional filtering
|
|
188
|
-
if (useCompactMode) {
|
|
189
|
-
// Compact mode with follow: parse lines in real-time
|
|
190
|
-
const tailProcess = spawn('tail', ['-f', logPath]);
|
|
191
|
-
const rl = readline.createInterface({
|
|
192
|
-
input: tailProcess.stdout,
|
|
193
|
-
crlfDelay: Infinity,
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
rl.on('line', (line) => {
|
|
197
|
-
if (line.includes('log_server_r')) {
|
|
198
|
-
logParser.processLine(line, (compactLine) => {
|
|
199
|
-
console.log(compactLine);
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
// Handle Ctrl+C gracefully
|
|
205
|
-
process.on('SIGINT', () => {
|
|
206
|
-
tailProcess.kill();
|
|
207
|
-
rl.close();
|
|
208
|
-
console.log();
|
|
209
|
-
process.exit(0);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
tailProcess.on('exit', () => {
|
|
213
|
-
process.exit(0);
|
|
214
|
-
});
|
|
215
|
-
} else if (filterPattern) {
|
|
216
|
-
// Use tail piped to grep for filtering
|
|
217
|
-
const grepProcess = spawn('sh', ['-c', `tail -f "${logPath}" | grep --line-buffered -E "${filterPattern}"`], {
|
|
218
|
-
stdio: 'inherit',
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
// Handle Ctrl+C gracefully
|
|
222
|
-
process.on('SIGINT', () => {
|
|
223
|
-
grepProcess.kill();
|
|
224
|
-
console.log();
|
|
225
|
-
process.exit(0);
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
grepProcess.on('exit', () => {
|
|
229
|
-
process.exit(0);
|
|
230
|
-
});
|
|
231
|
-
} else {
|
|
232
|
-
// No filter, just tail
|
|
233
|
-
const tail = spawn('tail', ['-f', logPath], {
|
|
234
|
-
stdio: 'inherit',
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
process.on('SIGINT', () => {
|
|
238
|
-
tail.kill();
|
|
239
|
-
console.log();
|
|
240
|
-
process.exit(0);
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
tail.on('exit', () => {
|
|
244
|
-
process.exit(0);
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
} else {
|
|
248
|
-
// Show last N lines with optional filtering
|
|
249
|
-
const lines = options.lines || 50;
|
|
250
|
-
|
|
251
|
-
if (useCompactMode) {
|
|
252
|
-
// Compact mode: read file and parse
|
|
253
|
-
try {
|
|
254
|
-
// Use large multiplier to account for verbose debug output between requests
|
|
255
|
-
// Add || true to prevent grep from failing when no matches found
|
|
256
|
-
const command = `tail -n ${lines * 100} "${logPath}" | grep -E "log_server_r" || true`;
|
|
257
|
-
const output = await execCommand(command);
|
|
258
|
-
const logLines = output.split('\n').filter((l) => l.trim());
|
|
259
|
-
|
|
260
|
-
if (logLines.length === 0) {
|
|
261
|
-
console.log(chalk.dim('No HTTP request logs in compact format.'));
|
|
262
|
-
console.log(chalk.dim('The server may be starting up, or only simple GET requests have been made.'));
|
|
263
|
-
console.log(chalk.dim('\nTip: Use --http to see raw HTTP logs, or --verbose for all server logs.'));
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
const compactLines: string[] = [];
|
|
268
|
-
for (const line of logLines) {
|
|
269
|
-
logParser.processLine(line, (compactLine) => {
|
|
270
|
-
compactLines.push(compactLine);
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Flush any remaining buffered logs (handles simple format)
|
|
275
|
-
logParser.flush((compactLine) => {
|
|
276
|
-
compactLines.push(compactLine);
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
// Check if we got any parsed output
|
|
280
|
-
if (compactLines.length === 0) {
|
|
281
|
-
console.log(chalk.dim('HTTP request logs found, but could not parse in compact format.'));
|
|
282
|
-
console.log(chalk.dim('This usually happens with simple GET requests (health checks, slots, etc.).'));
|
|
283
|
-
console.log(chalk.dim('\nTip: Use --http to see raw HTTP logs instead.'));
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// Show only the last N compact lines
|
|
288
|
-
const limitedLines = compactLines.slice(-lines);
|
|
289
|
-
limitedLines.forEach((line) => console.log(line));
|
|
290
|
-
} catch (error) {
|
|
291
|
-
throw new Error(`Failed to read logs: ${(error as Error).message}`);
|
|
292
|
-
}
|
|
293
|
-
} else {
|
|
294
|
-
// Regular filtering
|
|
295
|
-
try {
|
|
296
|
-
let command: string;
|
|
297
|
-
|
|
298
|
-
if (filterPattern) {
|
|
299
|
-
// Use tail piped to grep
|
|
300
|
-
// Add || true to prevent grep from failing when no matches found
|
|
301
|
-
command = `tail -n ${lines} "${logPath}" | grep -E "${filterPattern}" || true`;
|
|
302
|
-
} else {
|
|
303
|
-
// No filter
|
|
304
|
-
command = `tail -n ${lines} "${logPath}"`;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
const output = await execCommand(command);
|
|
308
|
-
|
|
309
|
-
if (filterPattern && output.trim() === '') {
|
|
310
|
-
console.log(chalk.dim(`No logs matching pattern: ${filterPattern}`));
|
|
311
|
-
console.log(chalk.dim('\nTip: Try --verbose to see all logs, or adjust your filter pattern.'));
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
console.log(output);
|
|
316
|
-
} catch (error) {
|
|
317
|
-
throw new Error(`Failed to read logs: ${(error as Error).message}`);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
package/src/commands/monitor.ts
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import blessed from 'blessed';
|
|
3
|
-
import { stateManager } from '../lib/state-manager.js';
|
|
4
|
-
import { createMonitorUI } from '../tui/MonitorApp.js';
|
|
5
|
-
import { createMultiServerMonitorUI } from '../tui/MultiServerMonitorApp.js';
|
|
6
|
-
|
|
7
|
-
export async function monitorCommand(identifier?: string): Promise<void> {
|
|
8
|
-
// Initialize state manager
|
|
9
|
-
await stateManager.initialize();
|
|
10
|
-
|
|
11
|
-
// Get all servers
|
|
12
|
-
const allServers = await stateManager.getAllServers();
|
|
13
|
-
if (allServers.length === 0) {
|
|
14
|
-
throw new Error(
|
|
15
|
-
`No servers configured.\n\n` +
|
|
16
|
-
`Create a server first: llamacpp server create <model>`
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Create blessed screen
|
|
21
|
-
const screen = blessed.screen({
|
|
22
|
-
smartCSR: true,
|
|
23
|
-
title: 'llama.cpp Server Monitor',
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
// Determine which UI to launch
|
|
27
|
-
if (identifier) {
|
|
28
|
-
// User specified a server - single server mode
|
|
29
|
-
const server = await stateManager.findServer(identifier);
|
|
30
|
-
if (!server) {
|
|
31
|
-
screen.destroy();
|
|
32
|
-
throw new Error(
|
|
33
|
-
`Server not found: ${identifier}\n\n` +
|
|
34
|
-
`Use: llamacpp ps (to list servers)\n` +
|
|
35
|
-
`Or create a new server: llamacpp server create <model>`
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Update server status to reflect actual launchctl state
|
|
40
|
-
const { statusChecker } = await import('../lib/status-checker.js');
|
|
41
|
-
const status = await statusChecker.checkServer(server);
|
|
42
|
-
server.status = status.isRunning ? 'running' : 'stopped';
|
|
43
|
-
server.pid = status.pid || undefined;
|
|
44
|
-
|
|
45
|
-
// Check if server is running
|
|
46
|
-
if (server.status !== 'running') {
|
|
47
|
-
screen.destroy();
|
|
48
|
-
throw new Error(
|
|
49
|
-
`Server ${server.modelName} is not running.\n\n` +
|
|
50
|
-
`Start it first: llamacpp server start ${server.id}`
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Launch single-server TUI
|
|
55
|
-
await createMonitorUI(screen, server);
|
|
56
|
-
} else if (allServers.length === 1) {
|
|
57
|
-
// Only one server - single server mode
|
|
58
|
-
const server = allServers[0];
|
|
59
|
-
|
|
60
|
-
// Update server status to reflect actual launchctl state
|
|
61
|
-
const { statusChecker } = await import('../lib/status-checker.js');
|
|
62
|
-
const status = await statusChecker.checkServer(server);
|
|
63
|
-
server.status = status.isRunning ? 'running' : 'stopped';
|
|
64
|
-
server.pid = status.pid || undefined;
|
|
65
|
-
|
|
66
|
-
// Check if server is running
|
|
67
|
-
if (server.status !== 'running') {
|
|
68
|
-
screen.destroy();
|
|
69
|
-
throw new Error(
|
|
70
|
-
`Server ${server.modelName} is not running.\n\n` +
|
|
71
|
-
`Start it first: llamacpp server start ${server.id}`
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Launch single-server TUI
|
|
76
|
-
await createMonitorUI(screen, server);
|
|
77
|
-
} else {
|
|
78
|
-
// Multiple servers - multi-server mode
|
|
79
|
-
// Update all server statuses to reflect actual launchctl state
|
|
80
|
-
const { statusChecker } = await import('../lib/status-checker.js');
|
|
81
|
-
for (const server of allServers) {
|
|
82
|
-
const status = await statusChecker.checkServer(server);
|
|
83
|
-
server.status = status.isRunning ? 'running' : 'stopped';
|
|
84
|
-
server.pid = status.pid || undefined;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Filter to only running servers for monitoring
|
|
88
|
-
const runningServers = allServers.filter(s => s.status === 'running');
|
|
89
|
-
|
|
90
|
-
if (runningServers.length === 0) {
|
|
91
|
-
screen.destroy();
|
|
92
|
-
throw new Error(
|
|
93
|
-
`No servers are currently running.\n\n` +
|
|
94
|
-
`Start a server first:\n` +
|
|
95
|
-
allServers
|
|
96
|
-
.map((s) => ` llamacpp server start ${s.id} # ${s.modelName}`)
|
|
97
|
-
.join('\n')
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Launch multi-server TUI (pass all servers so we can see stopped ones too)
|
|
102
|
-
await createMultiServerMonitorUI(screen, allServers);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Render the screen
|
|
106
|
-
screen.render();
|
|
107
|
-
|
|
108
|
-
// Note: TUI functions handle their own key events and exit directly
|
|
109
|
-
// The process will stay alive until user presses Q/Ctrl+C
|
|
110
|
-
}
|