@appkit/llamacpp-cli 1.5.0 → 1.7.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 (124) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/MONITORING-ACCURACY-FIX.md +199 -0
  3. package/PER-PROCESS-METRICS.md +190 -0
  4. package/README.md +124 -9
  5. package/dist/cli.js +32 -7
  6. package/dist/cli.js.map +1 -1
  7. package/dist/commands/config.d.ts.map +1 -1
  8. package/dist/commands/config.js +15 -1
  9. package/dist/commands/config.js.map +1 -1
  10. package/dist/commands/create.d.ts.map +1 -1
  11. package/dist/commands/create.js +12 -4
  12. package/dist/commands/create.js.map +1 -1
  13. package/dist/commands/delete.js +12 -10
  14. package/dist/commands/delete.js.map +1 -1
  15. package/dist/commands/logs-all.d.ts +9 -0
  16. package/dist/commands/logs-all.d.ts.map +1 -0
  17. package/dist/commands/logs-all.js +209 -0
  18. package/dist/commands/logs-all.js.map +1 -0
  19. package/dist/commands/logs.d.ts +4 -0
  20. package/dist/commands/logs.d.ts.map +1 -1
  21. package/dist/commands/logs.js +108 -2
  22. package/dist/commands/logs.js.map +1 -1
  23. package/dist/commands/monitor.d.ts.map +1 -1
  24. package/dist/commands/monitor.js +51 -1
  25. package/dist/commands/monitor.js.map +1 -1
  26. package/dist/commands/ps.d.ts +3 -1
  27. package/dist/commands/ps.d.ts.map +1 -1
  28. package/dist/commands/ps.js +75 -5
  29. package/dist/commands/ps.js.map +1 -1
  30. package/dist/commands/rm.d.ts.map +1 -1
  31. package/dist/commands/rm.js +5 -12
  32. package/dist/commands/rm.js.map +1 -1
  33. package/dist/commands/server-show.d.ts.map +1 -1
  34. package/dist/commands/server-show.js +30 -3
  35. package/dist/commands/server-show.js.map +1 -1
  36. package/dist/commands/start.d.ts.map +1 -1
  37. package/dist/commands/start.js +34 -7
  38. package/dist/commands/start.js.map +1 -1
  39. package/dist/commands/stop.js +3 -3
  40. package/dist/commands/stop.js.map +1 -1
  41. package/dist/lib/history-manager.d.ts +46 -0
  42. package/dist/lib/history-manager.d.ts.map +1 -0
  43. package/dist/lib/history-manager.js +157 -0
  44. package/dist/lib/history-manager.js.map +1 -0
  45. package/dist/lib/metrics-aggregator.d.ts +2 -1
  46. package/dist/lib/metrics-aggregator.d.ts.map +1 -1
  47. package/dist/lib/metrics-aggregator.js +15 -4
  48. package/dist/lib/metrics-aggregator.js.map +1 -1
  49. package/dist/lib/system-collector.d.ts +9 -4
  50. package/dist/lib/system-collector.d.ts.map +1 -1
  51. package/dist/lib/system-collector.js +29 -28
  52. package/dist/lib/system-collector.js.map +1 -1
  53. package/dist/tui/HistoricalMonitorApp.d.ts +5 -0
  54. package/dist/tui/HistoricalMonitorApp.d.ts.map +1 -0
  55. package/dist/tui/HistoricalMonitorApp.js +490 -0
  56. package/dist/tui/HistoricalMonitorApp.js.map +1 -0
  57. package/dist/tui/MonitorApp.d.ts.map +1 -1
  58. package/dist/tui/MonitorApp.js +84 -62
  59. package/dist/tui/MonitorApp.js.map +1 -1
  60. package/dist/tui/MultiServerMonitorApp.d.ts +1 -1
  61. package/dist/tui/MultiServerMonitorApp.d.ts.map +1 -1
  62. package/dist/tui/MultiServerMonitorApp.js +293 -77
  63. package/dist/tui/MultiServerMonitorApp.js.map +1 -1
  64. package/dist/types/history-types.d.ts +30 -0
  65. package/dist/types/history-types.d.ts.map +1 -0
  66. package/dist/types/history-types.js +11 -0
  67. package/dist/types/history-types.js.map +1 -0
  68. package/dist/types/monitor-types.d.ts +1 -0
  69. package/dist/types/monitor-types.d.ts.map +1 -1
  70. package/dist/types/server-config.d.ts +1 -0
  71. package/dist/types/server-config.d.ts.map +1 -1
  72. package/dist/types/server-config.js.map +1 -1
  73. package/dist/utils/downsample-utils.d.ts +35 -0
  74. package/dist/utils/downsample-utils.d.ts.map +1 -0
  75. package/dist/utils/downsample-utils.js +107 -0
  76. package/dist/utils/downsample-utils.js.map +1 -0
  77. package/dist/utils/file-utils.d.ts +6 -0
  78. package/dist/utils/file-utils.d.ts.map +1 -1
  79. package/dist/utils/file-utils.js +38 -0
  80. package/dist/utils/file-utils.js.map +1 -1
  81. package/dist/utils/log-utils.d.ts +43 -0
  82. package/dist/utils/log-utils.d.ts.map +1 -0
  83. package/dist/utils/log-utils.js +190 -0
  84. package/dist/utils/log-utils.js.map +1 -0
  85. package/dist/utils/process-utils.d.ts +19 -1
  86. package/dist/utils/process-utils.d.ts.map +1 -1
  87. package/dist/utils/process-utils.js +79 -1
  88. package/dist/utils/process-utils.js.map +1 -1
  89. package/docs/images/.gitkeep +1 -0
  90. package/package.json +3 -1
  91. package/src/cli.ts +32 -7
  92. package/src/commands/config.ts +15 -1
  93. package/src/commands/create.ts +14 -5
  94. package/src/commands/delete.ts +10 -10
  95. package/src/commands/logs-all.ts +251 -0
  96. package/src/commands/logs.ts +138 -2
  97. package/src/commands/monitor.ts +21 -1
  98. package/src/commands/ps.ts +88 -5
  99. package/src/commands/rm.ts +5 -12
  100. package/src/commands/server-show.ts +35 -3
  101. package/src/commands/start.ts +35 -7
  102. package/src/commands/stop.ts +3 -3
  103. package/src/lib/history-manager.ts +172 -0
  104. package/src/lib/metrics-aggregator.ts +18 -5
  105. package/src/lib/system-collector.ts +31 -28
  106. package/src/tui/HistoricalMonitorApp.ts +548 -0
  107. package/src/tui/MonitorApp.ts +89 -64
  108. package/src/tui/MultiServerMonitorApp.ts +348 -103
  109. package/src/types/history-types.ts +39 -0
  110. package/src/types/monitor-types.ts +1 -0
  111. package/src/types/server-config.ts +1 -0
  112. package/src/utils/downsample-utils.ts +128 -0
  113. package/src/utils/file-utils.ts +40 -0
  114. package/src/utils/log-utils.ts +178 -0
  115. package/src/utils/process-utils.ts +85 -1
  116. package/test-load.sh +100 -0
  117. package/dist/tui/components/ErrorState.d.ts +0 -8
  118. package/dist/tui/components/ErrorState.d.ts.map +0 -1
  119. package/dist/tui/components/ErrorState.js +0 -22
  120. package/dist/tui/components/ErrorState.js.map +0 -1
  121. package/dist/tui/components/LoadingState.d.ts +0 -8
  122. package/dist/tui/components/LoadingState.d.ts.map +0 -1
  123. package/dist/tui/components/LoadingState.js +0 -21
  124. package/dist/tui/components/LoadingState.js.map +0 -1
@@ -2,6 +2,8 @@ import blessed from 'blessed';
2
2
  import { ServerConfig } from '../types/server-config.js';
3
3
  import { MetricsAggregator } from '../lib/metrics-aggregator.js';
4
4
  import { MonitorData } from '../types/monitor-types.js';
5
+ import { HistoryManager } from '../lib/history-manager.js';
6
+ import { createHistoricalUI } from './HistoricalMonitorApp.js';
5
7
 
6
8
  export async function createMonitorUI(
7
9
  screen: blessed.Widgets.Screen,
@@ -13,6 +15,7 @@ export async function createMonitorUI(
13
15
  let lastGoodData: MonitorData | null = null;
14
16
  const STALE_THRESHOLD = 5;
15
17
  const metricsAggregator = new MetricsAggregator(server);
18
+ const historyManager = new HistoryManager(server.id);
16
19
 
17
20
  // Single scrollable content box
18
21
  const contentBox = blessed.box({
@@ -51,13 +54,21 @@ export async function createMonitorUI(
51
54
  consecutiveFailures = 0;
52
55
  lastGoodData = data;
53
56
 
57
+ // Append to history (silent failure)
58
+ // Only save history for servers that are healthy and not stale
59
+ if (!data.server.stale && data.server.healthy) {
60
+ historyManager.appendSnapshot(data.server, data.system).catch(() => {
61
+ // Don't interrupt monitoring on history write failure
62
+ });
63
+ }
64
+
54
65
  const termWidth = (screen.width as number) || 80;
55
66
  const divider = '─'.repeat(termWidth - 2); // Account for padding
56
67
 
57
68
  let content = '';
58
69
 
59
70
  // Header
60
- content += '{bold}{blue-fg}═══ llama.cpp Server Monitor ═══{/blue-fg}{/bold}\n\n';
71
+ content += `{bold}{blue-fg}═══ ${server.modelName} (${server.port}){/blue-fg}{/bold}\n\n`;
61
72
 
62
73
  // Server Info
63
74
  content += '{bold}Server Information{/bold}\n';
@@ -122,44 +133,40 @@ export async function createMonitorUI(
122
133
  }
123
134
  }
124
135
 
125
- // System Resources
126
- content += '{bold}System Resources{/bold}\n';
136
+ // Model Resources (per-process metrics)
137
+ content += '{bold}Model Resources{/bold}\n';
127
138
  content += divider + '\n';
128
139
 
129
- if (data.system) {
130
- if (data.system.gpuUsage !== undefined) {
131
- const bar = createProgressBar(data.system.gpuUsage);
132
- content += `GPU: {cyan-fg}${bar}{/cyan-fg} ${Math.round(data.system.gpuUsage)}%`;
133
-
134
- if (data.system.temperature !== undefined) {
135
- content += ` - ${Math.round(data.system.temperature)}°C`;
136
- }
140
+ // GPU: System-wide (can't get per-process on macOS)
141
+ if (data.system && data.system.gpuUsage !== undefined) {
142
+ const bar = createProgressBar(data.system.gpuUsage);
143
+ content += `GPU: {cyan-fg}${bar}{/cyan-fg} ${Math.round(data.system.gpuUsage)}% {gray-fg}(system){/gray-fg}`;
137
144
 
138
- content += '\n';
145
+ if (data.system.temperature !== undefined) {
146
+ content += ` - ${Math.round(data.system.temperature)}°C`;
139
147
  }
140
148
 
141
- if (data.system.cpuUsage !== undefined) {
142
- const bar = createProgressBar(data.system.cpuUsage);
143
- content += `CPU: {cyan-fg}${bar}{/cyan-fg} ${Math.round(data.system.cpuUsage)}%\n`;
144
- }
149
+ content += '\n';
150
+ }
145
151
 
146
- if (data.system.aneUsage !== undefined && data.system.aneUsage > 1) {
147
- const bar = createProgressBar(data.system.aneUsage);
148
- content += `ANE: {cyan-fg}${bar}{/cyan-fg} ${Math.round(data.system.aneUsage)}%\n`;
149
- }
152
+ // CPU: Per-process
153
+ if (data.server.processCpuUsage !== undefined) {
154
+ const bar = createProgressBar(data.server.processCpuUsage);
155
+ content += `CPU: {cyan-fg}${bar}{/cyan-fg} ${Math.round(data.server.processCpuUsage)}%\n`;
156
+ }
150
157
 
151
- if (data.system.memoryTotal > 0) {
152
- const memoryUsedGB = data.system.memoryUsed / (1024 ** 3);
153
- const memoryTotalGB = data.system.memoryTotal / (1024 ** 3);
154
- const memoryPercentage = (data.system.memoryUsed / data.system.memoryTotal) * 100;
155
- const bar = createProgressBar(memoryPercentage);
156
- content += `Memory: {cyan-fg}${bar}{/cyan-fg} ${Math.round(memoryPercentage)}% `;
157
- content += `(${memoryUsedGB.toFixed(1)} / ${memoryTotalGB.toFixed(1)} GB)\n`;
158
- }
158
+ // Memory: Per-process
159
+ if (data.server.processMemory !== undefined) {
160
+ const memoryGB = data.server.processMemory / (1024 ** 3);
161
+ // For progress bar, estimate against typical model sizes (e.g., 8GB max)
162
+ const estimatedMax = 8;
163
+ const memoryPercentage = Math.min((memoryGB / estimatedMax) * 100, 100);
164
+ const bar = createProgressBar(memoryPercentage);
165
+ content += `Memory: {cyan-fg}${bar}{/cyan-fg} ${memoryGB.toFixed(2)} GB\n`;
166
+ }
159
167
 
160
- if (data.system.warnings && data.system.warnings.length > 0) {
161
- content += `\n{yellow-fg}⚠ ${data.system.warnings.join(', ')}{/yellow-fg}\n`;
162
- }
168
+ if (data.system && data.system.warnings && data.system.warnings.length > 0) {
169
+ content += `\n{yellow-fg}⚠ ${data.system.warnings.join(', ')}{/yellow-fg}\n`;
163
170
  }
164
171
 
165
172
  content += '\n';
@@ -168,7 +175,7 @@ export async function createMonitorUI(
168
175
  content += divider + '\n';
169
176
  content += `{gray-fg}Updated: ${data.lastUpdated.toLocaleTimeString()} | `;
170
177
  content += `Interval: ${updateInterval}ms | `;
171
- content += `[R]efresh [+/-]Speed [Q]uit{/gray-fg}`;
178
+ content += `[H]istory [R]efresh [+/-]Speed [Q]uit{/gray-fg}`;
172
179
 
173
180
  contentBox.setContent(content);
174
181
  screen.render();
@@ -185,7 +192,7 @@ export async function createMonitorUI(
185
192
  let content = '';
186
193
 
187
194
  // Header with stale warning
188
- content += '{bold}{blue-fg}═══ llama.cpp Server Monitor ═══{/blue-fg}{/bold}\n';
195
+ content += `{bold}{blue-fg}═══ ${server.modelName} (${server.port}){/blue-fg}{/bold}\n`;
189
196
  content += '{bold}{yellow-fg}⚠ CONNECTION LOST - SHOWING STALE DATA{/yellow-fg}{/bold}\n\n';
190
197
 
191
198
  // Server Info
@@ -250,44 +257,39 @@ export async function createMonitorUI(
250
257
  }
251
258
  }
252
259
 
253
- // System Resources
254
- content += '{bold}System Resources{/bold} {yellow-fg}(stale){/yellow-fg}\n';
260
+ // Model Resources (per-process metrics)
261
+ content += '{bold}Model Resources{/bold} {yellow-fg}(stale){/yellow-fg}\n';
255
262
  content += divider + '\n';
256
263
 
257
- if (lastGoodData.system) {
258
- if (lastGoodData.system.gpuUsage !== undefined) {
259
- const bar = createProgressBar(lastGoodData.system.gpuUsage);
260
- content += `GPU: {cyan-fg}${bar}{/cyan-fg} ${Math.round(lastGoodData.system.gpuUsage)}%`;
261
-
262
- if (lastGoodData.system.temperature !== undefined) {
263
- content += ` - ${Math.round(lastGoodData.system.temperature)}°C`;
264
- }
264
+ // GPU: System-wide (can't get per-process on macOS)
265
+ if (lastGoodData.system && lastGoodData.system.gpuUsage !== undefined) {
266
+ const bar = createProgressBar(lastGoodData.system.gpuUsage);
267
+ content += `GPU: {cyan-fg}${bar}{/cyan-fg} ${Math.round(lastGoodData.system.gpuUsage)}% {gray-fg}(system){/gray-fg}`;
265
268
 
266
- content += '\n';
269
+ if (lastGoodData.system.temperature !== undefined) {
270
+ content += ` - ${Math.round(lastGoodData.system.temperature)}°C`;
267
271
  }
268
272
 
269
- if (lastGoodData.system.cpuUsage !== undefined) {
270
- const bar = createProgressBar(lastGoodData.system.cpuUsage);
271
- content += `CPU: {cyan-fg}${bar}{/cyan-fg} ${Math.round(lastGoodData.system.cpuUsage)}%\n`;
272
- }
273
+ content += '\n';
274
+ }
273
275
 
274
- if (lastGoodData.system.aneUsage !== undefined && lastGoodData.system.aneUsage > 1) {
275
- const bar = createProgressBar(lastGoodData.system.aneUsage);
276
- content += `ANE: {cyan-fg}${bar}{/cyan-fg} ${Math.round(lastGoodData.system.aneUsage)}%\n`;
277
- }
276
+ // CPU: Per-process
277
+ if (lastGoodData.server.processCpuUsage !== undefined) {
278
+ const bar = createProgressBar(lastGoodData.server.processCpuUsage);
279
+ content += `CPU: {cyan-fg}${bar}{/cyan-fg} ${Math.round(lastGoodData.server.processCpuUsage)}%\n`;
280
+ }
278
281
 
279
- if (lastGoodData.system.memoryTotal > 0) {
280
- const memoryUsedGB = lastGoodData.system.memoryUsed / (1024 ** 3);
281
- const memoryTotalGB = lastGoodData.system.memoryTotal / (1024 ** 3);
282
- const memoryPercentage = (lastGoodData.system.memoryUsed / lastGoodData.system.memoryTotal) * 100;
283
- const bar = createProgressBar(memoryPercentage);
284
- content += `Memory: {cyan-fg}${bar}{/cyan-fg} ${Math.round(memoryPercentage)}% `;
285
- content += `(${memoryUsedGB.toFixed(1)} / ${memoryTotalGB.toFixed(1)} GB)\n`;
286
- }
282
+ // Memory: Per-process
283
+ if (lastGoodData.server.processMemory !== undefined) {
284
+ const memoryGB = lastGoodData.server.processMemory / (1024 ** 3);
285
+ const estimatedMax = 8;
286
+ const memoryPercentage = Math.min((memoryGB / estimatedMax) * 100, 100);
287
+ const bar = createProgressBar(memoryPercentage);
288
+ content += `Memory: {cyan-fg}${bar}{/cyan-fg} ${memoryGB.toFixed(2)} GB\n`;
289
+ }
287
290
 
288
- if (lastGoodData.system.warnings && lastGoodData.system.warnings.length > 0) {
289
- content += `\n{yellow-fg}⚠ ${lastGoodData.system.warnings.join(', ')}{/yellow-fg}\n`;
290
- }
291
+ if (lastGoodData.system && lastGoodData.system.warnings && lastGoodData.system.warnings.length > 0) {
292
+ content += `\n{yellow-fg}⚠ ${lastGoodData.system.warnings.join(', ')}{/yellow-fg}\n`;
291
293
  }
292
294
 
293
295
  content += '\n';
@@ -296,7 +298,7 @@ export async function createMonitorUI(
296
298
  content += divider + '\n';
297
299
  content += `{yellow-fg}Last good data: ${lastGoodData.lastUpdated.toLocaleTimeString()}{/yellow-fg}\n`;
298
300
  content += `{yellow-fg}Connection failures: ${consecutiveFailures}{/yellow-fg}\n`;
299
- content += `{gray-fg}Interval: ${updateInterval}ms | [R]efresh [+/-]Speed [Q]uit{/gray-fg}`;
301
+ content += `{gray-fg}Interval: ${updateInterval}ms | [H]istory [R]efresh [+/-]Speed [Q]uit{/gray-fg}`;
300
302
 
301
303
  contentBox.setContent(content);
302
304
  screen.render();
@@ -340,6 +342,29 @@ export async function createMonitorUI(
340
342
  startPolling();
341
343
  });
342
344
 
345
+ // Track whether we're in historical view to prevent H key conflicts
346
+ let inHistoricalView = false;
347
+
348
+ screen.key(['h', 'H'], async () => {
349
+ // Prevent entering historical view if already there
350
+ if (inHistoricalView) return;
351
+
352
+ // Keep polling in background for live historical updates
353
+ // Remove current content box
354
+ screen.remove(contentBox);
355
+
356
+ // Mark that we're in historical view
357
+ inHistoricalView = true;
358
+
359
+ // Show historical view (polling continues in background)
360
+ await createHistoricalUI(screen, server, () => {
361
+ // Mark that we've left historical view
362
+ inHistoricalView = false;
363
+ // Re-attach content box when returning from history
364
+ screen.append(contentBox);
365
+ });
366
+ });
367
+
343
368
  screen.key(['q', 'Q', 'C-c'], () => {
344
369
  if (intervalId) clearInterval(intervalId);
345
370
  screen.destroy();