more-compute 0.1.2__py3-none-any.whl → 0.1.3__py3-none-any.whl

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 (67) hide show
  1. frontend/.DS_Store +0 -0
  2. frontend/.gitignore +41 -0
  3. frontend/README.md +36 -0
  4. frontend/__init__.py +1 -0
  5. frontend/app/favicon.ico +0 -0
  6. frontend/app/globals.css +1537 -0
  7. frontend/app/layout.tsx +173 -0
  8. frontend/app/page.tsx +11 -0
  9. frontend/components/AddCellButton.tsx +42 -0
  10. frontend/components/Cell.tsx +244 -0
  11. frontend/components/CellButton.tsx +58 -0
  12. frontend/components/CellOutput.tsx +70 -0
  13. frontend/components/ErrorDisplay.tsx +208 -0
  14. frontend/components/ErrorModal.tsx +154 -0
  15. frontend/components/MarkdownRenderer.tsx +84 -0
  16. frontend/components/Notebook.tsx +520 -0
  17. frontend/components/Sidebar.tsx +46 -0
  18. frontend/components/popups/ComputePopup.tsx +879 -0
  19. frontend/components/popups/FilterPopup.tsx +427 -0
  20. frontend/components/popups/FolderPopup.tsx +171 -0
  21. frontend/components/popups/MetricsPopup.tsx +168 -0
  22. frontend/components/popups/PackagesPopup.tsx +112 -0
  23. frontend/components/popups/PythonPopup.tsx +292 -0
  24. frontend/components/popups/SettingsPopup.tsx +68 -0
  25. frontend/eslint.config.mjs +25 -0
  26. frontend/lib/api.ts +469 -0
  27. frontend/lib/settings.ts +87 -0
  28. frontend/lib/websocket-native.ts +202 -0
  29. frontend/lib/websocket.ts +134 -0
  30. frontend/next-env.d.ts +6 -0
  31. frontend/next.config.mjs +17 -0
  32. frontend/next.config.ts +7 -0
  33. frontend/package-lock.json +5676 -0
  34. frontend/package.json +41 -0
  35. frontend/postcss.config.mjs +5 -0
  36. frontend/public/assets/icons/add.svg +1 -0
  37. frontend/public/assets/icons/check.svg +1 -0
  38. frontend/public/assets/icons/copy.svg +1 -0
  39. frontend/public/assets/icons/folder.svg +1 -0
  40. frontend/public/assets/icons/metric.svg +1 -0
  41. frontend/public/assets/icons/packages.svg +1 -0
  42. frontend/public/assets/icons/play.svg +1 -0
  43. frontend/public/assets/icons/python.svg +265 -0
  44. frontend/public/assets/icons/setting.svg +1 -0
  45. frontend/public/assets/icons/stop.svg +1 -0
  46. frontend/public/assets/icons/trash.svg +1 -0
  47. frontend/public/assets/icons/up-down.svg +1 -0
  48. frontend/public/assets/icons/x.svg +1 -0
  49. frontend/public/file.svg +1 -0
  50. frontend/public/fonts/Fira.ttf +0 -0
  51. frontend/public/fonts/Tiempos.woff2 +0 -0
  52. frontend/public/fonts/VeraMono.ttf +0 -0
  53. frontend/public/globe.svg +1 -0
  54. frontend/public/next.svg +1 -0
  55. frontend/public/vercel.svg +1 -0
  56. frontend/public/window.svg +1 -0
  57. frontend/tailwind.config.ts +29 -0
  58. frontend/tsconfig.json +27 -0
  59. frontend/types/notebook.ts +58 -0
  60. kernel_run.py +6 -0
  61. {more_compute-0.1.2.dist-info → more_compute-0.1.3.dist-info}/METADATA +1 -1
  62. more_compute-0.1.3.dist-info/RECORD +85 -0
  63. {more_compute-0.1.2.dist-info → more_compute-0.1.3.dist-info}/top_level.txt +1 -0
  64. more_compute-0.1.2.dist-info/RECORD +0 -26
  65. {more_compute-0.1.2.dist-info → more_compute-0.1.3.dist-info}/WHEEL +0 -0
  66. {more_compute-0.1.2.dist-info → more_compute-0.1.3.dist-info}/entry_points.txt +0 -0
  67. {more_compute-0.1.2.dist-info → more_compute-0.1.3.dist-info}/licenses/LICENSE +0 -0
frontend/lib/api.ts ADDED
@@ -0,0 +1,469 @@
1
+ export interface FileTreeItem {
2
+ name: string;
3
+ path: string;
4
+ type: "file" | "directory";
5
+ size?: number;
6
+ modified?: string;
7
+ }
8
+
9
+ export interface FileTreeResponse {
10
+ root: string;
11
+ path: string;
12
+ items: FileTreeItem[];
13
+ }
14
+
15
+ export async function fetchFileTree(
16
+ path: string = ".",
17
+ ): Promise<FileTreeResponse> {
18
+ const query = new URLSearchParams({ path }).toString();
19
+ const response = await fetch(`/api/files?${query}`);
20
+
21
+ if (!response.ok) {
22
+ throw new Error(`Failed to load file tree: ${response.status}`);
23
+ }
24
+
25
+ return response.json();
26
+ }
27
+
28
+ export async function fetchFilePreview(
29
+ path: string,
30
+ maxBytes = 256_000,
31
+ ): Promise<string> {
32
+ const query = new URLSearchParams({
33
+ path,
34
+ max_bytes: String(maxBytes),
35
+ }).toString();
36
+ const response = await fetch(`/api/file?${query}`);
37
+
38
+ if (!response.ok) {
39
+ throw new Error(`Failed to load file: ${response.status}`);
40
+ }
41
+
42
+ return response.text();
43
+ }
44
+
45
+ export interface PackageInfo {
46
+ name: string;
47
+ version: string;
48
+ }
49
+ export interface PackagesResponse {
50
+ packages: PackageInfo[];
51
+ }
52
+
53
+ export async function fetchInstalledPackages(forceRefresh: boolean = false): Promise<PackageInfo[]> {
54
+ const url = forceRefresh ? `/api/packages?force_refresh=true` : `/api/packages`;
55
+ const response = await fetch(url);
56
+ if (!response.ok) {
57
+ throw new Error(`Failed to load packages: ${response.status}`);
58
+ }
59
+ const data = (await response.json()) as PackagesResponse;
60
+ return data.packages || [];
61
+ }
62
+
63
+ export interface MetricsSnapshot {
64
+ timestamp: number;
65
+ cpu?: { percent?: number; frequency_mhz?: number; cores?: number };
66
+ memory?: {
67
+ total?: number;
68
+ available?: number;
69
+ used?: number;
70
+ percent?: number;
71
+ };
72
+ gpu?: Array<{
73
+ power_w?: number;
74
+ clock_sm_mhz?: number;
75
+ temperature_c?: number;
76
+ util_percent?: number;
77
+ mem_used_mb?: number;
78
+ mem_total_mb?: number;
79
+ }> | null;
80
+ storage?: {
81
+ total?: number;
82
+ used?: number;
83
+ percent?: number;
84
+ read_bytes?: number;
85
+ write_bytes?: number;
86
+ };
87
+ network?: {
88
+ bytes_sent?: number;
89
+ bytes_recv?: number;
90
+ packets_sent?: number;
91
+ packets_recv?: number;
92
+ };
93
+ process?: {
94
+ rss?: number;
95
+ vms?: number;
96
+ threads?: number;
97
+ cpu_percent?: number;
98
+ };
99
+ }
100
+
101
+ export async function fetchMetrics(): Promise<MetricsSnapshot> {
102
+ const response = await fetch(`/api/metrics`);
103
+ if (!response.ok)
104
+ throw new Error(`Failed to load metrics: ${response.status}`);
105
+ return response.json();
106
+ }
107
+
108
+ // Prime Intellect GPU API Types
109
+ export interface EnvVar {
110
+ key: string;
111
+ value: string;
112
+ }
113
+
114
+ export interface PodConfig {
115
+ // Required fields for pod creation
116
+ name: string;
117
+ cloudId: string;
118
+ gpuType: string;
119
+ socket: string;
120
+ gpuCount: number;
121
+
122
+ // Optional fields
123
+ diskSize?: number | null;
124
+ vcpus?: number | null;
125
+ memory?: number | null;
126
+ maxPrice?: number | null;
127
+ image?: string | null;
128
+ customTemplateId?: string | null;
129
+ dataCenterId?: string | null;
130
+ country?: string | null;
131
+ security?: string | null;
132
+ envVars?: EnvVar[] | null;
133
+ jupyterPassword?: string | null;
134
+ autoRestart?: boolean | null;
135
+ }
136
+
137
+ export interface ProviderConfig {
138
+ type?: string;
139
+ }
140
+
141
+ export interface TeamConfig {
142
+ teamId?: string | null;
143
+ }
144
+
145
+ export interface CreatePodRequest {
146
+ pod: PodConfig;
147
+ provider: ProviderConfig;
148
+ team?: TeamConfig | null;
149
+ }
150
+
151
+ export interface PodResponse {
152
+ id: string;
153
+ userId: string;
154
+ teamId: string | null;
155
+ name: string;
156
+ status: string;
157
+ gpuName: string;
158
+ gpuCount: number;
159
+ priceHr: number;
160
+ sshConnection: string | null;
161
+ ip: string | null;
162
+ createdAt: string;
163
+ updatedAt: string;
164
+ }
165
+
166
+ export interface GpuAvailabilityParams {
167
+ regions?: string[];
168
+ gpu_count?: number;
169
+ gpu_type?: string;
170
+ socket?: string;
171
+ security?: string;
172
+ }
173
+
174
+ export interface PodsListParams {
175
+ status?: string;
176
+ limit?: number;
177
+ offset?: number;
178
+ }
179
+
180
+ export interface GpuAvailability {
181
+ cloudId: string;
182
+ gpuType: string;
183
+ socket: string;
184
+ provider: string;
185
+ gpuCount: number;
186
+ gpuMemory: number;
187
+ security: string;
188
+ prices: {
189
+ onDemand: number;
190
+ communityPrice: number | null;
191
+ isVariable: boolean | null;
192
+ currency: string;
193
+ };
194
+ images: string[];
195
+ region: string | null;
196
+ dataCenter: string | null;
197
+ country: string | null;
198
+ disk?: {
199
+ minCount: number | null;
200
+ defaultCount: number | null;
201
+ maxCount: number | null;
202
+ pricePerUnit: number | null;
203
+ step: number | null;
204
+ defaultIncludedInPrice: boolean | null;
205
+ additionalInfo: string | null;
206
+ };
207
+ sharedDisk?: {
208
+ minCount: number | null;
209
+ defaultCount: number | null;
210
+ maxCount: number | null;
211
+ pricePerUnit: number | null;
212
+ step: number | null;
213
+ defaultIncludedInPrice: boolean | null;
214
+ additionalInfo: string | null;
215
+ };
216
+ vcpu?: {
217
+ minCount: number | null;
218
+ defaultCount: number | null;
219
+ maxCount: number | null;
220
+ pricePerUnit: number | null;
221
+ step: number | null;
222
+ defaultIncludedInPrice: boolean | null;
223
+ additionalInfo: string | null;
224
+ };
225
+ memory?: {
226
+ minCount: number | null;
227
+ defaultCount: number | null;
228
+ maxCount: number | null;
229
+ pricePerUnit: number | null;
230
+ step: number | null;
231
+ defaultIncludedInPrice: boolean | null;
232
+ additionalInfo: string | null;
233
+ };
234
+ internetSpeed: number | null;
235
+ interconnect: number | null;
236
+ interconnectType: string | null;
237
+ provisioningTime: number | null;
238
+ stockStatus?: string;
239
+ isSpot: boolean | null;
240
+ prepaidTime: number | null;
241
+ }
242
+
243
+ export interface GpuAvailabilityResponse {
244
+ [key: string]: GpuAvailability[];
245
+ }
246
+
247
+ export interface PodsListResponse {
248
+ total_count?: number;
249
+ offset?: number;
250
+ limit?: number;
251
+ data?: PodResponse[];
252
+ }
253
+
254
+ export interface DeletePodResponse {
255
+ [key: string]: unknown;
256
+ }
257
+
258
+ export async function fetchGpuConfig(): Promise<{ configured: boolean }> {
259
+ const response = await fetch("/api/gpu/config");
260
+ if (!response.ok) {
261
+ throw new Error(`Failed to fetch GPU config: ${response.status}`);
262
+ }
263
+ return response.json();
264
+ }
265
+
266
+ export async function setGpuApiKey(
267
+ apiKey: string,
268
+ ): Promise<{ configured: boolean; message: string }> {
269
+ const response = await fetch("/api/gpu/config", {
270
+ method: "POST",
271
+ headers: {
272
+ "Content-Type": "application/json",
273
+ },
274
+ body: JSON.stringify({ api_key: apiKey }),
275
+ });
276
+
277
+ if (!response.ok) {
278
+ throw new Error(`Failed to set API key: ${response.status}`);
279
+ }
280
+
281
+ return response.json();
282
+ }
283
+
284
+ export async function fetchGpuAvailability(
285
+ params?: GpuAvailabilityParams,
286
+ ): Promise<GpuAvailabilityResponse> {
287
+ const queryParams = new URLSearchParams();
288
+
289
+ if (params?.regions) {
290
+ params.regions.forEach((region) => queryParams.append("regions", region));
291
+ }
292
+ if (params?.gpu_count !== undefined) {
293
+ queryParams.set("gpu_count", String(params.gpu_count));
294
+ }
295
+ if (params?.gpu_type) {
296
+ queryParams.set("gpu_type", params.gpu_type);
297
+ }
298
+ if (params?.socket) {
299
+ queryParams.set("socket", params.socket);
300
+ }
301
+ if (params?.security) {
302
+ queryParams.set("security", params.security);
303
+ }
304
+
305
+ const query = queryParams.toString();
306
+ const url = query
307
+ ? `/api/gpu/availability?${query}`
308
+ : "/api/gpu/availability";
309
+ const response = await fetch(url);
310
+
311
+ if (!response.ok) {
312
+ throw new Error(`Failed to fetch GPU availability: ${response.status}`);
313
+ }
314
+
315
+ return response.json();
316
+ }
317
+
318
+ export async function fetchGpuPods(
319
+ params?: PodsListParams,
320
+ ): Promise<PodsListResponse> {
321
+ const queryParams = new URLSearchParams();
322
+
323
+ if (params?.status) {
324
+ queryParams.set("status", params.status);
325
+ }
326
+ if (params?.limit !== undefined) {
327
+ queryParams.set("limit", String(params.limit));
328
+ }
329
+ if (params?.offset !== undefined) {
330
+ queryParams.set("offset", String(params.offset));
331
+ }
332
+
333
+ const query = queryParams.toString();
334
+ const url = query ? `/api/gpu/pods?${query}` : "/api/gpu/pods";
335
+ const response = await fetch(url);
336
+
337
+ if (!response.ok) {
338
+ throw new Error(`Failed to fetch GPU pods: ${response.status}`);
339
+ }
340
+
341
+ return response.json();
342
+ }
343
+
344
+ export async function createGpuPod(
345
+ podRequest: CreatePodRequest,
346
+ ): Promise<PodResponse> {
347
+ const response = await fetch("/api/gpu/pods", {
348
+ method: "POST",
349
+ headers: {
350
+ "Content-Type": "application/json",
351
+ },
352
+ body: JSON.stringify(podRequest),
353
+ });
354
+
355
+ if (!response.ok) {
356
+ throw new Error(`Failed to create GPU pod: ${response.status}`);
357
+ }
358
+
359
+ return response.json();
360
+ }
361
+
362
+ export async function fetchGpuPod(podId: string): Promise<PodResponse> {
363
+ const response = await fetch(`/api/gpu/pods/${podId}`);
364
+
365
+ if (!response.ok) {
366
+ throw new Error(`Failed to fetch GPU pod: ${response.status}`);
367
+ }
368
+
369
+ return response.json();
370
+ }
371
+
372
+ export async function deleteGpuPod(podId: string): Promise<DeletePodResponse> {
373
+ const response = await fetch(`/api/gpu/pods/${podId}`, {
374
+ method: "DELETE",
375
+ });
376
+
377
+ if (!response.ok) {
378
+ const errorText = await response.text();
379
+ throw new Error(
380
+ `Failed to delete GPU pod: ${response.status} - ${errorText}`,
381
+ );
382
+ }
383
+
384
+ return response.json();
385
+ }
386
+
387
+ export interface PodConnectionResponse {
388
+ status: string;
389
+ message: string;
390
+ ssh_host?: string;
391
+ ssh_port?: string;
392
+ tunnel_ports?: {
393
+ cmd: string;
394
+ pub: string;
395
+ };
396
+ }
397
+
398
+ export interface PodConnectionStatus {
399
+ connected: boolean;
400
+ pod: {
401
+ id: string;
402
+ name: string;
403
+ status: string;
404
+ gpu_type: string;
405
+ gpu_count: number;
406
+ price_hr: number;
407
+ ssh_connection: string;
408
+ } | null;
409
+ tunnel?: {
410
+ alive: boolean;
411
+ local_cmd_port: number;
412
+ local_pub_port: number;
413
+ };
414
+ executor_attached?: boolean;
415
+ }
416
+
417
+ export async function connectToPod(
418
+ podId: string,
419
+ ): Promise<PodConnectionResponse> {
420
+ const response = await fetch(`/api/gpu/pods/${podId}/connect`, {
421
+ method: "POST",
422
+ });
423
+
424
+ if (!response.ok) {
425
+ throw new Error(`Failed to connect to pod: ${response.status}`);
426
+ }
427
+
428
+ return response.json();
429
+ }
430
+
431
+ export async function disconnectFromPod(): Promise<{
432
+ status: string;
433
+ messages: string[];
434
+ }> {
435
+ const response = await fetch("/api/gpu/pods/disconnect", {
436
+ method: "POST",
437
+ });
438
+
439
+ if (!response.ok) {
440
+ throw new Error(`Failed to disconnect from pod: ${response.status}`);
441
+ }
442
+
443
+ return response.json();
444
+ }
445
+
446
+ export async function getPodConnectionStatus(): Promise<PodConnectionStatus> {
447
+ const response = await fetch("/api/gpu/pods/connection/status");
448
+
449
+ if (!response.ok) {
450
+ throw new Error(`Failed to get connection status: ${response.status}`);
451
+ }
452
+
453
+ return response.json();
454
+ }
455
+
456
+ export async function fixIndentation(code: string): Promise<string> {
457
+ const response = await fetch("/api/fix-indentation", {
458
+ method: "POST",
459
+ headers: { "Content-Type": "application/json" },
460
+ body: JSON.stringify({ code }),
461
+ });
462
+
463
+ if (!response.ok) {
464
+ throw new Error(`Failed to fix indentation: ${response.status}`);
465
+ }
466
+
467
+ const data = await response.json();
468
+ return data.fixed_code;
469
+ }
@@ -0,0 +1,87 @@
1
+ export type ThemeDefinition = {
2
+ background: string;
3
+ cellBackground: string;
4
+ textColor: string;
5
+ markdownColor: string;
6
+ lineNumberColor: string;
7
+ };
8
+
9
+ export const THEMES: Record<string, ThemeDefinition> = {
10
+ light: {
11
+ background: '#f8fafc',
12
+ cellBackground: '#ffffff',
13
+ textColor: '#1f2937',
14
+ markdownColor: '#1f2937',
15
+ lineNumberColor: '#9ca3af',
16
+ },
17
+ dark: {
18
+ background: '#111827',
19
+ cellBackground: '#1f2937',
20
+ textColor: '#f9fafb',
21
+ markdownColor: '#e5e7eb',
22
+ lineNumberColor: '#6b7280',
23
+ },
24
+ catppuccin: {
25
+ background: '#1e1e2e',
26
+ cellBackground: '#313244',
27
+ textColor: '#cdd6f4',
28
+ markdownColor: '#cdd6f4',
29
+ lineNumberColor: '#9399b2',
30
+ },
31
+ };
32
+
33
+ export type NotebookSettings = {
34
+ theme: keyof typeof THEMES;
35
+ auto_save: boolean;
36
+ font_size: number;
37
+ font_family: string;
38
+ };
39
+
40
+ export const DEFAULT_SETTINGS: NotebookSettings = {
41
+ theme: 'light',
42
+ auto_save: true,
43
+ font_size: 14,
44
+ font_family: 'SF Mono',
45
+ };
46
+
47
+ const STORAGE_KEY = 'morecompute-settings';
48
+
49
+ export function loadSettings(): NotebookSettings {
50
+ if (typeof window === 'undefined') return DEFAULT_SETTINGS;
51
+ try {
52
+ const raw = window.localStorage.getItem(STORAGE_KEY);
53
+ if (!raw) return DEFAULT_SETTINGS;
54
+ const parsed = JSON.parse(raw);
55
+ const theme = parsed.theme && THEMES[parsed.theme] ? parsed.theme : DEFAULT_SETTINGS.theme;
56
+ return {
57
+ ...DEFAULT_SETTINGS,
58
+ ...parsed,
59
+ theme,
60
+ };
61
+ } catch (error) {
62
+ console.warn('Failed to load settings; defaulting', error);
63
+ return DEFAULT_SETTINGS;
64
+ }
65
+ }
66
+
67
+ export function saveSettings(settings: NotebookSettings) {
68
+ if (typeof window === 'undefined') return;
69
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
70
+ }
71
+
72
+ export function applyTheme(themeName: keyof typeof THEMES) {
73
+ if (typeof document === 'undefined') return;
74
+ const root = document.documentElement;
75
+ const theme = THEMES[themeName] ?? THEMES.light;
76
+ root.style.setProperty('--mc-background', theme.background);
77
+ root.style.setProperty('--mc-cell-background', theme.cellBackground);
78
+ root.style.setProperty('--mc-text-color', theme.textColor);
79
+ root.style.setProperty('--mc-markdown-color', theme.markdownColor);
80
+ root.style.setProperty('--mc-line-number-color', theme.lineNumberColor);
81
+ }
82
+
83
+ export function resetSettings() {
84
+ saveSettings(DEFAULT_SETTINGS);
85
+ applyTheme(DEFAULT_SETTINGS.theme);
86
+ }
87
+