@appkit/llamacpp-cli 1.1.0 → 1.2.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +95 -16
  3. package/dist/cli.js +38 -8
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/create.d.ts +10 -0
  6. package/dist/commands/create.d.ts.map +1 -0
  7. package/dist/commands/create.js +152 -0
  8. package/dist/commands/create.js.map +1 -0
  9. package/dist/commands/list.js +1 -1
  10. package/dist/commands/list.js.map +1 -1
  11. package/dist/commands/logs.d.ts.map +1 -1
  12. package/dist/commands/logs.js +17 -3
  13. package/dist/commands/logs.js.map +1 -1
  14. package/dist/commands/ps.js +1 -1
  15. package/dist/commands/ps.js.map +1 -1
  16. package/dist/commands/pull.js +1 -1
  17. package/dist/commands/pull.js.map +1 -1
  18. package/dist/commands/run.d.ts +5 -1
  19. package/dist/commands/run.d.ts.map +1 -1
  20. package/dist/commands/run.js +23 -4
  21. package/dist/commands/run.js.map +1 -1
  22. package/dist/commands/server-show.d.ts +2 -0
  23. package/dist/commands/server-show.d.ts.map +1 -0
  24. package/dist/commands/server-show.js +120 -0
  25. package/dist/commands/server-show.js.map +1 -0
  26. package/dist/commands/start.d.ts +1 -10
  27. package/dist/commands/start.d.ts.map +1 -1
  28. package/dist/commands/start.js +31 -121
  29. package/dist/commands/start.js.map +1 -1
  30. package/dist/lib/config-generator.d.ts +1 -2
  31. package/dist/lib/config-generator.d.ts.map +1 -1
  32. package/dist/lib/config-generator.js +3 -6
  33. package/dist/lib/config-generator.js.map +1 -1
  34. package/dist/lib/launchctl-manager.d.ts.map +1 -1
  35. package/dist/lib/launchctl-manager.js +3 -4
  36. package/dist/lib/launchctl-manager.js.map +1 -1
  37. package/dist/types/server-config.d.ts +1 -2
  38. package/dist/types/server-config.d.ts.map +1 -1
  39. package/dist/types/server-config.js.map +1 -1
  40. package/dist/utils/log-parser.d.ts +10 -0
  41. package/dist/utils/log-parser.d.ts.map +1 -1
  42. package/dist/utils/log-parser.js +51 -3
  43. package/dist/utils/log-parser.js.map +1 -1
  44. package/package.json +1 -1
  45. package/src/cli.ts +38 -8
  46. package/src/commands/create.ts +143 -0
  47. package/src/commands/list.ts +1 -1
  48. package/src/commands/logs.ts +20 -3
  49. package/src/commands/ps.ts +1 -1
  50. package/src/commands/pull.ts +1 -1
  51. package/src/commands/run.ts +28 -4
  52. package/src/commands/server-show.ts +125 -0
  53. package/src/commands/start.ts +39 -112
  54. package/src/lib/config-generator.ts +4 -8
  55. package/src/lib/launchctl-manager.ts +4 -3
  56. package/src/types/server-config.ts +1 -2
  57. package/src/utils/log-parser.ts +54 -3
@@ -8,6 +8,16 @@ export declare class LogParser {
8
8
  * Process log lines and output compact format
9
9
  */
10
10
  processLine(line: string, callback: (compactLine: string) => void): void;
11
+ /**
12
+ * Flush any buffered simple format logs
13
+ * Call this at the end of processing to handle simple logs that don't have response lines
14
+ */
15
+ flush(callback: (compactLine: string) => void): void;
16
+ /**
17
+ * Parse simple single-line format (non-verbose mode)
18
+ * Format: srv log_server_r: request: POST /v1/chat/completions 127.0.0.1 200
19
+ */
20
+ private parseSimpleFormat;
11
21
  /**
12
22
  * Consolidate buffered request/response lines into single line
13
23
  */
@@ -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;IAwBxE;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAiD1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;IACH,OAAO,CAAC,WAAW;IAYnB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAoB3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAa1B;AAGD,eAAO,MAAM,SAAS,WAAkB,CAAC"}
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;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAezB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAiD1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;IACH,OAAO,CAAC,WAAW;IAYnB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAoB3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAa1B;AAGD,eAAO,MAAM,SAAS,WAAkB,CAAC"}
@@ -13,8 +13,21 @@ class LogParser {
13
13
  * Process log lines and output compact format
14
14
  */
15
15
  processLine(line, callback) {
16
- // Check if this is the start of an HTTP request log
17
- if (line.includes('log_server_r: request: POST')) {
16
+ // Check if this is a simple single-line format (no JSON, non-verbose mode)
17
+ // Format: srv log_server_r: request: POST /v1/chat/completions 127.0.0.1 200
18
+ if (line.includes('log_server_r: request:') && !line.includes('{')) {
19
+ // Check if this is the start of verbose format (status line before JSON)
20
+ // or a simple single-line log
21
+ if (this.isBuffering) {
22
+ // We're already buffering, so this is a new request - process previous buffer
23
+ const compactLine = this.consolidateRequest(this.buffer);
24
+ if (compactLine) {
25
+ callback(compactLine);
26
+ }
27
+ this.buffer = [];
28
+ this.isBuffering = false;
29
+ }
30
+ // Start buffering (might be verbose or simple)
18
31
  this.isBuffering = true;
19
32
  this.buffer = [line];
20
33
  return;
@@ -22,7 +35,7 @@ class LogParser {
22
35
  // If we're buffering, collect lines
23
36
  if (this.isBuffering) {
24
37
  this.buffer.push(line);
25
- // Check if we have a complete request (found response line)
38
+ // Check if we have a complete request (found response line in verbose mode)
26
39
  if (line.includes('log_server_r: response:')) {
27
40
  const compactLine = this.consolidateRequest(this.buffer);
28
41
  if (compactLine) {
@@ -33,6 +46,41 @@ class LogParser {
33
46
  }
34
47
  }
35
48
  }
49
+ /**
50
+ * Flush any buffered simple format logs
51
+ * Call this at the end of processing to handle simple logs that don't have response lines
52
+ */
53
+ flush(callback) {
54
+ if (this.isBuffering && this.buffer.length > 0) {
55
+ // If we only have one line, it's a simple format log
56
+ if (this.buffer.length === 1) {
57
+ const simpleLine = this.parseSimpleFormat(this.buffer[0]);
58
+ if (simpleLine) {
59
+ callback(simpleLine);
60
+ }
61
+ }
62
+ this.buffer = [];
63
+ this.isBuffering = false;
64
+ }
65
+ }
66
+ /**
67
+ * Parse simple single-line format (non-verbose mode)
68
+ * Format: srv log_server_r: request: POST /v1/chat/completions 127.0.0.1 200
69
+ */
70
+ parseSimpleFormat(line) {
71
+ try {
72
+ const timestamp = this.extractTimestamp(line);
73
+ const requestMatch = line.match(/request: (POST|GET|PUT|DELETE) ([^\s]+) ([^\s]+) (\d+)/);
74
+ if (!requestMatch)
75
+ return null;
76
+ const [, method, endpoint, ip, status] = requestMatch;
77
+ // Simple format doesn't include message/token details
78
+ return `${timestamp} ${method} ${endpoint} ${ip} ${status}`;
79
+ }
80
+ catch (error) {
81
+ return null;
82
+ }
83
+ }
36
84
  /**
37
85
  * Consolidate buffered request/response lines into single line
38
86
  */
@@ -1 +1 @@
1
- {"version":3,"file":"log-parser.js","sourceRoot":"","sources":["../../src/utils/log-parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"log-parser.js","sourceRoot":"","sources":["../../src/utils/log-parser.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appkit/llamacpp-cli",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "CLI tool to manage local llama.cpp servers on macOS",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {
package/src/cli.ts CHANGED
@@ -4,6 +4,7 @@ import { Command } from 'commander';
4
4
  import chalk from 'chalk';
5
5
  import { listCommand } from './commands/list';
6
6
  import { psCommand } from './commands/ps';
7
+ import { createCommand } from './commands/create';
7
8
  import { startCommand } from './commands/start';
8
9
  import { runCommand } from './commands/run';
9
10
  import { stopCommand } from './commands/stop';
@@ -13,6 +14,7 @@ import { rmCommand } from './commands/rm';
13
14
  import { logsCommand } from './commands/logs';
14
15
  import { searchCommand } from './commands/search';
15
16
  import { showCommand } from './commands/show';
17
+ import { serverShowCommand } from './commands/server-show';
16
18
 
17
19
  const program = new Command();
18
20
 
@@ -114,20 +116,47 @@ const server = program
114
116
  .command('server')
115
117
  .description('Manage llama-server instances');
116
118
 
117
- // Start a server
119
+ // Create a new server
118
120
  server
119
- .command('start')
120
- .description('Start a llama-server instance')
121
+ .command('create')
122
+ .description('Create and start a new llama-server instance')
121
123
  .argument('<model>', 'Model filename or path')
122
124
  .option('-p, --port <number>', 'Port number (default: auto-assign)', parseInt)
123
125
  .option('-t, --threads <number>', 'Thread count (default: auto)', parseInt)
124
126
  .option('-c, --ctx-size <number>', 'Context size (default: auto)', parseInt)
125
127
  .option('-g, --gpu-layers <number>', 'GPU layers (default: 60)', parseInt)
126
- .option('-v, --log-verbosity <level>', 'Log verbosity: 0=errors, 1=warnings, 2=info (default), 9=debug, omit for all', parseInt)
127
- .option('--no-log-timestamps', 'Disable timestamps in log messages')
128
+ .option('-v, --verbose', 'Enable verbose HTTP logging (detailed request/response info)')
128
129
  .action(async (model: string, options) => {
129
130
  try {
130
- await startCommand(model, options);
131
+ await createCommand(model, options);
132
+ } catch (error) {
133
+ console.error(chalk.red('āŒ Error:'), (error as Error).message);
134
+ process.exit(1);
135
+ }
136
+ });
137
+
138
+ // Show server details
139
+ server
140
+ .command('show')
141
+ .description('Show server configuration details')
142
+ .argument('<identifier>', 'Server identifier: port (9000), server ID (llama-3-2-3b), or partial model name')
143
+ .action(async (identifier: string) => {
144
+ try {
145
+ await serverShowCommand(identifier);
146
+ } catch (error) {
147
+ console.error(chalk.red('āŒ Error:'), (error as Error).message);
148
+ process.exit(1);
149
+ }
150
+ });
151
+
152
+ // Start an existing server
153
+ server
154
+ .command('start')
155
+ .description('Start an existing stopped server')
156
+ .argument('<identifier>', 'Server identifier: port (9000), server ID (llama-3-2-3b), or partial model name')
157
+ .action(async (identifier: string) => {
158
+ try {
159
+ await startCommand(identifier);
131
160
  } catch (error) {
132
161
  console.error(chalk.red('āŒ Error:'), (error as Error).message);
133
162
  process.exit(1);
@@ -139,9 +168,10 @@ server
139
168
  .command('run')
140
169
  .description('Run an interactive chat session with a model')
141
170
  .argument('<model>', 'Model identifier: port (9000), server ID (llama-3-2-3b), partial name, or model filename')
142
- .action(async (model: string) => {
171
+ .option('-m, --message <text>', 'Send a single message and exit (non-interactive mode)')
172
+ .action(async (model: string, options) => {
143
173
  try {
144
- await runCommand(model);
174
+ await runCommand(model, options);
145
175
  } catch (error) {
146
176
  console.error(chalk.red('āŒ Error:'), (error as Error).message);
147
177
  process.exit(1);
@@ -0,0 +1,143 @@
1
+ import chalk from 'chalk';
2
+ import * as path from 'path';
3
+ import { modelScanner } from '../lib/model-scanner';
4
+ import { stateManager } from '../lib/state-manager';
5
+ import { configGenerator, ServerOptions } from '../lib/config-generator';
6
+ import { portManager } from '../lib/port-manager';
7
+ import { launchctlManager } from '../lib/launchctl-manager';
8
+ import { statusChecker } from '../lib/status-checker';
9
+ import { commandExists } from '../utils/process-utils';
10
+ import { formatBytes } from '../utils/format-utils';
11
+ import { ensureDir } from '../utils/file-utils';
12
+
13
+ interface CreateOptions {
14
+ port?: number;
15
+ threads?: number;
16
+ ctxSize?: number;
17
+ gpuLayers?: number;
18
+ verbose?: boolean;
19
+ }
20
+
21
+ export async function createCommand(model: string, options: CreateOptions): Promise<void> {
22
+ // Initialize state manager
23
+ await stateManager.initialize();
24
+
25
+ // 1. Check if llama-server exists
26
+ if (!(await commandExists('llama-server'))) {
27
+ throw new Error('llama-server not found. Install with: brew install llama.cpp');
28
+ }
29
+
30
+ // 2. Resolve model path
31
+ const modelPath = await modelScanner.resolveModelPath(model);
32
+ if (!modelPath) {
33
+ throw new Error(`Model not found: ${model}\n\nRun: llamacpp list`);
34
+ }
35
+
36
+ const modelName = path.basename(modelPath);
37
+
38
+ // 3. Check if server already exists for this model
39
+ const existingServer = await stateManager.serverExistsForModel(modelPath);
40
+ if (existingServer) {
41
+ throw new Error(`Server already exists for ${modelName}\n\nUse: llamacpp server start ${modelName}`);
42
+ }
43
+
44
+ // 4. Get model size
45
+ const modelSize = await modelScanner.getModelSize(modelName);
46
+ if (!modelSize) {
47
+ throw new Error(`Failed to read model file: ${modelPath}`);
48
+ }
49
+
50
+ // 5. Determine port
51
+ let port: number;
52
+ if (options.port) {
53
+ portManager.validatePort(options.port);
54
+ const available = await portManager.isPortAvailable(options.port);
55
+ if (!available) {
56
+ throw new Error(`Port ${options.port} is already in use`);
57
+ }
58
+ port = options.port;
59
+ } else {
60
+ port = await portManager.findAvailablePort();
61
+ }
62
+
63
+ // 6. Generate server configuration
64
+ console.log(chalk.blue(`šŸš€ Creating server for ${modelName}\n`));
65
+
66
+ const serverOptions: ServerOptions = {
67
+ port: options.port,
68
+ threads: options.threads,
69
+ ctxSize: options.ctxSize,
70
+ gpuLayers: options.gpuLayers,
71
+ verbose: options.verbose,
72
+ };
73
+
74
+ const config = await configGenerator.generateConfig(
75
+ modelPath,
76
+ modelName,
77
+ modelSize,
78
+ port,
79
+ serverOptions
80
+ );
81
+
82
+ // Display configuration
83
+ console.log(chalk.dim(`Model: ${modelPath}`));
84
+ console.log(chalk.dim(`Size: ${formatBytes(modelSize)}`));
85
+ console.log(chalk.dim(`Port: ${config.port}${options.port ? '' : ' (auto-assigned)'}`));
86
+ console.log(chalk.dim(`Threads: ${config.threads}`));
87
+ console.log(chalk.dim(`Context Size: ${config.ctxSize}`));
88
+ console.log(chalk.dim(`GPU Layers: ${config.gpuLayers}`));
89
+ console.log(chalk.dim(`Verbose Logging: ${config.verbose ? 'enabled' : 'disabled'}`));
90
+ console.log();
91
+
92
+ // 7. Ensure log directory exists
93
+ await ensureDir(path.dirname(config.stdoutPath));
94
+
95
+ // 8. Create plist file
96
+ console.log(chalk.dim('Creating launchctl service...'));
97
+ await launchctlManager.createPlist(config);
98
+
99
+ // 9. Load service
100
+ try {
101
+ await launchctlManager.loadService(config.plistPath);
102
+ } catch (error) {
103
+ // Clean up plist if load fails
104
+ await launchctlManager.deletePlist(config.plistPath);
105
+ throw new Error(`Failed to load service: ${(error as Error).message}`);
106
+ }
107
+
108
+ // 10. Start service
109
+ try {
110
+ await launchctlManager.startService(config.label);
111
+ } catch (error) {
112
+ // Clean up if start fails
113
+ await launchctlManager.unloadService(config.plistPath);
114
+ await launchctlManager.deletePlist(config.plistPath);
115
+ throw new Error(`Failed to start service: ${(error as Error).message}`);
116
+ }
117
+
118
+ // 11. Wait for startup
119
+ console.log(chalk.dim('Waiting for server to start...'));
120
+ const started = await launchctlManager.waitForServiceStart(config.label, 5000);
121
+
122
+ if (!started) {
123
+ // Clean up if startup fails
124
+ await launchctlManager.stopService(config.label);
125
+ await launchctlManager.unloadService(config.plistPath);
126
+ await launchctlManager.deletePlist(config.plistPath);
127
+ throw new Error('Server failed to start. Check logs with: llamacpp server logs --errors');
128
+ }
129
+
130
+ // 12. Update config with running status
131
+ const updatedConfig = await statusChecker.updateServerStatus(config);
132
+
133
+ // 13. Save server config
134
+ await stateManager.saveServerConfig(updatedConfig);
135
+
136
+ // 14. Display success message
137
+ console.log();
138
+ console.log(chalk.green('āœ… Server created and started successfully!'));
139
+ console.log();
140
+ console.log(chalk.dim(`Connect: http://localhost:${config.port}`));
141
+ console.log(chalk.dim(`View logs: llamacpp server logs ${config.id}`));
142
+ console.log(chalk.dim(`Stop: llamacpp server stop ${config.id}`));
143
+ }
@@ -33,5 +33,5 @@ export async function listCommand(): Promise<void> {
33
33
 
34
34
  const totalSize = models.reduce((sum, m) => sum + m.size, 0);
35
35
  console.log(chalk.dim(`\nTotal: ${models.length} models (${formatBytes(totalSize)})`));
36
- console.log(chalk.dim(`\nStart a server: llamacpp start <model-filename>`));
36
+ console.log(chalk.dim(`\nCreate a server: llamacpp server create <model-filename>`));
37
37
  }
@@ -63,7 +63,13 @@ export async function logsCommand(identifier: string, options: LogsOptions): Pro
63
63
  }
64
64
 
65
65
  console.log(chalk.blue(`šŸ“‹ Logs for ${server.modelName} (${logType}${filterDesc})`));
66
- console.log(chalk.dim(` ${logPath}\n`));
66
+ console.log(chalk.dim(` ${logPath}`));
67
+
68
+ // Show subtle note if verbose logging is not enabled
69
+ if (!server.verbose && !options.verbose && !options.errors && !options.http && !options.filter) {
70
+ console.log(chalk.dim(` verbosity is disabled`));
71
+ }
72
+ console.log();
67
73
 
68
74
  if (options.follow) {
69
75
  // Follow logs in real-time with optional filtering
@@ -133,15 +139,26 @@ export async function logsCommand(identifier: string, options: LogsOptions): Pro
133
139
  if (useCompactMode) {
134
140
  // Compact mode: read file and parse
135
141
  try {
136
- const command = `tail -n ${lines * 3} "${logPath}" | grep -E "log_server_r"`;
142
+ // Use large multiplier to account for verbose debug output between requests
143
+ const command = `tail -n ${lines * 100} "${logPath}" | grep -E "log_server_r"`;
137
144
  const output = await execCommand(command);
138
145
  const logLines = output.split('\n').filter((l) => l.trim());
139
146
 
147
+ const compactLines: string[] = [];
140
148
  for (const line of logLines) {
141
149
  logParser.processLine(line, (compactLine) => {
142
- console.log(compactLine);
150
+ compactLines.push(compactLine);
143
151
  });
144
152
  }
153
+
154
+ // Flush any remaining buffered logs (handles simple format)
155
+ logParser.flush((compactLine) => {
156
+ compactLines.push(compactLine);
157
+ });
158
+
159
+ // Show only the last N compact lines
160
+ const limitedLines = compactLines.slice(-lines);
161
+ limitedLines.forEach((line) => console.log(line));
145
162
  } catch (error) {
146
163
  throw new Error(`Failed to read logs: ${(error as Error).message}`);
147
164
  }
@@ -10,7 +10,7 @@ export async function psCommand(): Promise<void> {
10
10
 
11
11
  if (servers.length === 0) {
12
12
  console.log(chalk.yellow('No servers configured.'));
13
- console.log(chalk.dim('\nStart a server: llamacpp server start <model-filename>'));
13
+ console.log(chalk.dim('\nCreate a server: llamacpp server create <model-filename>'));
14
14
  return;
15
15
  }
16
16
 
@@ -30,7 +30,7 @@ export async function pullCommand(identifier: string, options: PullOptions): Pro
30
30
  const modelPath = await modelDownloader.downloadModel(parsed.repo, filename);
31
31
 
32
32
  console.log();
33
- console.log(chalk.dim(`Start server: llamacpp start ${filename}`));
33
+ console.log(chalk.dim(`Create server: llamacpp server create ${filename}`));
34
34
  } catch (error) {
35
35
  if ((error as Error).message.includes('interrupted')) {
36
36
  console.log(chalk.dim('\nDownload was interrupted. Run the same command again to retry.'));
@@ -25,7 +25,11 @@ interface ChatCompletionChunk {
25
25
  }>;
26
26
  }
27
27
 
28
- export async function runCommand(modelIdentifier: string): Promise<void> {
28
+ interface RunOptions {
29
+ message?: string;
30
+ }
31
+
32
+ export async function runCommand(modelIdentifier: string, options: RunOptions = {}): Promise<void> {
29
33
  await stateManager.initialize();
30
34
 
31
35
  // 1. Find or start server
@@ -35,7 +39,7 @@ export async function runCommand(modelIdentifier: string): Promise<void> {
35
39
  // Try to resolve as a model name and start it
36
40
  console.log(chalk.blue(`šŸš€ No running server found. Starting ${modelIdentifier}...\n`));
37
41
  try {
38
- await startCommand(modelIdentifier, {});
42
+ await startCommand(modelIdentifier);
39
43
  server = await stateManager.findServer(modelIdentifier);
40
44
  if (!server) {
41
45
  throw new Error('Failed to start server');
@@ -49,10 +53,30 @@ export async function runCommand(modelIdentifier: string): Promise<void> {
49
53
  // 2. Verify server is running
50
54
  const status = await statusChecker.checkServer(server);
51
55
  if (!status.isRunning) {
52
- throw new Error(`Server exists but is not running. Start it with: llamacpp start ${server.id}`);
56
+ throw new Error(`Server exists but is not running. Start it with: llamacpp server start ${server.id}`);
57
+ }
58
+
59
+ // 3. If message provided, do one-shot mode
60
+ if (options.message) {
61
+ const conversationHistory: ChatMessage[] = [
62
+ {
63
+ role: 'user',
64
+ content: options.message,
65
+ },
66
+ ];
67
+
68
+ try {
69
+ await streamChatCompletion(server, conversationHistory);
70
+ console.log(); // Blank line after response
71
+ process.exit(0);
72
+ } catch (error) {
73
+ console.error(chalk.red(`\nāŒ Error: ${(error as Error).message}\n`));
74
+ process.exit(1);
75
+ }
76
+ return;
53
77
  }
54
78
 
55
- // 3. Start REPL
79
+ // 4. Start REPL
56
80
  console.log(chalk.green(`šŸ’¬ Connected to ${server.modelName} (port ${server.port})`));
57
81
  console.log(chalk.dim(`Type your message and press Enter. Use /exit to quit, /clear to reset history, /help for commands.\n`));
58
82
 
@@ -0,0 +1,125 @@
1
+ import chalk from 'chalk';
2
+ import { stateManager } from '../lib/state-manager';
3
+ import { statusChecker } from '../lib/status-checker';
4
+ import { formatUptime, formatBytes } from '../utils/format-utils';
5
+ import { getProcessMemory } from '../utils/process-utils';
6
+
7
+ export async function serverShowCommand(identifier: string): Promise<void> {
8
+ // Find the server
9
+ const server = await stateManager.findServer(identifier);
10
+
11
+ if (!server) {
12
+ console.error(chalk.red(`āŒ Server not found: ${identifier}`));
13
+ console.log(chalk.dim('\nAvailable servers:'));
14
+ const allServers = await stateManager.getAllServers();
15
+ if (allServers.length === 0) {
16
+ console.log(chalk.dim(' (none)'));
17
+ console.log(chalk.dim('\nCreate a server: llamacpp server create <model-filename>'));
18
+ } else {
19
+ allServers.forEach(s => {
20
+ console.log(chalk.dim(` - ${s.id} (port ${s.port})`));
21
+ });
22
+ }
23
+ process.exit(1);
24
+ }
25
+
26
+ // Update status to get real-time info
27
+ console.log(chalk.dim('Checking server status...\n'));
28
+ const updatedServer = await statusChecker.updateServerStatus(server);
29
+
30
+ // Display server information
31
+ console.log(chalk.bold('Server Configuration:'));
32
+ console.log('─'.repeat(70));
33
+
34
+ // Basic info
35
+ console.log(`${chalk.bold('Server ID:')} ${updatedServer.id}`);
36
+ console.log(`${chalk.bold('Model Name:')} ${updatedServer.modelName}`);
37
+ console.log(`${chalk.bold('Model Path:')} ${chalk.dim(updatedServer.modelPath)}`);
38
+ console.log(`${chalk.bold('Port:')} http://localhost:${updatedServer.port}`);
39
+
40
+ // Status with color
41
+ let statusText: string;
42
+ let statusColor: (text: string) => string;
43
+ switch (updatedServer.status) {
44
+ case 'running':
45
+ statusText = 'āœ… RUNNING';
46
+ statusColor = chalk.green;
47
+ break;
48
+ case 'crashed':
49
+ statusText = 'āŒ CRASHED';
50
+ statusColor = chalk.red;
51
+ break;
52
+ default:
53
+ statusText = 'āš ļø STOPPED';
54
+ statusColor = chalk.yellow;
55
+ }
56
+ console.log(`${chalk.bold('Status:')} ${statusColor(statusText)}`);
57
+
58
+ if (updatedServer.pid) {
59
+ console.log(`${chalk.bold('PID:')} ${updatedServer.pid}`);
60
+ }
61
+
62
+ // Runtime info for running servers
63
+ if (updatedServer.status === 'running') {
64
+ if (updatedServer.lastStarted) {
65
+ const uptime = formatUptime(updatedServer.lastStarted);
66
+ console.log(`${chalk.bold('Uptime:')} ${uptime}`);
67
+ }
68
+
69
+ if (updatedServer.pid) {
70
+ const memoryBytes = await getProcessMemory(updatedServer.pid);
71
+ if (memoryBytes !== null) {
72
+ console.log(`${chalk.bold('Memory:')} ${formatBytes(memoryBytes)}`);
73
+ }
74
+ }
75
+ }
76
+
77
+ // Configuration section
78
+ console.log('\n' + '─'.repeat(70));
79
+ console.log(chalk.bold('Configuration:'));
80
+ console.log('─'.repeat(70));
81
+ console.log(`${chalk.bold('Threads:')} ${updatedServer.threads}`);
82
+ console.log(`${chalk.bold('Context Size:')} ${updatedServer.ctxSize.toLocaleString()}`);
83
+ console.log(`${chalk.bold('GPU Layers:')} ${updatedServer.gpuLayers}`);
84
+ console.log(`${chalk.bold('Embeddings:')} ${updatedServer.embeddings ? 'enabled' : 'disabled'}`);
85
+ console.log(`${chalk.bold('Jinja:')} ${updatedServer.jinja ? 'enabled' : 'disabled'}`);
86
+ console.log(`${chalk.bold('Verbose Logs:')} ${updatedServer.verbose ? chalk.green('enabled') : chalk.dim('disabled')}`);
87
+
88
+ // Timestamps section
89
+ console.log('\n' + '─'.repeat(70));
90
+ console.log(chalk.bold('Timestamps:'));
91
+ console.log('─'.repeat(70));
92
+ console.log(`${chalk.bold('Created:')} ${new Date(updatedServer.createdAt).toLocaleString()}`);
93
+ if (updatedServer.lastStarted) {
94
+ console.log(`${chalk.bold('Last Started:')} ${new Date(updatedServer.lastStarted).toLocaleString()}`);
95
+ }
96
+ if (updatedServer.lastStopped) {
97
+ console.log(`${chalk.bold('Last Stopped:')} ${new Date(updatedServer.lastStopped).toLocaleString()}`);
98
+ }
99
+
100
+ // System paths section
101
+ console.log('\n' + '─'.repeat(70));
102
+ console.log(chalk.bold('System Paths:'));
103
+ console.log('─'.repeat(70));
104
+ console.log(`${chalk.bold('Service Label:')} ${updatedServer.label}`);
105
+ console.log(`${chalk.bold('Plist File:')} ${chalk.dim(updatedServer.plistPath)}`);
106
+ console.log(`${chalk.bold('Stdout Log:')} ${chalk.dim(updatedServer.stdoutPath)}`);
107
+ console.log(`${chalk.bold('Stderr Log:')} ${chalk.dim(updatedServer.stderrPath)}`);
108
+
109
+ // Helpful commands
110
+ console.log('\n' + '─'.repeat(70));
111
+ console.log(chalk.bold('Quick Commands:'));
112
+ console.log('─'.repeat(70));
113
+
114
+ if (updatedServer.status === 'running') {
115
+ console.log(chalk.dim(' View logs: ') + `llamacpp server logs ${updatedServer.id}`);
116
+ console.log(chalk.dim(' Interactive chat: ') + `llamacpp server run ${updatedServer.id}`);
117
+ console.log(chalk.dim(' Stop server: ') + `llamacpp server stop ${updatedServer.id}`);
118
+ } else {
119
+ console.log(chalk.dim(' Start server: ') + `llamacpp server start ${updatedServer.id}`);
120
+ if (updatedServer.status === 'crashed') {
121
+ console.log(chalk.dim(' View error logs: ') + `llamacpp server logs ${updatedServer.id} --errors`);
122
+ }
123
+ }
124
+ console.log(chalk.dim(' Remove server: ') + `llamacpp server rm ${updatedServer.id}`);
125
+ }