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
@@ -0,0 +1,202 @@
1
+ import { Cell, ExecutionResult } from '@/types/notebook';
2
+
3
+ export class WebSocketService {
4
+ private ws: WebSocket | null = null;
5
+ private listeners: Map<string, Function[]> = new Map();
6
+ private reconnectAttempts = 0;
7
+ private maxReconnectAttempts = 5;
8
+ private url: string = '';
9
+
10
+ connect(url: string = 'ws://localhost:8888/ws'): Promise<void> {
11
+ this.url = url;
12
+ return new Promise((resolve, reject) => {
13
+ try {
14
+ this.ws = new WebSocket(this.url);
15
+
16
+ this.ws.onopen = () => {
17
+ console.log('Connected to server');
18
+ this.reconnectAttempts = 0;
19
+ this.emit('connect', null);
20
+ resolve();
21
+ };
22
+
23
+ this.ws.onerror = (error) => {
24
+ console.error('WebSocket error:', error);
25
+ this.emit('disconnect', null);
26
+ reject(error);
27
+ };
28
+
29
+ this.ws.onclose = (ev) => {
30
+ console.log('Disconnected from server', { code: ev.code, reason: ev.reason, wasClean: ev.wasClean });
31
+ this.emit('disconnect', null);
32
+ this.handleDisconnect();
33
+ };
34
+
35
+ this.ws.onmessage = (event) => {
36
+ try {
37
+ const data = JSON.parse(event.data);
38
+ console.log('[WS RECV]', data);
39
+ this.handleMessage(data);
40
+ } catch (error) {
41
+ console.error('Failed to parse message:', error);
42
+ }
43
+ };
44
+ } catch (error) {
45
+ reject(error);
46
+ }
47
+ });
48
+ }
49
+
50
+ private handleMessage(data: any) {
51
+ const messageType = data.type;
52
+ const messageData = data.data;
53
+
54
+ // Map FastAPI message types to our expected events
55
+ switch (messageType) {
56
+ case 'notebook_data':
57
+ this.emit('notebook_loaded', messageData);
58
+ break;
59
+ case 'notebook_updated':
60
+ this.emit('notebook_updated', messageData);
61
+ break;
62
+ case 'execution_start':
63
+ this.emit('execution_start', messageData);
64
+ break;
65
+ case 'stream_output':
66
+ this.emit('stream_output', messageData);
67
+ break;
68
+ case 'execution_result':
69
+ this.emit('execution_result', messageData);
70
+ break;
71
+ case 'execution_complete': // This may be sent by some legacy paths
72
+ this.emit('execution_complete', messageData);
73
+ break;
74
+ case 'execution_error':
75
+ this.emit('execution_error', messageData);
76
+ break;
77
+ case 'execution_interrupted':
78
+ this.emit('execution_interrupted', messageData);
79
+ break;
80
+ case 'cell_updated': // Note: This is now handled by notebook_updated
81
+ this.emit('cell_updated', messageData);
82
+ break;
83
+ case 'cell_added':
84
+ this.emit('cell_added', messageData);
85
+ break;
86
+ case 'cell_deleted':
87
+ this.emit('cell_deleted', messageData);
88
+ break;
89
+ case 'kernel_status':
90
+ this.emit('kernel_status', messageData);
91
+ break;
92
+ case 'packages_updated':
93
+ // Notify listeners and also broadcast a DOM event for decoupled UIs
94
+ this.emit('packages_updated', messageData);
95
+ try {
96
+ window.dispatchEvent(new CustomEvent('mc:packages-updated', { detail: messageData }));
97
+ } catch {}
98
+ break;
99
+ case 'error':
100
+ this.emit('error', messageData);
101
+ break;
102
+ default:
103
+ console.warn('Unknown message type:', messageType);
104
+ }
105
+ }
106
+
107
+ private handleDisconnect() {
108
+ this.emit('disconnect', null);
109
+ // Attempt to reconnect
110
+ if (this.reconnectAttempts < this.maxReconnectAttempts) {
111
+ this.reconnectAttempts++;
112
+ console.log(`Attempting to reconnect (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);
113
+ setTimeout(() => {
114
+ this.connect(this.url).catch(console.error);
115
+ }, 1000 * this.reconnectAttempts);
116
+ }
117
+ }
118
+
119
+ on(event: string, callback: Function) {
120
+ if (!this.listeners.has(event)) {
121
+ this.listeners.set(event, []);
122
+ }
123
+ this.listeners.get(event)!.push(callback);
124
+ }
125
+
126
+ off(event: string, callback: Function) {
127
+ const callbacks = this.listeners.get(event);
128
+ if (callbacks) {
129
+ const index = callbacks.indexOf(callback);
130
+ if (index > -1) {
131
+ callbacks.splice(index, 1);
132
+ }
133
+ }
134
+ }
135
+
136
+ private emit(event: string, data: any) {
137
+ const callbacks = this.listeners.get(event);
138
+ if (callbacks) {
139
+ callbacks.forEach(callback => callback(data));
140
+ }
141
+ }
142
+
143
+ private send(type: string, data: any = {}) {
144
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
145
+ this.ws.send(JSON.stringify({ type, data }));
146
+ } else {
147
+ console.error('WebSocket is not connected');
148
+ }
149
+ }
150
+
151
+ // Notebook operations
152
+ loadNotebook(notebookName: string) {
153
+ this.send('load_notebook', { notebook_name: notebookName });
154
+ }
155
+
156
+ saveNotebook() {
157
+ this.send('save_notebook');
158
+ }
159
+
160
+ // Cell operations
161
+ addCell(index: number, cellType: 'code' | 'markdown', source: string = '') {
162
+ this.send('add_cell', {
163
+ index,
164
+ cell_type: cellType,
165
+ source,
166
+ });
167
+ }
168
+
169
+ deleteCell(cellIndex: number) {
170
+ this.send('delete_cell', { cell_index: cellIndex });
171
+ }
172
+
173
+ updateCell(cellIndex: number, source: string) {
174
+ this.send('update_cell', {
175
+ cell_index: cellIndex,
176
+ source,
177
+ });
178
+ }
179
+
180
+ executeCell(cellIndex: number, source: string) {
181
+ this.send('execute_cell', {
182
+ cell_index: cellIndex,
183
+ source,
184
+ });
185
+ }
186
+
187
+ // Kernel operations
188
+ resetKernel() {
189
+ this.send('reset_kernel');
190
+ }
191
+
192
+ interruptKernel(cellIndex?: number) {
193
+ this.send('interrupt_kernel', { cell_index: cellIndex });
194
+ }
195
+
196
+ disconnect() {
197
+ if (this.ws) {
198
+ this.ws.close();
199
+ this.ws = null;
200
+ }
201
+ }
202
+ }
@@ -0,0 +1,134 @@
1
+ import { io, Socket } from 'socket.io-client';
2
+ import { Cell, ExecutionResult } from '@/types/notebook';
3
+
4
+ export class WebSocketService {
5
+ private socket: Socket | null = null;
6
+ private listeners: Map<string, Function[]> = new Map();
7
+
8
+ connect(url: string = 'ws://localhost:8000'): Promise<void> {
9
+ return new Promise((resolve, reject) => {
10
+ // For development, connect directly to the backend WebSocket
11
+ const wsUrl = process.env.NODE_ENV === 'production'
12
+ ? '/ws'
13
+ : 'ws://localhost:8000/ws';
14
+
15
+ // Use native WebSocket for FastAPI compatibility
16
+ const ws = new WebSocket(wsUrl);
17
+
18
+ // Wrap WebSocket in Socket.IO-like interface
19
+ this.socket = this.createSocketWrapper(ws);
20
+
21
+ this.socket.on('connect', () => {
22
+ console.log('Connected to server');
23
+ resolve();
24
+ });
25
+
26
+ this.socket.on('connect_error', (error) => {
27
+ console.error('Connection error:', error);
28
+ reject(error);
29
+ });
30
+
31
+ this.socket.on('disconnect', () => {
32
+ console.log('Disconnected from server');
33
+ });
34
+
35
+ // Set up event forwarding
36
+ this.setupEventForwarding();
37
+ });
38
+ }
39
+
40
+ private setupEventForwarding() {
41
+ if (!this.socket) return;
42
+
43
+ // Forward common events
44
+ const events = [
45
+ 'notebook_loaded',
46
+ 'cell_added',
47
+ 'cell_deleted',
48
+ 'cell_updated',
49
+ 'execution_result',
50
+ 'kernel_status',
51
+ 'error',
52
+ ];
53
+
54
+ events.forEach(event => {
55
+ this.socket!.on(event, (data) => {
56
+ this.emit(event, data);
57
+ });
58
+ });
59
+ }
60
+
61
+ on(event: string, callback: Function) {
62
+ if (!this.listeners.has(event)) {
63
+ this.listeners.set(event, []);
64
+ }
65
+ this.listeners.get(event)!.push(callback);
66
+ }
67
+
68
+ off(event: string, callback: Function) {
69
+ const callbacks = this.listeners.get(event);
70
+ if (callbacks) {
71
+ const index = callbacks.indexOf(callback);
72
+ if (index > -1) {
73
+ callbacks.splice(index, 1);
74
+ }
75
+ }
76
+ }
77
+
78
+ private emit(event: string, data: any) {
79
+ const callbacks = this.listeners.get(event);
80
+ if (callbacks) {
81
+ callbacks.forEach(callback => callback(data));
82
+ }
83
+ }
84
+
85
+ // Notebook operations
86
+ loadNotebook(notebookName: string) {
87
+ this.socket?.emit('load_notebook', { notebook_name: notebookName });
88
+ }
89
+
90
+ saveNotebook() {
91
+ this.socket?.emit('save_notebook');
92
+ }
93
+
94
+ // Cell operations
95
+ addCell(index: number, cellType: 'code' | 'markdown', source: string = '') {
96
+ this.socket?.emit('add_cell', {
97
+ index,
98
+ cell_type: cellType,
99
+ source,
100
+ });
101
+ }
102
+
103
+ deleteCell(cellIndex: number) {
104
+ this.socket?.emit('delete_cell', { cell_index: cellIndex });
105
+ }
106
+
107
+ updateCell(cellIndex: number, source: string) {
108
+ this.socket?.emit('update_cell', {
109
+ cell_index: cellIndex,
110
+ source,
111
+ });
112
+ }
113
+
114
+ executeCell(cellIndex: number, source: string) {
115
+ this.socket?.emit('execute_cell', {
116
+ cell_index: cellIndex,
117
+ source,
118
+ });
119
+ }
120
+
121
+ // Kernel operations
122
+ resetKernel() {
123
+ this.socket?.emit('reset_kernel');
124
+ }
125
+
126
+ interruptKernel() {
127
+ this.socket?.emit('interrupt_kernel');
128
+ }
129
+
130
+ disconnect() {
131
+ this.socket?.disconnect();
132
+ this.socket = null;
133
+ }
134
+ }
frontend/next-env.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+ /// <reference path="./.next/types/routes.d.ts" />
4
+
5
+ // NOTE: This file should not be edited
6
+ // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -0,0 +1,17 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ async rewrites() {
4
+ return [
5
+ {
6
+ source: '/ws/:path*',
7
+ destination: 'http://localhost:8000/ws/:path*',
8
+ },
9
+ {
10
+ source: '/api/:path*',
11
+ destination: 'http://localhost:8000/api/:path*',
12
+ },
13
+ ];
14
+ },
15
+ };
16
+
17
+ export default nextConfig;
@@ -0,0 +1,7 @@
1
+ import type { NextConfig } from "next";
2
+
3
+ const nextConfig: NextConfig = {
4
+ /* config options here */
5
+ };
6
+
7
+ export default nextConfig;