@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
@@ -1,368 +0,0 @@
1
- import blessed from 'blessed';
2
- import { modelScanner } from '../lib/model-scanner.js';
3
- import { stateManager } from '../lib/state-manager.js';
4
- import { launchctlManager } from '../lib/launchctl-manager.js';
5
- import { ModelInfo } from '../types/model-info.js';
6
- import { ServerConfig } from '../types/server-config.js';
7
- import { formatBytes, formatDateShort } from '../utils/format-utils.js';
8
- import * as fs from 'fs/promises';
9
- import { createSearchUI } from './SearchApp.js';
10
-
11
- /**
12
- * Models management TUI
13
- * Display installed models and allow deletion
14
- */
15
- export async function createModelsUI(
16
- screen: blessed.Widgets.Screen,
17
- onBack: () => void,
18
- onSearch: () => void
19
- ): Promise<void> {
20
- let models: ModelInfo[] = [];
21
- let selectedIndex = 0;
22
- let isLoading = false;
23
-
24
- // Create content box
25
- const contentBox = blessed.box({
26
- top: 0,
27
- left: 0,
28
- width: '100%',
29
- height: '100%',
30
- tags: true,
31
- scrollable: true,
32
- alwaysScroll: true,
33
- keys: true,
34
- vi: true,
35
- mouse: true,
36
- scrollbar: {
37
- ch: '█',
38
- style: {
39
- fg: 'blue',
40
- },
41
- },
42
- });
43
- screen.append(contentBox);
44
-
45
- // Render models view
46
- async function render() {
47
- const termWidth = (screen.width as number) || 80;
48
- const divider = '─'.repeat(termWidth - 2);
49
- let content = '';
50
-
51
- // Header
52
- content += '{bold}{blue-fg}═══ Models Management{/blue-fg}{/bold}\n\n';
53
-
54
- if (isLoading) {
55
- content += '{cyan-fg}⏳ Loading models...{/cyan-fg}\n';
56
- contentBox.setContent(content);
57
- screen.render();
58
- return;
59
- }
60
-
61
- if (models.length === 0) {
62
- content += '{yellow-fg}No models found{/yellow-fg}\n\n';
63
- content += '{dim}Models directory: ' + await stateManager.getModelsDirectory() + '{/dim}\n';
64
- content += '{dim}Download models: Press [S] to search HuggingFace{/dim}\n';
65
- content += '\n' + divider + '\n';
66
- content += `{gray-fg}[S]earch [ESC] Back [Q]uit{/gray-fg}`;
67
- contentBox.setContent(content);
68
- screen.render();
69
- return;
70
- }
71
-
72
- // System info
73
- const totalSize = models.reduce((sum, m) => sum + m.size, 0);
74
- content += `{bold}Total: ${models.length} models{/bold} - ${formatBytes(totalSize)}\n`;
75
- content += divider + '\n';
76
-
77
- // Get all servers to check dependencies
78
- const allServers = await stateManager.getAllServers();
79
-
80
- // Table header
81
- content += '{bold} │ Model File │ Size │ Modified │ Servers{/bold}\n';
82
- content += divider + '\n';
83
-
84
- // Model rows
85
- for (let i = 0; i < models.length; i++) {
86
- const model = models[i];
87
- const isSelected = i === selectedIndex;
88
-
89
- // Count servers using this model
90
- const serversUsingModel = allServers.filter(s => s.modelPath === model.path);
91
- const serverCount = serversUsingModel.length;
92
-
93
- // Selection indicator
94
- const indicator = isSelected ? '►' : ' ';
95
-
96
- // Model filename (truncate if too long)
97
- const maxFilenameLen = 46;
98
- let filename = model.filename;
99
- if (filename.length > maxFilenameLen) {
100
- filename = filename.substring(0, maxFilenameLen - 3) + '...';
101
- }
102
- filename = filename.padEnd(maxFilenameLen);
103
-
104
- // Size
105
- const size = model.sizeFormatted.padStart(11);
106
-
107
- // Modified date
108
- const modified = formatDateShort(model.modified).padStart(11);
109
-
110
- // Servers count with color coding
111
- let serversText = '';
112
- let serversTextPlain = '';
113
- if (serverCount === 0) {
114
- serversText = '{green-fg}0 servers{/green-fg}';
115
- serversTextPlain = '0 servers';
116
- } else {
117
- const runningCount = serversUsingModel.filter(s => s.status === 'running').length;
118
- if (runningCount > 0) {
119
- serversText = `{yellow-fg}${serverCount} (${runningCount} running){/yellow-fg}`;
120
- serversTextPlain = `${serverCount} (${runningCount} running)`;
121
- } else {
122
- serversText = `{gray-fg}${serverCount} stopped{/gray-fg}`;
123
- serversTextPlain = `${serverCount} stopped`;
124
- }
125
- }
126
-
127
- // Build row content
128
- let rowContent = '';
129
- if (isSelected) {
130
- // Selected row: cyan background with bright white text
131
- rowContent = `{cyan-bg}{15-fg}${indicator} │ ${filename} │ ${size} │ ${modified} │ ${serversTextPlain}{/15-fg}{/cyan-bg}`;
132
- } else {
133
- // Normal row: with colored server text
134
- rowContent = `${indicator} │ ${filename} │ ${size} │ ${modified} │ ${serversText}`;
135
- }
136
-
137
- content += rowContent + '\n';
138
- }
139
-
140
- // Footer
141
- content += '\n' + divider + '\n';
142
- content += '{gray-fg}[↑/↓] Navigate [D]elete [S]earch [R]efresh [ESC] Back [Q]uit{/gray-fg}';
143
-
144
- contentBox.setContent(content);
145
- screen.render();
146
- }
147
-
148
- // Load models
149
- async function loadModels() {
150
- isLoading = true;
151
- await render();
152
-
153
- models = await modelScanner.scanModels();
154
- selectedIndex = Math.min(selectedIndex, Math.max(0, models.length - 1));
155
-
156
- isLoading = false;
157
- await render();
158
- }
159
-
160
- // Delete selected model
161
- async function deleteModel() {
162
- if (models.length === 0) return;
163
-
164
- const model = models[selectedIndex];
165
- const allServers = await stateManager.getAllServers();
166
- const serversUsingModel = allServers.filter(s => s.modelPath === model.path);
167
-
168
- // Show confirmation dialog
169
- const confirmBox = blessed.message({
170
- parent: screen,
171
- top: 'center',
172
- left: 'center',
173
- width: '60%',
174
- height: 'shrink',
175
- border: { type: 'line' },
176
- style: {
177
- border: { fg: 'red' },
178
- fg: 'white',
179
- },
180
- tags: true,
181
- });
182
-
183
- let confirmText = `{bold}Delete model: ${model.filename}?{/bold}\n\n`;
184
- confirmText += `Size: ${model.sizeFormatted}\n\n`;
185
-
186
- if (serversUsingModel.length > 0) {
187
- confirmText += `{yellow-fg}⚠️ This model has ${serversUsingModel.length} server(s) configured:{/yellow-fg}\n`;
188
- for (const server of serversUsingModel) {
189
- const statusColor = server.status === 'running' ? 'green-fg' : 'gray-fg';
190
- confirmText += ` - ${server.id} ({${statusColor}}${server.status}{/${statusColor}})\n`;
191
- }
192
- confirmText += `\n{yellow-fg}These servers will be deleted before removing the model.{/yellow-fg}\n\n`;
193
- }
194
-
195
- confirmText += `Type 'yes' to confirm:\n\n\n\n`; // Extra lines for input box space
196
-
197
- // Create input box for confirmation
198
- const inputBox = blessed.textbox({
199
- parent: confirmBox,
200
- bottom: 1,
201
- left: 2,
202
- right: 2,
203
- height: 3,
204
- inputOnFocus: true,
205
- border: { type: 'line' },
206
- style: {
207
- border: { fg: 'cyan' },
208
- focus: { border: { fg: 'green' } },
209
- },
210
- });
211
-
212
- confirmBox.setContent(confirmText);
213
- screen.append(confirmBox);
214
- confirmBox.focus();
215
- inputBox.focus();
216
- screen.render();
217
-
218
- inputBox.on('submit', async (value: string) => {
219
- screen.remove(confirmBox);
220
-
221
- if (value.toLowerCase() !== 'yes') {
222
- await render();
223
- return;
224
- }
225
-
226
- // Show deleting message
227
- isLoading = true;
228
- contentBox.setContent('{cyan-fg}⏳ Deleting model...{/cyan-fg}');
229
- screen.render();
230
-
231
- try {
232
- // Delete all servers using this model
233
- for (const server of serversUsingModel) {
234
- // Unload service (stops and removes from launchd)
235
- try {
236
- await launchctlManager.unloadService(server.plistPath);
237
- if (server.status === 'running') {
238
- await launchctlManager.waitForServiceStop(server.label, 5000);
239
- }
240
- } catch (error) {
241
- // Continue even if unload fails
242
- }
243
-
244
- // Delete plist
245
- await launchctlManager.deletePlist(server.plistPath);
246
-
247
- // Delete server config
248
- await stateManager.deleteServerConfig(server.id);
249
- }
250
-
251
- // Delete model file
252
- await fs.unlink(model.path);
253
-
254
- // Reload models
255
- await loadModels();
256
- } catch (error) {
257
- // Show error
258
- const errorBox = blessed.message({
259
- parent: screen,
260
- top: 'center',
261
- left: 'center',
262
- width: '60%',
263
- height: 'shrink',
264
- border: { type: 'line' },
265
- style: {
266
- border: { fg: 'red' },
267
- fg: 'red',
268
- },
269
- tags: true,
270
- });
271
-
272
- const errorMsg = error instanceof Error ? error.message : 'Unknown error';
273
- errorBox.display(`{bold}Delete failed{/bold}\n\n${errorMsg}\n\nPress any key to continue`, () => {
274
- screen.remove(errorBox);
275
- isLoading = false;
276
- render();
277
- });
278
- }
279
- });
280
-
281
- inputBox.on('cancel', () => {
282
- screen.remove(confirmBox);
283
- render();
284
- });
285
-
286
- inputBox.key(['escape'], () => {
287
- screen.remove(confirmBox);
288
- render();
289
- });
290
- }
291
-
292
- // Store key handler references for cleanup
293
- const keyHandlers = {
294
- up: () => {
295
- if (models.length === 0) return;
296
- selectedIndex = Math.max(0, selectedIndex - 1);
297
- render();
298
- },
299
- down: () => {
300
- if (models.length === 0) return;
301
- selectedIndex = Math.min(models.length - 1, selectedIndex + 1);
302
- render();
303
- },
304
- delete: () => {
305
- deleteModel();
306
- },
307
- search: async () => {
308
- // Cleanup current handlers before switching views
309
- cleanup();
310
-
311
- // Open search view
312
- await createSearchUI(screen, async () => {
313
- // onBack callback - return to models view
314
- // Re-register handlers
315
- registerHandlers();
316
- screen.append(contentBox);
317
- await loadModels();
318
- });
319
- },
320
- refresh: () => {
321
- loadModels();
322
- },
323
- escape: async () => {
324
- cleanup();
325
- await onBack();
326
- },
327
- quit: () => {
328
- screen.destroy();
329
- process.exit(0);
330
- },
331
- };
332
-
333
- // Cleanup function to unregister all handlers
334
- function cleanup() {
335
- screen.unkey('up', keyHandlers.up);
336
- screen.unkey('k', keyHandlers.up);
337
- screen.unkey('down', keyHandlers.down);
338
- screen.unkey('j', keyHandlers.down);
339
- screen.unkey('d', keyHandlers.delete);
340
- screen.unkey('D', keyHandlers.delete);
341
- screen.unkey('s', keyHandlers.search);
342
- screen.unkey('S', keyHandlers.search);
343
- screen.unkey('r', keyHandlers.refresh);
344
- screen.unkey('R', keyHandlers.refresh);
345
- screen.unkey('escape', keyHandlers.escape);
346
- screen.unkey('q', keyHandlers.quit);
347
- screen.unkey('Q', keyHandlers.quit);
348
- screen.unkey('C-c', keyHandlers.quit);
349
- screen.remove(contentBox);
350
- }
351
-
352
- // Register key handlers
353
- function registerHandlers() {
354
- screen.key(['up', 'k'], keyHandlers.up);
355
- screen.key(['down', 'j'], keyHandlers.down);
356
- screen.key(['d', 'D'], keyHandlers.delete);
357
- screen.key(['s', 'S'], keyHandlers.search);
358
- screen.key(['r', 'R'], keyHandlers.refresh);
359
- screen.key(['escape'], keyHandlers.escape);
360
- screen.key(['q', 'Q', 'C-c'], keyHandlers.quit);
361
- }
362
-
363
- // Register initial handlers
364
- registerHandlers();
365
-
366
- // Initial load
367
- await loadModels();
368
- }