@appkit/llamacpp-cli 1.12.0 → 1.13.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 (136) hide show
  1. package/README.md +294 -168
  2. package/dist/cli.js +35 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/launch/claude.d.ts +6 -0
  5. package/dist/commands/launch/claude.d.ts.map +1 -0
  6. package/dist/commands/launch/claude.js +277 -0
  7. package/dist/commands/launch/claude.js.map +1 -0
  8. package/dist/lib/integration-checker.d.ts +26 -0
  9. package/dist/lib/integration-checker.d.ts.map +1 -0
  10. package/dist/lib/integration-checker.js +77 -0
  11. package/dist/lib/integration-checker.js.map +1 -0
  12. package/dist/lib/router-manager.d.ts +4 -0
  13. package/dist/lib/router-manager.d.ts.map +1 -1
  14. package/dist/lib/router-manager.js +10 -0
  15. package/dist/lib/router-manager.js.map +1 -1
  16. package/dist/lib/router-server.d.ts +13 -0
  17. package/dist/lib/router-server.d.ts.map +1 -1
  18. package/dist/lib/router-server.js +267 -7
  19. package/dist/lib/router-server.js.map +1 -1
  20. package/dist/types/integration-config.d.ts +28 -0
  21. package/dist/types/integration-config.d.ts.map +1 -0
  22. package/dist/types/integration-config.js +3 -0
  23. package/dist/types/integration-config.js.map +1 -0
  24. package/package.json +10 -2
  25. package/web/dist/assets/index-Bin89Lwr.css +1 -0
  26. package/web/dist/assets/index-CVmonw3T.js +17 -0
  27. package/web/{index.html → dist/index.html} +2 -1
  28. package/.versionrc.json +0 -16
  29. package/CHANGELOG.md +0 -213
  30. package/docs/images/.gitkeep +0 -1
  31. package/docs/images/web-ui-servers.png +0 -0
  32. package/src/cli.ts +0 -523
  33. package/src/commands/admin/config.ts +0 -121
  34. package/src/commands/admin/logs.ts +0 -91
  35. package/src/commands/admin/restart.ts +0 -26
  36. package/src/commands/admin/start.ts +0 -27
  37. package/src/commands/admin/status.ts +0 -84
  38. package/src/commands/admin/stop.ts +0 -16
  39. package/src/commands/config-global.ts +0 -38
  40. package/src/commands/config.ts +0 -323
  41. package/src/commands/create.ts +0 -183
  42. package/src/commands/delete.ts +0 -74
  43. package/src/commands/list.ts +0 -37
  44. package/src/commands/logs-all.ts +0 -251
  45. package/src/commands/logs.ts +0 -345
  46. package/src/commands/monitor.ts +0 -110
  47. package/src/commands/ps.ts +0 -84
  48. package/src/commands/pull.ts +0 -44
  49. package/src/commands/rm.ts +0 -107
  50. package/src/commands/router/config.ts +0 -116
  51. package/src/commands/router/logs.ts +0 -256
  52. package/src/commands/router/restart.ts +0 -36
  53. package/src/commands/router/start.ts +0 -60
  54. package/src/commands/router/status.ts +0 -119
  55. package/src/commands/router/stop.ts +0 -33
  56. package/src/commands/run.ts +0 -233
  57. package/src/commands/search.ts +0 -107
  58. package/src/commands/server-show.ts +0 -161
  59. package/src/commands/show.ts +0 -207
  60. package/src/commands/start.ts +0 -101
  61. package/src/commands/stop.ts +0 -39
  62. package/src/commands/tui.ts +0 -25
  63. package/src/lib/admin-manager.ts +0 -435
  64. package/src/lib/admin-server.ts +0 -1243
  65. package/src/lib/config-generator.ts +0 -130
  66. package/src/lib/download-job-manager.ts +0 -213
  67. package/src/lib/history-manager.ts +0 -172
  68. package/src/lib/launchctl-manager.ts +0 -225
  69. package/src/lib/metrics-aggregator.ts +0 -257
  70. package/src/lib/model-downloader.ts +0 -328
  71. package/src/lib/model-scanner.ts +0 -157
  72. package/src/lib/model-search.ts +0 -114
  73. package/src/lib/models-dir-setup.ts +0 -46
  74. package/src/lib/port-manager.ts +0 -80
  75. package/src/lib/router-logger.ts +0 -201
  76. package/src/lib/router-manager.ts +0 -414
  77. package/src/lib/router-server.ts +0 -538
  78. package/src/lib/state-manager.ts +0 -206
  79. package/src/lib/status-checker.ts +0 -113
  80. package/src/lib/system-collector.ts +0 -315
  81. package/src/tui/ConfigApp.ts +0 -1085
  82. package/src/tui/HistoricalMonitorApp.ts +0 -587
  83. package/src/tui/ModelsApp.ts +0 -368
  84. package/src/tui/MonitorApp.ts +0 -386
  85. package/src/tui/MultiServerMonitorApp.ts +0 -1833
  86. package/src/tui/RootNavigator.ts +0 -74
  87. package/src/tui/SearchApp.ts +0 -511
  88. package/src/tui/SplashScreen.ts +0 -149
  89. package/src/types/admin-config.ts +0 -25
  90. package/src/types/global-config.ts +0 -26
  91. package/src/types/history-types.ts +0 -39
  92. package/src/types/model-info.ts +0 -8
  93. package/src/types/monitor-types.ts +0 -162
  94. package/src/types/router-config.ts +0 -25
  95. package/src/types/server-config.ts +0 -46
  96. package/src/utils/downsample-utils.ts +0 -128
  97. package/src/utils/file-utils.ts +0 -146
  98. package/src/utils/format-utils.ts +0 -98
  99. package/src/utils/log-parser.ts +0 -284
  100. package/src/utils/log-utils.ts +0 -178
  101. package/src/utils/process-utils.ts +0 -316
  102. package/src/utils/prompt-utils.ts +0 -47
  103. package/test-load.sh +0 -100
  104. package/tsconfig.json +0 -20
  105. package/web/eslint.config.js +0 -23
  106. package/web/llamacpp-web-dist.tar.gz +0 -0
  107. package/web/package-lock.json +0 -4017
  108. package/web/package.json +0 -38
  109. package/web/postcss.config.js +0 -6
  110. package/web/src/App.css +0 -42
  111. package/web/src/App.tsx +0 -86
  112. package/web/src/assets/react.svg +0 -1
  113. package/web/src/components/ApiKeyPrompt.tsx +0 -71
  114. package/web/src/components/CreateServerModal.tsx +0 -372
  115. package/web/src/components/DownloadProgress.tsx +0 -123
  116. package/web/src/components/Nav.tsx +0 -89
  117. package/web/src/components/RouterConfigModal.tsx +0 -240
  118. package/web/src/components/SearchModal.tsx +0 -306
  119. package/web/src/components/ServerConfigModal.tsx +0 -291
  120. package/web/src/hooks/useApi.ts +0 -259
  121. package/web/src/index.css +0 -42
  122. package/web/src/lib/api.ts +0 -226
  123. package/web/src/main.tsx +0 -10
  124. package/web/src/pages/Dashboard.tsx +0 -103
  125. package/web/src/pages/Models.tsx +0 -258
  126. package/web/src/pages/Router.tsx +0 -270
  127. package/web/src/pages/RouterLogs.tsx +0 -201
  128. package/web/src/pages/ServerLogs.tsx +0 -553
  129. package/web/src/pages/Servers.tsx +0 -358
  130. package/web/src/types/api.ts +0 -140
  131. package/web/tailwind.config.js +0 -31
  132. package/web/tsconfig.app.json +0 -28
  133. package/web/tsconfig.json +0 -7
  134. package/web/tsconfig.node.json +0 -26
  135. package/web/vite.config.ts +0 -25
  136. /package/web/{public → dist}/vite.svg +0 -0
@@ -1,259 +0,0 @@
1
- import { useQuery, useMutation, useQueryClient, keepPreviousData } from '@tanstack/react-query';
2
- import { api } from '../lib/api';
3
- import type { CreateServerRequest, UpdateServerRequest, UpdateRouterRequest } from '../types/api';
4
-
5
- // System
6
- export function useSystemStatus() {
7
- return useQuery({
8
- queryKey: ['system', 'status'],
9
- queryFn: () => api.getSystemStatus(),
10
- refetchInterval: 5000, // Auto-refresh every 5s
11
- });
12
- }
13
-
14
- // Servers
15
- export function useServers() {
16
- return useQuery({
17
- queryKey: ['servers'],
18
- queryFn: () => api.listServers(),
19
- refetchInterval: 5000, // Auto-refresh every 5s
20
- });
21
- }
22
-
23
- export function useServer(id: string) {
24
- return useQuery({
25
- queryKey: ['servers', id],
26
- queryFn: () => api.getServer(id),
27
- enabled: !!id,
28
- });
29
- }
30
-
31
- export function useCreateServer() {
32
- const queryClient = useQueryClient();
33
-
34
- return useMutation({
35
- mutationFn: (data: CreateServerRequest) => api.createServer(data),
36
- onSuccess: () => {
37
- queryClient.invalidateQueries({ queryKey: ['servers'] });
38
- queryClient.invalidateQueries({ queryKey: ['system'] });
39
- },
40
- });
41
- }
42
-
43
- export function useUpdateServer() {
44
- const queryClient = useQueryClient();
45
-
46
- return useMutation({
47
- mutationFn: ({ id, data }: { id: string; data: UpdateServerRequest }) =>
48
- api.updateServer(id, data),
49
- onSuccess: (_, variables) => {
50
- queryClient.invalidateQueries({ queryKey: ['servers'] });
51
- queryClient.invalidateQueries({ queryKey: ['servers', variables.id] });
52
- },
53
- });
54
- }
55
-
56
- export function useDeleteServer() {
57
- const queryClient = useQueryClient();
58
-
59
- return useMutation({
60
- mutationFn: (id: string) => api.deleteServer(id),
61
- onSuccess: () => {
62
- queryClient.invalidateQueries({ queryKey: ['servers'] });
63
- queryClient.invalidateQueries({ queryKey: ['system'] });
64
- },
65
- });
66
- }
67
-
68
- export function useStartServer() {
69
- const queryClient = useQueryClient();
70
-
71
- return useMutation({
72
- mutationFn: (id: string) => api.startServer(id),
73
- onSuccess: (_, id) => {
74
- queryClient.invalidateQueries({ queryKey: ['servers'] });
75
- queryClient.invalidateQueries({ queryKey: ['servers', id] });
76
- },
77
- });
78
- }
79
-
80
- export function useStopServer() {
81
- const queryClient = useQueryClient();
82
-
83
- return useMutation({
84
- mutationFn: (id: string) => api.stopServer(id),
85
- onSuccess: (_, id) => {
86
- queryClient.invalidateQueries({ queryKey: ['servers'] });
87
- queryClient.invalidateQueries({ queryKey: ['servers', id] });
88
- },
89
- });
90
- }
91
-
92
- export function useRestartServer() {
93
- const queryClient = useQueryClient();
94
-
95
- return useMutation({
96
- mutationFn: (id: string) => api.restartServer(id),
97
- onSuccess: (_, id) => {
98
- queryClient.invalidateQueries({ queryKey: ['servers'] });
99
- queryClient.invalidateQueries({ queryKey: ['servers', id] });
100
- },
101
- });
102
- }
103
-
104
- export function useServerLogs(serverId: string | null, lines = 500) {
105
- return useQuery({
106
- queryKey: ['serverLogs', serverId, lines],
107
- queryFn: () => api.getServerLogs(serverId!, 'both', lines),
108
- enabled: !!serverId,
109
- refetchInterval: 2000, // Auto-refresh every 2s
110
- });
111
- }
112
-
113
- // Models
114
- export function useModels() {
115
- return useQuery({
116
- queryKey: ['models'],
117
- queryFn: () => api.listModels(),
118
- refetchInterval: 10000, // Auto-refresh every 10s
119
- });
120
- }
121
-
122
- export function useModel(name: string) {
123
- return useQuery({
124
- queryKey: ['models', name],
125
- queryFn: () => api.getModel(name),
126
- enabled: !!name,
127
- });
128
- }
129
-
130
- export function useDeleteModel() {
131
- const queryClient = useQueryClient();
132
-
133
- return useMutation({
134
- mutationFn: ({ name, cascade }: { name: string; cascade: boolean }) =>
135
- api.deleteModel(name, cascade),
136
- onSuccess: () => {
137
- queryClient.invalidateQueries({ queryKey: ['models'] });
138
- queryClient.invalidateQueries({ queryKey: ['servers'] });
139
- queryClient.invalidateQueries({ queryKey: ['system'] });
140
- },
141
- });
142
- }
143
-
144
- export function useDownloadModel() {
145
- return useMutation({
146
- mutationFn: ({ repo, filename }: { repo: string; filename: string }) =>
147
- api.downloadModel(repo, filename),
148
- // Don't invalidate immediately - download is background job
149
- });
150
- }
151
-
152
- // Search
153
- export function useSearchModels() {
154
- return useMutation({
155
- mutationFn: ({ query, limit = 20 }: { query: string; limit?: number }) =>
156
- api.searchModels(query, limit),
157
- });
158
- }
159
-
160
- export function useModelFiles(repoId: string | null) {
161
- return useQuery({
162
- queryKey: ['modelFiles', repoId],
163
- queryFn: () => api.getModelFiles(repoId!),
164
- enabled: !!repoId,
165
- });
166
- }
167
-
168
- // Download Jobs
169
- export function useDownloadJobs(enabled = true) {
170
- return useQuery({
171
- queryKey: ['downloadJobs'],
172
- queryFn: () => api.listDownloadJobs(),
173
- refetchInterval: enabled ? 1000 : false, // Poll every 1s when enabled
174
- enabled,
175
- });
176
- }
177
-
178
- export function useDownloadJob(jobId: string | null) {
179
- return useQuery({
180
- queryKey: ['downloadJobs', jobId],
181
- queryFn: () => api.getDownloadJob(jobId!),
182
- enabled: !!jobId,
183
- refetchInterval: 500, // Fast polling for active job
184
- });
185
- }
186
-
187
- export function useCancelDownload() {
188
- const queryClient = useQueryClient();
189
-
190
- return useMutation({
191
- mutationFn: (jobId: string) => api.cancelDownloadJob(jobId),
192
- onSuccess: () => {
193
- queryClient.invalidateQueries({ queryKey: ['downloadJobs'] });
194
- },
195
- });
196
- }
197
-
198
- // Router
199
- export function useRouter() {
200
- return useQuery({
201
- queryKey: ['router'],
202
- queryFn: () => api.getRouter(),
203
- refetchInterval: 5000, // Auto-refresh every 5s
204
- placeholderData: keepPreviousData, // Keep previous data during refetch to prevent flash
205
- });
206
- }
207
-
208
- export function useStartRouter() {
209
- const queryClient = useQueryClient();
210
-
211
- return useMutation({
212
- mutationFn: () => api.startRouter(),
213
- onSuccess: () => {
214
- queryClient.invalidateQueries({ queryKey: ['router'] });
215
- },
216
- });
217
- }
218
-
219
- export function useStopRouter() {
220
- const queryClient = useQueryClient();
221
-
222
- return useMutation({
223
- mutationFn: () => api.stopRouter(),
224
- onSuccess: () => {
225
- queryClient.invalidateQueries({ queryKey: ['router'] });
226
- },
227
- });
228
- }
229
-
230
- export function useRestartRouter() {
231
- const queryClient = useQueryClient();
232
-
233
- return useMutation({
234
- mutationFn: () => api.restartRouter(),
235
- onSuccess: () => {
236
- queryClient.invalidateQueries({ queryKey: ['router'] });
237
- },
238
- });
239
- }
240
-
241
- export function useRouterLogs(lines = 500) {
242
- return useQuery({
243
- queryKey: ['routerLogs', lines],
244
- queryFn: () => api.getRouterLogs('both', lines),
245
- refetchInterval: 2000, // Auto-refresh every 2s
246
- placeholderData: keepPreviousData, // Keep previous data during refetch to prevent flash
247
- });
248
- }
249
-
250
- export function useUpdateRouter() {
251
- const queryClient = useQueryClient();
252
-
253
- return useMutation({
254
- mutationFn: (data: UpdateRouterRequest) => api.updateRouter(data),
255
- onSuccess: () => {
256
- queryClient.invalidateQueries({ queryKey: ['router'] });
257
- },
258
- });
259
- }
package/web/src/index.css DELETED
@@ -1,42 +0,0 @@
1
- @import "tailwindcss";
2
-
3
- :root {
4
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
5
- line-height: 1.5;
6
- font-weight: 400;
7
- font-synthesis: none;
8
- text-rendering: optimizeLegibility;
9
- -webkit-font-smoothing: antialiased;
10
- -moz-osx-font-smoothing: grayscale;
11
- }
12
-
13
- body {
14
- margin: 0;
15
- min-width: 320px;
16
- min-height: 100vh;
17
- background-color: #fafafa;
18
- color: #171717;
19
- }
20
-
21
- #root {
22
- min-height: 100vh;
23
- }
24
-
25
- /* Custom scrollbar for Ollama aesthetic */
26
- ::-webkit-scrollbar {
27
- width: 8px;
28
- height: 8px;
29
- }
30
-
31
- ::-webkit-scrollbar-track {
32
- background: transparent;
33
- }
34
-
35
- ::-webkit-scrollbar-thumb {
36
- background: #d4d4d4;
37
- border-radius: 4px;
38
- }
39
-
40
- ::-webkit-scrollbar-thumb:hover {
41
- background: #a3a3a3;
42
- }
@@ -1,226 +0,0 @@
1
- import type {
2
- Server,
3
- Model,
4
- SystemStatus,
5
- CreateServerRequest,
6
- UpdateServerRequest,
7
- ApiError,
8
- HFModelResult,
9
- DownloadJob,
10
- RouterInfo,
11
- UpdateRouterRequest,
12
- } from '../types/api';
13
-
14
- const API_BASE = ''; // Proxy handles routing
15
-
16
- class ApiClient {
17
- private apiKey: string | null = null;
18
-
19
- setApiKey(key: string) {
20
- this.apiKey = key;
21
- localStorage.setItem('llamacpp_api_key', key);
22
- }
23
-
24
- getApiKey(): string | null {
25
- if (!this.apiKey) {
26
- this.apiKey = localStorage.getItem('llamacpp_api_key');
27
- }
28
- return this.apiKey;
29
- }
30
-
31
- clearApiKey() {
32
- this.apiKey = null;
33
- localStorage.removeItem('llamacpp_api_key');
34
- }
35
-
36
- private async request<T>(
37
- endpoint: string,
38
- options: RequestInit = {}
39
- ): Promise<T> {
40
- const apiKey = this.getApiKey();
41
-
42
- const headers: Record<string, string> = {
43
- 'Content-Type': 'application/json',
44
- ...(options.headers as Record<string, string>),
45
- };
46
-
47
- if (apiKey && endpoint !== '/health') {
48
- headers['Authorization'] = `Bearer ${apiKey}`;
49
- }
50
-
51
- const response = await fetch(`${API_BASE}${endpoint}`, {
52
- ...options,
53
- headers,
54
- });
55
-
56
- if (!response.ok) {
57
- const error: ApiError = await response.json();
58
- throw new Error(error.details || error.error);
59
- }
60
-
61
- return response.json();
62
- }
63
-
64
- // Health
65
- async getHealth() {
66
- return this.request<{ status: string; uptime: number; timestamp: string }>('/health');
67
- }
68
-
69
- // System
70
- async getSystemStatus() {
71
- return this.request<SystemStatus>('/api/status');
72
- }
73
-
74
- // Servers
75
- async listServers() {
76
- return this.request<{ servers: Server[] }>('/api/servers');
77
- }
78
-
79
- async getServer(id: string) {
80
- return this.request<{ server: Server }>(`/api/servers/${id}`);
81
- }
82
-
83
- async createServer(data: CreateServerRequest) {
84
- return this.request<{ server: Server }>('/api/servers', {
85
- method: 'POST',
86
- body: JSON.stringify(data),
87
- });
88
- }
89
-
90
- async updateServer(id: string, data: UpdateServerRequest) {
91
- return this.request<{ server: Server }>(`/api/servers/${id}`, {
92
- method: 'PATCH',
93
- body: JSON.stringify(data),
94
- });
95
- }
96
-
97
- async deleteServer(id: string) {
98
- return this.request<{ success: boolean }>(`/api/servers/${id}`, {
99
- method: 'DELETE',
100
- });
101
- }
102
-
103
- async startServer(id: string) {
104
- return this.request<{ server: Server }>(`/api/servers/${id}/start`, {
105
- method: 'POST',
106
- });
107
- }
108
-
109
- async stopServer(id: string) {
110
- return this.request<{ server: Server }>(`/api/servers/${id}/stop`, {
111
- method: 'POST',
112
- });
113
- }
114
-
115
- async restartServer(id: string) {
116
- return this.request<{ server: Server }>(`/api/servers/${id}/restart`, {
117
- method: 'POST',
118
- });
119
- }
120
-
121
- async getServerLogs(id: string, type: 'stdout' | 'stderr' | 'both' = 'both', lines = 100) {
122
- return this.request<{ stdout: string; stderr: string }>(
123
- `/api/servers/${id}/logs?type=${type}&lines=${lines}`
124
- );
125
- }
126
-
127
- // Models
128
- async listModels() {
129
- return this.request<{ models: Model[] }>('/api/models');
130
- }
131
-
132
- async getModel(name: string) {
133
- return this.request<{ model: Model }>(`/api/models/${encodeURIComponent(name)}`);
134
- }
135
-
136
- async searchModels(query: string, limit = 20) {
137
- return this.request<{ results: HFModelResult[] }>(
138
- `/api/models/search?q=${encodeURIComponent(query)}&limit=${limit}`
139
- );
140
- }
141
-
142
- async getModelFiles(repoId: string) {
143
- return this.request<{ repoId: string; files: string[] }>(
144
- `/api/models/${encodeURIComponent(repoId)}/files`
145
- );
146
- }
147
-
148
- async downloadModel(repo: string, filename: string) {
149
- return this.request<{ jobId: string; status: string }>(
150
- '/api/models/download',
151
- {
152
- method: 'POST',
153
- body: JSON.stringify({ repo, filename }),
154
- }
155
- );
156
- }
157
-
158
- async deleteModel(name: string, cascade = false) {
159
- return this.request<{ success: boolean; deletedServers?: string[] }>(
160
- `/api/models/${encodeURIComponent(name)}?cascade=${cascade}`,
161
- {
162
- method: 'DELETE',
163
- }
164
- );
165
- }
166
-
167
- // Download Jobs
168
- async listDownloadJobs() {
169
- return this.request<{ jobs: DownloadJob[] }>('/api/jobs');
170
- }
171
-
172
- async getDownloadJob(jobId: string) {
173
- return this.request<{ job: DownloadJob }>(`/api/jobs/${jobId}`);
174
- }
175
-
176
- async cancelDownloadJob(jobId: string) {
177
- return this.request<{ success: boolean; message: string }>(
178
- `/api/jobs/${jobId}`,
179
- { method: 'DELETE' }
180
- );
181
- }
182
-
183
- // Router
184
- async getRouter() {
185
- return this.request<RouterInfo>('/api/router');
186
- }
187
-
188
- async startRouter() {
189
- return this.request<{ success: boolean; status: string; pid: number | null }>(
190
- '/api/router/start',
191
- { method: 'POST' }
192
- );
193
- }
194
-
195
- async stopRouter() {
196
- return this.request<{ success: boolean; status: string }>(
197
- '/api/router/stop',
198
- { method: 'POST' }
199
- );
200
- }
201
-
202
- async restartRouter() {
203
- return this.request<{ success: boolean; status: string; pid: number | null }>(
204
- '/api/router/restart',
205
- { method: 'POST' }
206
- );
207
- }
208
-
209
- async getRouterLogs(type: 'stdout' | 'stderr' | 'both' = 'both', lines = 100) {
210
- return this.request<{ stdout: string; stderr: string }>(
211
- `/api/router/logs?type=${type}&lines=${lines}`
212
- );
213
- }
214
-
215
- async updateRouter(data: UpdateRouterRequest) {
216
- return this.request<{ success: boolean; needsRestart: boolean; config: any }>(
217
- '/api/router',
218
- {
219
- method: 'PATCH',
220
- body: JSON.stringify(data),
221
- }
222
- );
223
- }
224
- }
225
-
226
- export const api = new ApiClient();
package/web/src/main.tsx DELETED
@@ -1,10 +0,0 @@
1
- import { StrictMode } from 'react'
2
- import { createRoot } from 'react-dom/client'
3
- import './index.css'
4
- import App from './App.tsx'
5
-
6
- createRoot(document.getElementById('root')!).render(
7
- <StrictMode>
8
- <App />
9
- </StrictMode>,
10
- )
@@ -1,103 +0,0 @@
1
- import { useSystemStatus, useServers } from '../hooks/useApi';
2
- import { Server, Box, Activity, Clock } from 'lucide-react';
3
-
4
- export function Dashboard() {
5
- const { data: status } = useSystemStatus();
6
- const { data: serversData } = useServers();
7
-
8
- const runningServers = serversData?.servers.filter(s => s.status === 'running') || [];
9
-
10
- return (
11
- <div className="max-w-7xl mx-auto px-6 py-8">
12
- <div className="mb-8">
13
- <h1 className="text-3xl font-semibold text-gray-900 dark:text-white mb-2">
14
- Dashboard
15
- </h1>
16
- <p className="text-gray-600 dark:text-gray-400">
17
- Manage your local llama.cpp servers
18
- </p>
19
- </div>
20
-
21
- <div className="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
22
- <div className="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-lg p-6">
23
- <div className="flex items-center justify-between mb-2">
24
- <span className="text-sm text-gray-600 dark:text-gray-400">Total Servers</span>
25
- <Server className="w-4 h-4 text-gray-400" />
26
- </div>
27
- <div className="text-3xl font-semibold text-gray-900 dark:text-white">
28
- {status?.servers.total || 0}
29
- </div>
30
- </div>
31
-
32
- <div className="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-lg p-6">
33
- <div className="flex items-center justify-between mb-2">
34
- <span className="text-sm text-gray-600 dark:text-gray-400">Running</span>
35
- <Activity className="w-4 h-4 text-green-500" />
36
- </div>
37
- <div className="text-3xl font-semibold text-green-600 dark:text-green-500">
38
- {status?.servers.running || 0}
39
- </div>
40
- </div>
41
-
42
- <div className="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-lg p-6">
43
- <div className="flex items-center justify-between mb-2">
44
- <span className="text-sm text-gray-600 dark:text-gray-400">Stopped</span>
45
- <Clock className="w-4 h-4 text-gray-400" />
46
- </div>
47
- <div className="text-3xl font-semibold text-gray-900 dark:text-white">
48
- {status?.servers.stopped || 0}
49
- </div>
50
- </div>
51
-
52
- <div className="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-lg p-6">
53
- <div className="flex items-center justify-between mb-2">
54
- <span className="text-sm text-gray-600 dark:text-gray-400">Models</span>
55
- <Box className="w-4 h-4 text-gray-400" />
56
- </div>
57
- <div className="text-3xl font-semibold text-gray-900 dark:text-white">
58
- {status?.models.total || 0}
59
- </div>
60
- </div>
61
- </div>
62
-
63
- <div className="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-lg">
64
- <div className="p-6 border-b border-gray-200 dark:border-gray-800">
65
- <h2 className="text-lg font-semibold text-gray-900 dark:text-white">
66
- Running Servers
67
- </h2>
68
- </div>
69
- <div className="divide-y divide-gray-200 dark:divide-gray-800">
70
- {runningServers.length === 0 ? (
71
- <div className="p-8 text-center">
72
- <p className="text-gray-500 dark:text-gray-400">No servers running</p>
73
- </div>
74
- ) : (
75
- runningServers.map((server) => (
76
- <div key={server.id} className="p-6 hover:bg-gray-50 dark:hover:bg-gray-800/50 transition-colors">
77
- <div className="flex items-center justify-between">
78
- <div>
79
- <h3 className="text-sm font-medium text-gray-900 dark:text-white mb-1">
80
- {server.modelName}
81
- </h3>
82
- <div className="flex items-center space-x-4 text-sm text-gray-600 dark:text-gray-400">
83
- <span>Port {server.port}</span>
84
- <span>•</span>
85
- <span>{server.threads} threads</span>
86
- <span>•</span>
87
- <span>Context {server.ctxSize}</span>
88
- </div>
89
- </div>
90
- <div className="flex items-center space-x-2">
91
- <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400">
92
- Running
93
- </span>
94
- </div>
95
- </div>
96
- </div>
97
- ))
98
- )}
99
- </div>
100
- </div>
101
- </div>
102
- );
103
- }