@appkit/llamacpp-cli 1.12.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.
Files changed (114) hide show
  1. package/README.md +217 -168
  2. package/package.json +10 -2
  3. package/web/dist/assets/index-Bin89Lwr.css +1 -0
  4. package/web/dist/assets/index-CVmonw3T.js +17 -0
  5. package/web/{index.html → dist/index.html} +2 -1
  6. package/.versionrc.json +0 -16
  7. package/CHANGELOG.md +0 -213
  8. package/docs/images/.gitkeep +0 -1
  9. package/docs/images/web-ui-servers.png +0 -0
  10. package/src/cli.ts +0 -523
  11. package/src/commands/admin/config.ts +0 -121
  12. package/src/commands/admin/logs.ts +0 -91
  13. package/src/commands/admin/restart.ts +0 -26
  14. package/src/commands/admin/start.ts +0 -27
  15. package/src/commands/admin/status.ts +0 -84
  16. package/src/commands/admin/stop.ts +0 -16
  17. package/src/commands/config-global.ts +0 -38
  18. package/src/commands/config.ts +0 -323
  19. package/src/commands/create.ts +0 -183
  20. package/src/commands/delete.ts +0 -74
  21. package/src/commands/list.ts +0 -37
  22. package/src/commands/logs-all.ts +0 -251
  23. package/src/commands/logs.ts +0 -345
  24. package/src/commands/monitor.ts +0 -110
  25. package/src/commands/ps.ts +0 -84
  26. package/src/commands/pull.ts +0 -44
  27. package/src/commands/rm.ts +0 -107
  28. package/src/commands/router/config.ts +0 -116
  29. package/src/commands/router/logs.ts +0 -256
  30. package/src/commands/router/restart.ts +0 -36
  31. package/src/commands/router/start.ts +0 -60
  32. package/src/commands/router/status.ts +0 -119
  33. package/src/commands/router/stop.ts +0 -33
  34. package/src/commands/run.ts +0 -233
  35. package/src/commands/search.ts +0 -107
  36. package/src/commands/server-show.ts +0 -161
  37. package/src/commands/show.ts +0 -207
  38. package/src/commands/start.ts +0 -101
  39. package/src/commands/stop.ts +0 -39
  40. package/src/commands/tui.ts +0 -25
  41. package/src/lib/admin-manager.ts +0 -435
  42. package/src/lib/admin-server.ts +0 -1243
  43. package/src/lib/config-generator.ts +0 -130
  44. package/src/lib/download-job-manager.ts +0 -213
  45. package/src/lib/history-manager.ts +0 -172
  46. package/src/lib/launchctl-manager.ts +0 -225
  47. package/src/lib/metrics-aggregator.ts +0 -257
  48. package/src/lib/model-downloader.ts +0 -328
  49. package/src/lib/model-scanner.ts +0 -157
  50. package/src/lib/model-search.ts +0 -114
  51. package/src/lib/models-dir-setup.ts +0 -46
  52. package/src/lib/port-manager.ts +0 -80
  53. package/src/lib/router-logger.ts +0 -201
  54. package/src/lib/router-manager.ts +0 -414
  55. package/src/lib/router-server.ts +0 -538
  56. package/src/lib/state-manager.ts +0 -206
  57. package/src/lib/status-checker.ts +0 -113
  58. package/src/lib/system-collector.ts +0 -315
  59. package/src/tui/ConfigApp.ts +0 -1085
  60. package/src/tui/HistoricalMonitorApp.ts +0 -587
  61. package/src/tui/ModelsApp.ts +0 -368
  62. package/src/tui/MonitorApp.ts +0 -386
  63. package/src/tui/MultiServerMonitorApp.ts +0 -1833
  64. package/src/tui/RootNavigator.ts +0 -74
  65. package/src/tui/SearchApp.ts +0 -511
  66. package/src/tui/SplashScreen.ts +0 -149
  67. package/src/types/admin-config.ts +0 -25
  68. package/src/types/global-config.ts +0 -26
  69. package/src/types/history-types.ts +0 -39
  70. package/src/types/model-info.ts +0 -8
  71. package/src/types/monitor-types.ts +0 -162
  72. package/src/types/router-config.ts +0 -25
  73. package/src/types/server-config.ts +0 -46
  74. package/src/utils/downsample-utils.ts +0 -128
  75. package/src/utils/file-utils.ts +0 -146
  76. package/src/utils/format-utils.ts +0 -98
  77. package/src/utils/log-parser.ts +0 -284
  78. package/src/utils/log-utils.ts +0 -178
  79. package/src/utils/process-utils.ts +0 -316
  80. package/src/utils/prompt-utils.ts +0 -47
  81. package/test-load.sh +0 -100
  82. package/tsconfig.json +0 -20
  83. package/web/eslint.config.js +0 -23
  84. package/web/llamacpp-web-dist.tar.gz +0 -0
  85. package/web/package-lock.json +0 -4017
  86. package/web/package.json +0 -38
  87. package/web/postcss.config.js +0 -6
  88. package/web/src/App.css +0 -42
  89. package/web/src/App.tsx +0 -86
  90. package/web/src/assets/react.svg +0 -1
  91. package/web/src/components/ApiKeyPrompt.tsx +0 -71
  92. package/web/src/components/CreateServerModal.tsx +0 -372
  93. package/web/src/components/DownloadProgress.tsx +0 -123
  94. package/web/src/components/Nav.tsx +0 -89
  95. package/web/src/components/RouterConfigModal.tsx +0 -240
  96. package/web/src/components/SearchModal.tsx +0 -306
  97. package/web/src/components/ServerConfigModal.tsx +0 -291
  98. package/web/src/hooks/useApi.ts +0 -259
  99. package/web/src/index.css +0 -42
  100. package/web/src/lib/api.ts +0 -226
  101. package/web/src/main.tsx +0 -10
  102. package/web/src/pages/Dashboard.tsx +0 -103
  103. package/web/src/pages/Models.tsx +0 -258
  104. package/web/src/pages/Router.tsx +0 -270
  105. package/web/src/pages/RouterLogs.tsx +0 -201
  106. package/web/src/pages/ServerLogs.tsx +0 -553
  107. package/web/src/pages/Servers.tsx +0 -358
  108. package/web/src/types/api.ts +0 -140
  109. package/web/tailwind.config.js +0 -31
  110. package/web/tsconfig.app.json +0 -28
  111. package/web/tsconfig.json +0 -7
  112. package/web/tsconfig.node.json +0 -26
  113. package/web/vite.config.ts +0 -25
  114. /package/web/{public → dist}/vite.svg +0 -0
package/src/cli.ts DELETED
@@ -1,523 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { Command } from 'commander';
4
- import chalk from 'chalk';
5
- import { listCommand } from './commands/list';
6
- import { psCommand } from './commands/ps';
7
- import { createCommand } from './commands/create';
8
- import { startCommand } from './commands/start';
9
- import { runCommand } from './commands/run';
10
- import { stopCommand } from './commands/stop';
11
- import { deleteCommand } from './commands/delete';
12
- import { pullCommand } from './commands/pull';
13
- import { rmCommand } from './commands/rm';
14
- import { logsCommand } from './commands/logs';
15
- import { logsAllCommand } from './commands/logs-all';
16
- import { searchCommand } from './commands/search';
17
- import { showCommand } from './commands/show';
18
- import { serverShowCommand } from './commands/server-show';
19
- import { serverConfigCommand } from './commands/config';
20
- import { configGlobalCommand } from './commands/config-global';
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';
28
- import { adminStartCommand } from './commands/admin/start';
29
- import { adminStopCommand } from './commands/admin/stop';
30
- import { adminStatusCommand } from './commands/admin/status';
31
- import { adminRestartCommand } from './commands/admin/restart';
32
- import { adminConfigCommand } from './commands/admin/config';
33
- import { adminLogsCommand } from './commands/admin/logs';
34
- import packageJson from '../package.json';
35
-
36
- const program = new Command();
37
-
38
- program
39
- .name('llamacpp')
40
- .description('CLI tool to manage local llama.cpp servers on macOS')
41
- .version(packageJson.version, '-v, --version', 'Output the version number')
42
- .action(async () => {
43
- // Default action: launch TUI when no command provided
44
- try {
45
- const { tuiCommand } = await import('./commands/tui');
46
- await tuiCommand();
47
- } catch (error) {
48
- console.error(chalk.red('❌ Error:'), (error as Error).message);
49
- process.exit(1);
50
- }
51
- });
52
-
53
- // List models
54
- program
55
- .command('ls')
56
- .description('List available GGUF models')
57
- .action(async () => {
58
- try {
59
- await listCommand();
60
- } catch (error) {
61
- console.error(chalk.red('❌ Error:'), (error as Error).message);
62
- process.exit(1);
63
- }
64
- });
65
-
66
- // List servers (static table)
67
- program
68
- .command('ps')
69
- .description('List all servers with status (static table)')
70
- .action(async () => {
71
- try {
72
- await psCommand();
73
- } catch (error) {
74
- console.error(chalk.red('❌ Error:'), (error as Error).message);
75
- process.exit(1);
76
- }
77
- });
78
-
79
- // View all server logs
80
- program
81
- .command('logs')
82
- .description('View log sizes for all servers (with batch operations)')
83
- .option('--clear', 'Clear current logs for all servers')
84
- .option('--clear-archived', 'Delete only archived logs for all servers')
85
- .option('--clear-all', 'Clear current + delete archived logs for all servers')
86
- .option('--rotate', 'Rotate logs for all servers with timestamps')
87
- .action(async (options) => {
88
- try {
89
- await logsAllCommand(options);
90
- } catch (error) {
91
- console.error(chalk.red('❌ Error:'), (error as Error).message);
92
- process.exit(1);
93
- }
94
- });
95
-
96
- // Search for models
97
- program
98
- .command('search')
99
- .description('Search Hugging Face for GGUF models')
100
- .argument('<query>', 'Search query (e.g., "llama 3b" or "qwen")')
101
- .option('-l, --limit <number>', 'Max results to show (default: 20)', parseInt)
102
- .option('--files [number]', 'Show available files for result number (e.g., --files 1)', (val) => {
103
- return val ? parseInt(val) : true;
104
- })
105
- .action(async (query: string, options) => {
106
- try {
107
- await searchCommand(query, options);
108
- } catch (error) {
109
- console.error(chalk.red('❌ Error:'), (error as Error).message);
110
- process.exit(1);
111
- }
112
- });
113
-
114
- // Show model details
115
- program
116
- .command('show')
117
- .description('Show details about a model or file')
118
- .argument('<identifier>', 'HuggingFace repo/file (e.g., owner/repo or owner/repo/file.gguf)')
119
- .option('-f, --file <filename>', 'Specific GGUF file to show details for')
120
- .action(async (identifier: string, options) => {
121
- try {
122
- await showCommand(identifier, options);
123
- } catch (error) {
124
- console.error(chalk.red('❌ Error:'), (error as Error).message);
125
- process.exit(1);
126
- }
127
- });
128
-
129
- // Download a model
130
- program
131
- .command('pull')
132
- .description('Download a GGUF model from Hugging Face')
133
- .argument('<identifier>', 'HuggingFace repo/file (e.g., owner/repo/file.gguf or owner/repo)')
134
- .option('-f, --file <filename>', 'Specific GGUF file (alternative to path in identifier)')
135
- .action(async (identifier: string, options) => {
136
- try {
137
- await pullCommand(identifier, options);
138
- } catch (error) {
139
- console.error(chalk.red('❌ Error:'), (error as Error).message);
140
- process.exit(1);
141
- }
142
- });
143
-
144
- // Delete a model
145
- program
146
- .command('rm')
147
- .description('Delete a model file (and any associated servers)')
148
- .argument('<model>', 'Model filename or partial name')
149
- .action(async (model: string) => {
150
- try {
151
- await rmCommand(model);
152
- } catch (error) {
153
- console.error(chalk.red('❌ Error:'), (error as Error).message);
154
- process.exit(1);
155
- }
156
- });
157
-
158
- // Global configuration
159
- program
160
- .command('config')
161
- .description('View or change global configuration')
162
- .option('--models-dir <path>', 'Set models directory path')
163
- .action(async (options) => {
164
- try {
165
- await configGlobalCommand(options);
166
- } catch (error) {
167
- console.error(chalk.red('❌ Error:'), (error as Error).message);
168
- process.exit(1);
169
- }
170
- });
171
-
172
- // Server management commands
173
- const server = program
174
- .command('server')
175
- .description('Manage llama-server instances');
176
-
177
- // Create a new server
178
- server
179
- .command('create')
180
- .description('Create and start a new llama-server instance')
181
- .argument('<model>', 'Model filename or path')
182
- .option('-p, --port <number>', 'Port number (default: auto-assign)', parseInt)
183
- .option('-h, --host <address>', 'Bind address (default: 127.0.0.1, use 0.0.0.0 for remote access)')
184
- .option('-t, --threads <number>', 'Thread count (default: auto)', parseInt)
185
- .option('-c, --ctx-size <number>', 'Context size (default: auto)', parseInt)
186
- .option('-g, --gpu-layers <number>', 'GPU layers (default: 60)', parseInt)
187
- .option('-v, --verbose', 'Enable verbose HTTP logging (detailed request/response info)')
188
- .option('-f, --flags <flags>', 'Additional llama-server flags (comma-separated, e.g., "--pooling,mean")')
189
- .action(async (model: string, options) => {
190
- try {
191
- await createCommand(model, options);
192
- } catch (error) {
193
- console.error(chalk.red('❌ Error:'), (error as Error).message);
194
- process.exit(1);
195
- }
196
- });
197
-
198
- // Show server details
199
- server
200
- .command('show')
201
- .description('Show server configuration details')
202
- .argument('<identifier>', 'Server identifier: port (9000), server ID (llama-3-2-3b), or partial model name')
203
- .action(async (identifier: string) => {
204
- try {
205
- await serverShowCommand(identifier);
206
- } catch (error) {
207
- console.error(chalk.red('❌ Error:'), (error as Error).message);
208
- process.exit(1);
209
- }
210
- });
211
-
212
- // Update server configuration
213
- server
214
- .command('config')
215
- .description('Update server configuration parameters')
216
- .argument('<identifier>', 'Server identifier: port (9000), server ID (llama-3-2-3b), or partial model name')
217
- .option('-m, --model <filename>', 'Update model (filename or path)')
218
- .option('-h, --host <address>', 'Update bind address (127.0.0.1 for localhost, 0.0.0.0 for remote access)')
219
- .option('-t, --threads <number>', 'Update thread count', parseInt)
220
- .option('-c, --ctx-size <number>', 'Update context size', parseInt)
221
- .option('-g, --gpu-layers <number>', 'Update GPU layers', parseInt)
222
- .option('-v, --verbose', 'Enable verbose logging')
223
- .option('--no-verbose', 'Disable verbose logging')
224
- .option('-f, --flags <flags>', 'Update custom llama-server flags (comma-separated, empty string to clear)')
225
- .option('-r, --restart', 'Automatically restart server if running')
226
- .action(async (identifier: string, options) => {
227
- try {
228
- await serverConfigCommand(identifier, options);
229
- } catch (error) {
230
- console.error(chalk.red('❌ Error:'), (error as Error).message);
231
- process.exit(1);
232
- }
233
- });
234
-
235
- // Start an existing server
236
- server
237
- .command('start')
238
- .description('Start an existing stopped server')
239
- .argument('<identifier>', 'Server identifier: port (9000), server ID (llama-3-2-3b), or partial model name')
240
- .action(async (identifier: string) => {
241
- try {
242
- await startCommand(identifier);
243
- } catch (error) {
244
- console.error(chalk.red('❌ Error:'), (error as Error).message);
245
- process.exit(1);
246
- }
247
- });
248
-
249
- // Run interactive chat with a model
250
- server
251
- .command('run')
252
- .description('Run an interactive chat session with a model')
253
- .argument('<model>', 'Model identifier: port (9000), server ID (llama-3-2-3b), partial name, or model filename')
254
- .option('-m, --message <text>', 'Send a single message and exit (non-interactive mode)')
255
- .action(async (model: string, options) => {
256
- try {
257
- await runCommand(model, options);
258
- } catch (error) {
259
- console.error(chalk.red('❌ Error:'), (error as Error).message);
260
- process.exit(1);
261
- }
262
- });
263
-
264
- // Stop a server
265
- server
266
- .command('stop')
267
- .description('Stop a running server')
268
- .argument('<identifier>', 'Server identifier: port (9000), server ID (llama-3-2-3b), or partial model name')
269
- .action(async (identifier: string) => {
270
- try {
271
- await stopCommand(identifier);
272
- } catch (error) {
273
- console.error(chalk.red('❌ Error:'), (error as Error).message);
274
- process.exit(1);
275
- }
276
- });
277
-
278
- // Delete a server
279
- server
280
- .command('rm')
281
- .description('Remove a server configuration and launchctl service (preserves model file)')
282
- .argument('<identifier>', 'Server identifier: port (9000), server ID (llama-3-2-3b), or partial model name')
283
- .action(async (identifier: string) => {
284
- try {
285
- await deleteCommand(identifier);
286
- } catch (error) {
287
- console.error(chalk.red('❌ Error:'), (error as Error).message);
288
- process.exit(1);
289
- }
290
- });
291
-
292
- // View logs
293
- server
294
- .command('logs')
295
- .description('View server logs (default: compact one-line per request)')
296
- .argument('<identifier>', 'Server identifier: port (9000), server ID (llama-3-2-3b), or partial model name')
297
- .option('-f, --follow', 'Follow log output in real-time')
298
- .option('-n, --lines <number>', 'Number of lines to show (default: 50)', parseInt)
299
- .option('--http', 'Show full HTTP JSON request/response logs')
300
- .option('--errors', 'Show only error messages')
301
- .option('--verbose', 'Show all messages including debug internals')
302
- .option('--filter <pattern>', 'Custom grep pattern for filtering')
303
- .option('--stdout', 'Show stdout instead of stderr (rarely needed)')
304
- .option('--clear', 'Clear (truncate) log file to zero bytes')
305
- .option('--clear-archived', 'Delete only archived logs (preserves current logs)')
306
- .option('--clear-all', 'Clear current logs AND delete all archived logs')
307
- .option('--rotate', 'Rotate log file with timestamp (preserves old logs)')
308
- .option('--include-health', 'Include health check requests (/health, /slots, /props) - filtered by default')
309
- .action(async (identifier: string, options) => {
310
- try {
311
- await logsCommand(identifier, options);
312
- } catch (error) {
313
- console.error(chalk.red('❌ Error:'), (error as Error).message);
314
- process.exit(1);
315
- }
316
- });
317
-
318
- // Monitor server (deprecated - redirects to TUI)
319
- server
320
- .command('monitor [identifier]')
321
- .description('Monitor server with real-time metrics TUI (deprecated: use "llamacpp" instead)')
322
- .action(async (identifier?: string) => {
323
- try {
324
- console.log(chalk.yellow('⚠️ The "monitor" command is deprecated and will be removed in a future version.'));
325
- console.log(chalk.dim(' Please use "llamacpp" instead for the same functionality.\n'));
326
- await monitorCommand(identifier);
327
- } catch (error) {
328
- console.error(chalk.red('❌ Error:'), (error as Error).message);
329
- process.exit(1);
330
- }
331
- });
332
-
333
- // Router management commands
334
- const router = program
335
- .command('router')
336
- .description('Manage the unified router endpoint');
337
-
338
- // Start router
339
- router
340
- .command('start')
341
- .description('Start the router service')
342
- .action(async () => {
343
- try {
344
- await routerStartCommand();
345
- } catch (error) {
346
- console.error(chalk.red('❌ Error:'), (error as Error).message);
347
- process.exit(1);
348
- }
349
- });
350
-
351
- // Stop router
352
- router
353
- .command('stop')
354
- .description('Stop the router service')
355
- .action(async () => {
356
- try {
357
- await routerStopCommand();
358
- } catch (error) {
359
- console.error(chalk.red('❌ Error:'), (error as Error).message);
360
- process.exit(1);
361
- }
362
- });
363
-
364
- // Show router status
365
- router
366
- .command('status')
367
- .description('Show router status and configuration')
368
- .action(async () => {
369
- try {
370
- await routerStatusCommand();
371
- } catch (error) {
372
- console.error(chalk.red('❌ Error:'), (error as Error).message);
373
- process.exit(1);
374
- }
375
- });
376
-
377
- // Restart router
378
- router
379
- .command('restart')
380
- .description('Restart the router service')
381
- .action(async () => {
382
- try {
383
- await routerRestartCommand();
384
- } catch (error) {
385
- console.error(chalk.red('❌ Error:'), (error as Error).message);
386
- process.exit(1);
387
- }
388
- });
389
-
390
- // Configure router
391
- router
392
- .command('config')
393
- .description('Update router configuration')
394
- .option('-p, --port <number>', 'Update port number', parseInt)
395
- .option('-h, --host <address>', 'Update bind address')
396
- .option('--timeout <ms>', 'Update request timeout (milliseconds)', parseInt)
397
- .option('--health-interval <ms>', 'Update health check interval (milliseconds)', parseInt)
398
- .option('-v, --verbose [boolean]', 'Enable/disable verbose logging to file (true/false)', (val) => val === 'true' || val === '1')
399
- .option('-r, --restart', 'Automatically restart router if running')
400
- .action(async (options) => {
401
- try {
402
- await routerConfigCommand(options);
403
- } catch (error) {
404
- console.error(chalk.red('❌ Error:'), (error as Error).message);
405
- process.exit(1);
406
- }
407
- });
408
-
409
- // Router logs
410
- router
411
- .command('logs')
412
- .description('View router logs')
413
- .option('-f, --follow', 'Follow logs in real-time (like tail -f)')
414
- .option('-n, --lines <number>', 'Number of lines to show (default: 50)', parseInt)
415
- .option('--stderr', 'Show system logs (stderr) instead of activity logs (stdout)')
416
- .option('-v, --verbose', 'Show verbose JSON log file (if enabled)')
417
- .option('--clear', 'Clear the log file')
418
- .option('--rotate', 'Rotate the log file with timestamp')
419
- .option('--clear-all', 'Clear all router logs (activity, system, verbose)')
420
- .action(async (options) => {
421
- try {
422
- await routerLogsCommand(options);
423
- } catch (error) {
424
- console.error(chalk.red('❌ Error:'), (error as Error).message);
425
- process.exit(1);
426
- }
427
- });
428
-
429
- // Admin management commands
430
- const admin = program
431
- .command('admin')
432
- .description('Manage the admin REST API service');
433
-
434
- // Start admin
435
- admin
436
- .command('start')
437
- .description('Start the admin service')
438
- .action(async () => {
439
- try {
440
- await adminStartCommand();
441
- } catch (error) {
442
- console.error(chalk.red('❌ Error:'), (error as Error).message);
443
- process.exit(1);
444
- }
445
- });
446
-
447
- // Stop admin
448
- admin
449
- .command('stop')
450
- .description('Stop the admin service')
451
- .action(async () => {
452
- try {
453
- await adminStopCommand();
454
- } catch (error) {
455
- console.error(chalk.red('❌ Error:'), (error as Error).message);
456
- process.exit(1);
457
- }
458
- });
459
-
460
- // Show admin status
461
- admin
462
- .command('status')
463
- .description('Show admin service status and configuration')
464
- .action(async () => {
465
- try {
466
- await adminStatusCommand();
467
- } catch (error) {
468
- console.error(chalk.red('❌ Error:'), (error as Error).message);
469
- process.exit(1);
470
- }
471
- });
472
-
473
- // Restart admin
474
- admin
475
- .command('restart')
476
- .description('Restart the admin service')
477
- .action(async () => {
478
- try {
479
- await adminRestartCommand();
480
- } catch (error) {
481
- console.error(chalk.red('❌ Error:'), (error as Error).message);
482
- process.exit(1);
483
- }
484
- });
485
-
486
- // Configure admin
487
- admin
488
- .command('config')
489
- .description('Update admin service configuration')
490
- .option('-p, --port <number>', 'Update port number', parseInt)
491
- .option('-h, --host <address>', 'Update bind address')
492
- .option('--regenerate-key', 'Generate a new API key')
493
- .option('-v, --verbose [boolean]', 'Enable/disable verbose logging', (val) => val === 'true' || val === '1')
494
- .option('-r, --restart', 'Automatically restart admin service if running')
495
- .action(async (options) => {
496
- try {
497
- await adminConfigCommand(options);
498
- } catch (error) {
499
- console.error(chalk.red('❌ Error:'), (error as Error).message);
500
- process.exit(1);
501
- }
502
- });
503
-
504
- // Admin logs
505
- admin
506
- .command('logs')
507
- .description('View admin service logs')
508
- .option('-f, --follow', 'Follow logs in real-time (like tail -f)')
509
- .option('-n, --lines <number>', 'Number of lines to show (default: 100)', parseInt)
510
- .option('--stdout', 'Show activity logs (stdout)')
511
- .option('--stderr', 'Show system logs (stderr)')
512
- .option('--clear', 'Clear the log files')
513
- .action(async (options) => {
514
- try {
515
- await adminLogsCommand(options);
516
- } catch (error) {
517
- console.error(chalk.red('❌ Error:'), (error as Error).message);
518
- process.exit(1);
519
- }
520
- });
521
-
522
- // Parse arguments
523
- program.parse();
@@ -1,121 +0,0 @@
1
- import chalk from 'chalk';
2
- import { adminManager } from '../../lib/admin-manager';
3
-
4
- interface ConfigOptions {
5
- port?: number;
6
- host?: string;
7
- regenerateKey?: boolean;
8
- verbose?: boolean;
9
- restart?: boolean;
10
- }
11
-
12
- export async function adminConfigCommand(options: ConfigOptions): Promise<void> {
13
- try {
14
- const result = await adminManager.getStatus();
15
-
16
- if (!result) {
17
- console.error(chalk.red('✗ Admin service is not configured'));
18
- console.log(chalk.gray('\nRun: llamacpp admin start'));
19
- process.exit(1);
20
- }
21
-
22
- const { config, status } = result;
23
-
24
- // Check if any options were provided
25
- const hasChanges = options.port || options.host || options.regenerateKey !== undefined || options.verbose !== undefined;
26
- if (!hasChanges) {
27
- console.error(chalk.red('✗ No configuration options provided'));
28
- console.log(chalk.gray('\nAvailable options:'));
29
- console.log(chalk.gray(' --port <port> Change port'));
30
- console.log(chalk.gray(' --host <host> Change host'));
31
- console.log(chalk.gray(' --regenerate-key Generate new API key'));
32
- console.log(chalk.gray(' --verbose Enable verbose logging'));
33
- console.log(chalk.gray(' --restart Restart after config change'));
34
- process.exit(1);
35
- }
36
-
37
- // Display what will change
38
- console.log(chalk.bold('Configuration Changes:'));
39
- console.log();
40
-
41
- const updates: Partial<typeof config> = {};
42
-
43
- if (options.port !== undefined) {
44
- console.log(chalk.bold(' Port: '), chalk.gray(config.port.toString()), chalk.gray('→'), chalk.cyan(options.port.toString()));
45
- updates.port = options.port;
46
- }
47
-
48
- if (options.host !== undefined) {
49
- console.log(chalk.bold(' Host: '), chalk.gray(config.host), chalk.gray('→'), chalk.cyan(options.host));
50
- updates.host = options.host;
51
-
52
- // Warn if binding to non-localhost
53
- if (options.host !== '127.0.0.1' && options.host !== 'localhost') {
54
- console.log();
55
- console.log(chalk.yellow(' ⚠ Warning: Binding to non-localhost address exposes admin API to network'));
56
- console.log(chalk.yellow(' ⚠ Ensure your firewall is properly configured'));
57
- }
58
- }
59
-
60
- if (options.verbose !== undefined) {
61
- console.log(chalk.bold(' Verbose: '), chalk.gray(config.verbose ? 'enabled' : 'disabled'), chalk.gray('→'), chalk.cyan(options.verbose ? 'enabled' : 'disabled'));
62
- updates.verbose = options.verbose;
63
- }
64
-
65
- let newApiKey: string | undefined;
66
- if (options.regenerateKey) {
67
- newApiKey = await adminManager.regenerateApiKey();
68
- console.log(chalk.bold(' API Key: '), chalk.gray('*********************'), chalk.gray('→'), chalk.yellow(newApiKey));
69
- }
70
-
71
- console.log();
72
-
73
- // Check if restart is needed
74
- const isRunning = status.isRunning;
75
- const needsRestart = isRunning && (options.port !== undefined || options.host !== undefined);
76
-
77
- if (needsRestart && !options.restart) {
78
- console.log(chalk.yellow('⚠ Admin service is running. Changes require restart.'));
79
- console.log(chalk.gray(' Add --restart flag to restart automatically\n'));
80
- }
81
-
82
- // Apply changes
83
- if (Object.keys(updates).length > 0) {
84
- await adminManager.updateConfig(updates);
85
- }
86
-
87
- // Restart if requested and needed
88
- if (options.restart && needsRestart) {
89
- console.log(chalk.blue('🔄 Restarting admin service...\n'));
90
-
91
- // Regenerate plist with new config
92
- const updatedConfig = await adminManager.loadConfig();
93
- if (updatedConfig) {
94
- await adminManager.createPlist(updatedConfig);
95
- }
96
-
97
- await adminManager.restart();
98
-
99
- console.log(chalk.green('✓ Admin service restarted successfully'));
100
- } else {
101
- console.log(chalk.green('✓ Configuration updated'));
102
-
103
- if (needsRestart && !options.restart) {
104
- console.log(chalk.gray('\nRestart with: llamacpp admin restart'));
105
- }
106
- }
107
-
108
- console.log();
109
-
110
- // Show new API key prominently if regenerated
111
- if (newApiKey) {
112
- console.log(chalk.bold('New API Key:'), chalk.yellow(newApiKey));
113
- console.log(chalk.gray('Store this key securely - it cannot be retrieved later'));
114
- console.log();
115
- }
116
- } catch (error) {
117
- console.error(chalk.red('✗ Failed to update admin configuration'));
118
- console.error(chalk.gray((error as Error).message));
119
- process.exit(1);
120
- }
121
- }