more-compute 0.3.3__tar.gz → 0.4.1__tar.gz
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.
- {more_compute-0.3.3 → more_compute-0.4.1}/MANIFEST.in +4 -0
- {more_compute-0.3.3/more_compute.egg-info → more_compute-0.4.1}/PKG-INFO +35 -33
- more_compute-0.4.1/README.md +97 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/app/globals.css +9 -7
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/app/layout.tsx +43 -1
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/Notebook.tsx +22 -1
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/cell/CellButton.tsx +5 -4
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/cell/MonacoCell.tsx +42 -21
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/output/ErrorDisplay.tsx +14 -1
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/contexts/PodWebSocketContext.tsx +1 -1
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/lib/websocket.ts +2 -2
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/next.config.mjs +2 -2
- {more_compute-0.3.3 → more_compute-0.4.1}/kernel_run.py +107 -17
- {more_compute-0.3.3 → more_compute-0.4.1/more_compute.egg-info}/PKG-INFO +35 -33
- {more_compute-0.3.3 → more_compute-0.4.1}/more_compute.egg-info/SOURCES.txt +2 -1
- more_compute-0.4.1/morecompute/__version__.py +1 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/execution/executor.py +113 -44
- more_compute-0.4.1/morecompute/execution/worker.py +616 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/notebook.py +65 -6
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/server.py +72 -40
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/utils/cell_magics.py +35 -4
- more_compute-0.4.1/morecompute/utils/notebook_converter.py +129 -0
- more_compute-0.4.1/morecompute/utils/py_percent_parser.py +190 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/utils/special_commands.py +126 -49
- {more_compute-0.3.3 → more_compute-0.4.1}/pyproject.toml +1 -3
- {more_compute-0.3.3 → more_compute-0.4.1}/setup.py +1 -3
- more_compute-0.3.3/README.md +0 -93
- more_compute-0.3.3/frontend/.DS_Store +0 -0
- more_compute-0.3.3/morecompute/__version__.py +0 -1
- more_compute-0.3.3/morecompute/execution/worker.py +0 -404
- {more_compute-0.3.3 → more_compute-0.4.1}/LICENSE +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/.gitignore +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/README.md +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/__init__.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/app/favicon.ico +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/app/page.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/cell/AddCellButton.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/layout/ConnectionBanner.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/layout/Sidebar.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/modals/ConfirmModal.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/modals/ErrorModal.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/modals/SuccessModal.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/output/CellOutput.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/output/MarkdownRenderer.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/popups/ComputePopup.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/popups/FilterPopup.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/popups/FolderPopup.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/popups/MetricsPopup.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/popups/PackagesPopup.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/components/popups/SettingsPopup.tsx +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/eslint.config.mjs +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/lib/api.ts +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/lib/monaco-themes.ts +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/lib/settings.ts +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/lib/themes.json +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/lib/websocket-native.ts +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/next-env.d.ts +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/next.config.ts +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/package-lock.json +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/package.json +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/postcss.config.mjs +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/assets/icons/add.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/assets/icons/check.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/assets/icons/copy.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/assets/icons/folder.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/assets/icons/metric.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/assets/icons/packages.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/assets/icons/play.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/assets/icons/python.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/assets/icons/setting.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/assets/icons/stop.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/assets/icons/trash.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/assets/icons/up-down.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/assets/icons/x.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/file.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/fonts/Fira.ttf +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/fonts/Tiempos.woff2 +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/fonts/VeraMono.ttf +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/globe.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/next.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/vercel.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/public/window.svg +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/styling_README.md +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/tailwind.config.ts +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/tsconfig.json +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/frontend/types/notebook.ts +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/more_compute.egg-info/dependency_links.txt +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/more_compute.egg-info/entry_points.txt +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/more_compute.egg-info/requires.txt +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/more_compute.egg-info/top_level.txt +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/__init__.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/cli.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/execution/__init__.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/execution/__main__.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/models/__init__.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/models/api_models.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/process_worker.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/services/data_manager.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/services/lsp_service.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/services/pod_manager.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/services/pod_monitor.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/services/prime_intellect.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/static/styles.css +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/utils/__init__.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/utils/cache_util.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/utils/config_util.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/utils/error_utils.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/utils/line_magics.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/utils/notebook_util.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/utils/python_environment_util.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/utils/shell_utils.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/utils/system_environment_util.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/morecompute/utils/zmq_util.py +0 -0
- {more_compute-0.3.3 → more_compute-0.4.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: more-compute
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: An interactive notebook environment for local and GPU computing
|
|
5
5
|
Home-page: https://github.com/DannyMang/MORECOMPUTE
|
|
6
6
|
Author: MoreCompute Team
|
|
@@ -15,12 +15,10 @@ Classifier: Intended Audience :: Developers
|
|
|
15
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
16
16
|
Classifier: Operating System :: OS Independent
|
|
17
17
|
Classifier: Programming Language :: Python :: 3
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
20
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
22
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
-
Requires-Python: >=3.
|
|
21
|
+
Requires-Python: >=3.10
|
|
24
22
|
Description-Content-Type: text/markdown
|
|
25
23
|
License-File: LICENSE
|
|
26
24
|
Requires-Dist: fastapi>=0.104.0
|
|
@@ -41,22 +39,20 @@ Dynamic: requires-python
|
|
|
41
39
|
# more-compute
|
|
42
40
|
|
|
43
41
|
[](https://pypi.org/project/more-compute/)
|
|
44
|
-
[](https://www.python.org/downloads/)
|
|
45
43
|
[](LICENSE)
|
|
46
44
|
|
|
47
|
-
An interactive notebook environment, similar to Marimo and Google Colab, that runs locally.
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
An interactive Python notebook environment, similar to Marimo and Google Colab, that runs locally.
|
|
50
46
|
|
|
51
47
|
|
|
52
48
|
https://github.com/user-attachments/assets/8c7ec716-dade-4de2-ad37-71d328129c97
|
|
53
49
|
|
|
54
50
|
|
|
55
|
-
|
|
56
|
-
|
|
57
51
|
## Installation
|
|
58
52
|
|
|
59
|
-
**Prerequisites:**
|
|
53
|
+
**Prerequisites:**
|
|
54
|
+
- [Node.js](https://nodejs.org/) >= 20.10.0 required for web interface
|
|
55
|
+
- Python >= 3.10 (uv installs this automatically, pip users need to install manually)
|
|
60
56
|
|
|
61
57
|
### Using uv (Recommended)
|
|
62
58
|
|
|
@@ -83,40 +79,46 @@ pip install more-compute
|
|
|
83
79
|
## Usage
|
|
84
80
|
|
|
85
81
|
```bash
|
|
86
|
-
more-compute notebook.
|
|
87
|
-
more-compute
|
|
82
|
+
more-compute notebook.py # Open existing notebook
|
|
83
|
+
more-compute new # Create new notebook
|
|
88
84
|
more-compute --debug # Show logs
|
|
89
85
|
```
|
|
90
86
|
|
|
91
|
-
Opens automatically at http://localhost:
|
|
87
|
+
Opens automatically at http://localhost:3141
|
|
92
88
|
|
|
93
|
-
|
|
89
|
+
### Converting Between Formats
|
|
94
90
|
|
|
95
|
-
|
|
96
|
-
```bash
|
|
97
|
-
uv tool update-shell # Fixes PATH automatically
|
|
98
|
-
```
|
|
91
|
+
MoreCompute uses `.py` notebooks with `# %%` cell markers, but you can convert to/from `.ipynb`:
|
|
99
92
|
|
|
100
|
-
**
|
|
93
|
+
**From .ipynb to .py:**
|
|
101
94
|
```bash
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
```
|
|
95
|
+
# Auto-detect output name (notebook.ipynb -> notebook.py)
|
|
96
|
+
more-compute convert notebook.ipynb
|
|
105
97
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
# Restart PowerShell
|
|
98
|
+
# Or specify output
|
|
99
|
+
more-compute convert notebook.ipynb -o my_notebook.py
|
|
100
|
+
|
|
101
|
+
# Then open in MoreCompute
|
|
102
|
+
more-compute my_notebook.py
|
|
112
103
|
```
|
|
113
104
|
|
|
114
|
-
|
|
105
|
+
The converter automatically extracts dependencies from `!pip install` commands and adds UV inline script metadata.
|
|
106
|
+
|
|
107
|
+
**From .py to .ipynb:**
|
|
115
108
|
```bash
|
|
116
|
-
|
|
117
|
-
|
|
109
|
+
# Auto-detect output name (notebook.py -> notebook.ipynb)
|
|
110
|
+
more-compute convert notebook.py
|
|
111
|
+
|
|
112
|
+
# Or specify output
|
|
113
|
+
more-compute convert notebook.py -o colab_notebook.ipynb
|
|
118
114
|
```
|
|
119
115
|
|
|
116
|
+
This makes your notebooks compatible with Google Colab, Jupyter, and other tools that require `.ipynb` format.
|
|
117
|
+
|
|
118
|
+
## Troubleshooting
|
|
119
|
+
|
|
120
|
+
will add things here as things progress...
|
|
121
|
+
|
|
120
122
|
## Development
|
|
121
123
|
|
|
122
124
|
```bash
|
|
@@ -125,7 +127,7 @@ cd MORECOMPUTE
|
|
|
125
127
|
uv venv && source .venv/bin/activate
|
|
126
128
|
uv pip install -e .
|
|
127
129
|
cd frontend && npm install && cd ..
|
|
128
|
-
|
|
130
|
+
more-compute notebook.py
|
|
129
131
|
```
|
|
130
132
|
|
|
131
133
|
## License
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# more-compute
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/more-compute/)
|
|
4
|
+
[](https://www.python.org/downloads/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
An interactive Python notebook environment, similar to Marimo and Google Colab, that runs locally.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
https://github.com/user-attachments/assets/8c7ec716-dade-4de2-ad37-71d328129c97
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
**Prerequisites:**
|
|
16
|
+
- [Node.js](https://nodejs.org/) >= 20.10.0 required for web interface
|
|
17
|
+
- Python >= 3.10 (uv installs this automatically, pip users need to install manually)
|
|
18
|
+
|
|
19
|
+
### Using uv (Recommended)
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# macOS/Linux
|
|
23
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
24
|
+
uv tool install more-compute
|
|
25
|
+
|
|
26
|
+
# Windows
|
|
27
|
+
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
28
|
+
uv tool install more-compute
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Using pip
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install more-compute
|
|
35
|
+
|
|
36
|
+
# Add to PATH if needed:
|
|
37
|
+
# macOS/Linux: echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
|
|
38
|
+
# Windows: See troubleshooting below
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
more-compute notebook.py # Open existing notebook
|
|
45
|
+
more-compute new # Create new notebook
|
|
46
|
+
more-compute --debug # Show logs
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Opens automatically at http://localhost:3141
|
|
50
|
+
|
|
51
|
+
### Converting Between Formats
|
|
52
|
+
|
|
53
|
+
MoreCompute uses `.py` notebooks with `# %%` cell markers, but you can convert to/from `.ipynb`:
|
|
54
|
+
|
|
55
|
+
**From .ipynb to .py:**
|
|
56
|
+
```bash
|
|
57
|
+
# Auto-detect output name (notebook.ipynb -> notebook.py)
|
|
58
|
+
more-compute convert notebook.ipynb
|
|
59
|
+
|
|
60
|
+
# Or specify output
|
|
61
|
+
more-compute convert notebook.ipynb -o my_notebook.py
|
|
62
|
+
|
|
63
|
+
# Then open in MoreCompute
|
|
64
|
+
more-compute my_notebook.py
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The converter automatically extracts dependencies from `!pip install` commands and adds UV inline script metadata.
|
|
68
|
+
|
|
69
|
+
**From .py to .ipynb:**
|
|
70
|
+
```bash
|
|
71
|
+
# Auto-detect output name (notebook.py -> notebook.ipynb)
|
|
72
|
+
more-compute convert notebook.py
|
|
73
|
+
|
|
74
|
+
# Or specify output
|
|
75
|
+
more-compute convert notebook.py -o colab_notebook.ipynb
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
This makes your notebooks compatible with Google Colab, Jupyter, and other tools that require `.ipynb` format.
|
|
79
|
+
|
|
80
|
+
## Troubleshooting
|
|
81
|
+
|
|
82
|
+
will add things here as things progress...
|
|
83
|
+
|
|
84
|
+
## Development
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
git clone https://github.com/DannyMang/MORECOMPUTE.git
|
|
88
|
+
cd MORECOMPUTE
|
|
89
|
+
uv venv && source .venv/bin/activate
|
|
90
|
+
uv pip install -e .
|
|
91
|
+
cd frontend && npm install && cd ..
|
|
92
|
+
more-compute notebook.py
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## License
|
|
96
|
+
|
|
97
|
+
MIT - see [LICENSE](LICENSE)
|
|
@@ -643,7 +643,8 @@ body {
|
|
|
643
643
|
}
|
|
644
644
|
|
|
645
645
|
.markdown-rendered code {
|
|
646
|
-
background:
|
|
646
|
+
background: var(--mc-secondary);
|
|
647
|
+
color: var(--mc-text-color);
|
|
647
648
|
padding: 2px 4px;
|
|
648
649
|
border-radius: 3px;
|
|
649
650
|
font-family: 'Fira', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
|
|
@@ -651,7 +652,7 @@ body {
|
|
|
651
652
|
}
|
|
652
653
|
|
|
653
654
|
.markdown-rendered pre {
|
|
654
|
-
background:
|
|
655
|
+
background: var(--mc-secondary);
|
|
655
656
|
padding: 12px;
|
|
656
657
|
border-radius: 6px;
|
|
657
658
|
margin: 12px 0;
|
|
@@ -665,7 +666,7 @@ body {
|
|
|
665
666
|
}
|
|
666
667
|
|
|
667
668
|
.markdown-rendered blockquote {
|
|
668
|
-
border-left: 3px solid
|
|
669
|
+
border-left: 3px solid var(--mc-border);
|
|
669
670
|
padding-left: 12px;
|
|
670
671
|
margin: 12px 0;
|
|
671
672
|
color: var(--mc-markdown-paragraph-color);
|
|
@@ -684,7 +685,7 @@ body {
|
|
|
684
685
|
}
|
|
685
686
|
|
|
686
687
|
.markdown-rendered .empty-markdown {
|
|
687
|
-
color:
|
|
688
|
+
color: var(--mc-line-number-color);
|
|
688
689
|
font-style: italic;
|
|
689
690
|
}
|
|
690
691
|
|
|
@@ -697,19 +698,20 @@ body {
|
|
|
697
698
|
flex-direction: column;
|
|
698
699
|
align-items: center;
|
|
699
700
|
font-size: 11px;
|
|
700
|
-
color:
|
|
701
|
+
color: var(--mc-line-number-color);
|
|
701
702
|
width: 30px;
|
|
702
703
|
}
|
|
703
704
|
|
|
704
705
|
.execution-count {
|
|
705
706
|
font-family: 'Fira', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
|
|
706
707
|
font-size: 10px;
|
|
707
|
-
color:
|
|
708
|
+
color: var(--mc-line-number-color);
|
|
708
709
|
}
|
|
709
710
|
|
|
710
711
|
.execution-time {
|
|
711
712
|
font-size: 9px;
|
|
712
|
-
color:
|
|
713
|
+
color: var(--mc-line-number-color);
|
|
714
|
+
opacity: 0.7;
|
|
713
715
|
margin-top: 2px;
|
|
714
716
|
}
|
|
715
717
|
|
|
@@ -8,6 +8,7 @@ import PackagesPopup from "@/components/popups/PackagesPopup";
|
|
|
8
8
|
import ComputePopup from "@/components/popups/ComputePopup";
|
|
9
9
|
import MetricsPopup from "@/components/popups/MetricsPopup";
|
|
10
10
|
import SettingsPopup from "@/components/popups/SettingsPopup";
|
|
11
|
+
import ConfirmModal from "@/components/modals/ConfirmModal";
|
|
11
12
|
import { ConnectionBanner } from "@/components/layout/ConnectionBanner";
|
|
12
13
|
import {
|
|
13
14
|
PodWebSocketProvider,
|
|
@@ -22,6 +23,7 @@ const POLL_MS = 3000;
|
|
|
22
23
|
function AppContent({ children }: { children: React.ReactNode }) {
|
|
23
24
|
const [appSettings, setAppSettings] = useState<NotebookSettings>(() => loadSettings());
|
|
24
25
|
const [activePopup, setActivePopup] = useState<string | null>(null);
|
|
26
|
+
const [showRestartModal, setShowRestartModal] = useState(false);
|
|
25
27
|
const { connectionState, gpuPods, connectingPodId } = usePodWebSocket();
|
|
26
28
|
|
|
27
29
|
// Persistent metrics collection
|
|
@@ -84,6 +86,15 @@ function AppContent({ children }: { children: React.ReactNode }) {
|
|
|
84
86
|
setActivePopup(null);
|
|
85
87
|
};
|
|
86
88
|
|
|
89
|
+
const handleRestartKernel = () => {
|
|
90
|
+
// Send reset kernel command via WebSocket
|
|
91
|
+
const ws = new WebSocket('ws://127.0.0.1:3141/ws');
|
|
92
|
+
ws.onopen = () => {
|
|
93
|
+
ws.send(JSON.stringify({ type: 'reset_kernel' }));
|
|
94
|
+
setTimeout(() => ws.close(), 100);
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
|
|
87
98
|
const renderPopup = () => {
|
|
88
99
|
if (!activePopup) return null;
|
|
89
100
|
|
|
@@ -176,7 +187,28 @@ function AppContent({ children }: { children: React.ReactNode }) {
|
|
|
176
187
|
id="kernel-status-dot"
|
|
177
188
|
className="status-dot connecting"
|
|
178
189
|
></span>
|
|
179
|
-
<span
|
|
190
|
+
<span
|
|
191
|
+
id="kernel-status-text"
|
|
192
|
+
className="status-text"
|
|
193
|
+
data-original-text="Connecting..."
|
|
194
|
+
style={{
|
|
195
|
+
cursor: 'pointer',
|
|
196
|
+
transition: 'all 0.15s ease',
|
|
197
|
+
}}
|
|
198
|
+
onMouseEnter={(e) => {
|
|
199
|
+
const originalText = e.currentTarget.textContent || '';
|
|
200
|
+
e.currentTarget.setAttribute('data-original-text', originalText);
|
|
201
|
+
e.currentTarget.textContent = 'Restart Kernel';
|
|
202
|
+
e.currentTarget.style.color = 'var(--mc-primary)';
|
|
203
|
+
}}
|
|
204
|
+
onMouseLeave={(e) => {
|
|
205
|
+
const originalText = e.currentTarget.getAttribute('data-original-text') || 'Connecting...';
|
|
206
|
+
e.currentTarget.textContent = originalText;
|
|
207
|
+
e.currentTarget.style.color = '';
|
|
208
|
+
}}
|
|
209
|
+
onClick={() => setShowRestartModal(true)}
|
|
210
|
+
title="Click to restart kernel"
|
|
211
|
+
>
|
|
180
212
|
Connecting...
|
|
181
213
|
</span>
|
|
182
214
|
</div>
|
|
@@ -197,6 +229,16 @@ function AppContent({ children }: { children: React.ReactNode }) {
|
|
|
197
229
|
/>
|
|
198
230
|
</div>
|
|
199
231
|
</div>
|
|
232
|
+
<ConfirmModal
|
|
233
|
+
isOpen={showRestartModal}
|
|
234
|
+
onClose={() => setShowRestartModal(false)}
|
|
235
|
+
onConfirm={handleRestartKernel}
|
|
236
|
+
title="Restart Kernel"
|
|
237
|
+
message="Are you sure you want to restart the kernel? All variables will be lost."
|
|
238
|
+
confirmLabel="Restart"
|
|
239
|
+
cancelLabel="Cancel"
|
|
240
|
+
isDangerous={true}
|
|
241
|
+
/>
|
|
200
242
|
</>
|
|
201
243
|
);
|
|
202
244
|
}
|
|
@@ -276,10 +276,18 @@ function notebookReducer(
|
|
|
276
276
|
case "EXECUTION_COMPLETE": {
|
|
277
277
|
const payload = action.payload || {};
|
|
278
278
|
const cell_index = payload.cell_index;
|
|
279
|
+
|
|
280
|
+
console.log(`[EXECUTION_COMPLETE] Processing completion for cell ${cell_index}`, payload);
|
|
281
|
+
|
|
279
282
|
// Support both shapes: { result: {...} } and flat payload {...}
|
|
280
283
|
const result = payload && payload.result ? payload.result : payload || {};
|
|
284
|
+
|
|
285
|
+
console.log(`[EXECUTION_COMPLETE] result.status=${result.status}, result.error=`, result.error);
|
|
286
|
+
|
|
287
|
+
// ALWAYS remove cell from executingCells when completion arrives
|
|
281
288
|
const newExecuting = new Set(state.executingCells);
|
|
282
289
|
newExecuting.delete(cell_index);
|
|
290
|
+
|
|
283
291
|
return {
|
|
284
292
|
...state,
|
|
285
293
|
executingCells: newExecuting,
|
|
@@ -310,8 +318,13 @@ function notebookReducer(
|
|
|
310
318
|
|
|
311
319
|
case "EXECUTION_ERROR": {
|
|
312
320
|
const { cell_index, error } = action.payload;
|
|
321
|
+
|
|
322
|
+
console.log(`[EXECUTION_ERROR] Processing error for cell ${cell_index}`);
|
|
323
|
+
|
|
324
|
+
// ALWAYS remove cell from executingCells when error arrives
|
|
313
325
|
const newExecuting = new Set(state.executingCells);
|
|
314
326
|
newExecuting.delete(cell_index);
|
|
327
|
+
|
|
315
328
|
const normalizedError = normalizeError(error);
|
|
316
329
|
return {
|
|
317
330
|
...state,
|
|
@@ -348,6 +361,8 @@ function notebookReducer(
|
|
|
348
361
|
...cell,
|
|
349
362
|
outputs: [],
|
|
350
363
|
execution_count: null,
|
|
364
|
+
execution_time: null,
|
|
365
|
+
error: null,
|
|
351
366
|
})),
|
|
352
367
|
};
|
|
353
368
|
|
|
@@ -435,6 +450,10 @@ export const Notebook: React.FC<NotebookProps> = ({
|
|
|
435
450
|
dispatch({ type: "NOTEBOOK_UPDATED", payload: data });
|
|
436
451
|
}, []);
|
|
437
452
|
|
|
453
|
+
const handleKernelRestarted = useCallback(() => {
|
|
454
|
+
dispatch({ type: "RESET_KERNEL" });
|
|
455
|
+
}, []);
|
|
456
|
+
|
|
438
457
|
const handleHeartbeat = useCallback((data: any) => {
|
|
439
458
|
// Heartbeat received - execution still in progress
|
|
440
459
|
// Cell spinner already showing via executingCells set
|
|
@@ -473,7 +492,7 @@ export const Notebook: React.FC<NotebookProps> = ({
|
|
|
473
492
|
wsRef.current = ws;
|
|
474
493
|
handleKernelStatusUpdate("connecting");
|
|
475
494
|
|
|
476
|
-
ws.connect("ws://127.0.0.1:
|
|
495
|
+
ws.connect("ws://127.0.0.1:3141/ws")
|
|
477
496
|
.then(() => {
|
|
478
497
|
ws.loadNotebook(notebookName || "default");
|
|
479
498
|
})
|
|
@@ -486,6 +505,7 @@ export const Notebook: React.FC<NotebookProps> = ({
|
|
|
486
505
|
ws.on("disconnect", () => handleKernelStatusUpdate("disconnected"));
|
|
487
506
|
ws.on("notebook_loaded", handleNotebookLoaded);
|
|
488
507
|
ws.on("notebook_updated", handleNotebookUpdate);
|
|
508
|
+
ws.on("kernel_restarted", handleKernelRestarted);
|
|
489
509
|
ws.on("execution_start", handleExecutionStart);
|
|
490
510
|
ws.on("stream_output", handleStreamOutput);
|
|
491
511
|
ws.on("execution_complete", handleExecutionComplete);
|
|
@@ -499,6 +519,7 @@ export const Notebook: React.FC<NotebookProps> = ({
|
|
|
499
519
|
handleKernelStatusUpdate,
|
|
500
520
|
handleNotebookLoaded,
|
|
501
521
|
handleNotebookUpdate,
|
|
522
|
+
handleKernelRestarted,
|
|
502
523
|
handleExecutionStart,
|
|
503
524
|
handleStreamOutput,
|
|
504
525
|
handleExecuteResult,
|
|
@@ -22,7 +22,8 @@ export const CellButton: React.FC<CellButtonProps> = ({
|
|
|
22
22
|
const [isHovered, setIsHovered] = useState(false);
|
|
23
23
|
|
|
24
24
|
const handleClick = (e: React.MouseEvent) => {
|
|
25
|
-
if (onClick && !disabled
|
|
25
|
+
if (onClick && !disabled) {
|
|
26
|
+
// Allow clicks even when loading (for stop/interrupt functionality)
|
|
26
27
|
onClick(e);
|
|
27
28
|
}
|
|
28
29
|
};
|
|
@@ -34,7 +35,7 @@ export const CellButton: React.FC<CellButtonProps> = ({
|
|
|
34
35
|
onClick={handleClick}
|
|
35
36
|
onMouseEnter={() => setIsHovered(true)}
|
|
36
37
|
onMouseLeave={() => setIsHovered(false)}
|
|
37
|
-
disabled={disabled
|
|
38
|
+
disabled={disabled}
|
|
38
39
|
title={title}
|
|
39
40
|
style={{
|
|
40
41
|
width: '28px',
|
|
@@ -45,9 +46,9 @@ export const CellButton: React.FC<CellButtonProps> = ({
|
|
|
45
46
|
display: 'flex',
|
|
46
47
|
alignItems: 'center',
|
|
47
48
|
justifyContent: 'center',
|
|
48
|
-
cursor: disabled
|
|
49
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
49
50
|
transition: 'background-color 0.15s ease',
|
|
50
|
-
opacity: disabled ? 0.5 : 1
|
|
51
|
+
opacity: disabled ? 0.5 : isLoading ? 0.8 : 1
|
|
51
52
|
}}
|
|
52
53
|
>
|
|
53
54
|
{icon}
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
UpdateIcon,
|
|
13
13
|
LinkBreak2Icon,
|
|
14
14
|
PlayIcon,
|
|
15
|
+
StopIcon,
|
|
15
16
|
ChevronUpIcon,
|
|
16
17
|
ChevronDownIcon,
|
|
17
18
|
} from "@radix-ui/react-icons";
|
|
@@ -269,13 +270,13 @@ export const MonacoCell: React.FC<CellProps> = ({
|
|
|
269
270
|
onExecute(indexRef.current);
|
|
270
271
|
setIsEditing(false);
|
|
271
272
|
} else {
|
|
272
|
-
|
|
273
|
-
onInterrupt(indexRef.current);
|
|
274
|
-
} else {
|
|
275
|
-
onExecute(indexRef.current);
|
|
276
|
-
}
|
|
273
|
+
onExecute(indexRef.current);
|
|
277
274
|
}
|
|
278
|
-
}, [cell.cell_type,
|
|
275
|
+
}, [cell.cell_type, onExecute]);
|
|
276
|
+
|
|
277
|
+
const handleInterrupt = useCallback(() => {
|
|
278
|
+
onInterrupt(indexRef.current);
|
|
279
|
+
}, [onInterrupt]);
|
|
279
280
|
|
|
280
281
|
const handleCellClick = () => {
|
|
281
282
|
onSetActive(indexRef.current);
|
|
@@ -583,15 +584,26 @@ export const MonacoCell: React.FC<CellProps> = ({
|
|
|
583
584
|
<div className="cell-hover-controls">
|
|
584
585
|
<div className="cell-actions-right">
|
|
585
586
|
{!isMarkdownWithContent && (
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
e
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
587
|
+
<>
|
|
588
|
+
<CellButton
|
|
589
|
+
icon={<PlayIcon className="w-6 h-6" />}
|
|
590
|
+
onClick={(e) => {
|
|
591
|
+
e.stopPropagation();
|
|
592
|
+
handleExecute();
|
|
593
|
+
}}
|
|
594
|
+
title="Run cell"
|
|
595
|
+
disabled={isExecuting}
|
|
596
|
+
/>
|
|
597
|
+
<CellButton
|
|
598
|
+
icon={<StopIcon className="w-6 h-6" />}
|
|
599
|
+
onClick={(e) => {
|
|
600
|
+
e.stopPropagation();
|
|
601
|
+
handleInterrupt();
|
|
602
|
+
}}
|
|
603
|
+
title="Stop execution"
|
|
604
|
+
disabled={!isExecuting}
|
|
605
|
+
/>
|
|
606
|
+
</>
|
|
595
607
|
)}
|
|
596
608
|
<CellButton
|
|
597
609
|
icon={<ChevronUpIcon className="w-6 h-6" />}
|
|
@@ -599,8 +611,8 @@ export const MonacoCell: React.FC<CellProps> = ({
|
|
|
599
611
|
e.stopPropagation();
|
|
600
612
|
onMoveUp(indexRef.current);
|
|
601
613
|
}}
|
|
602
|
-
title="Move cell up"
|
|
603
|
-
disabled={index === 0}
|
|
614
|
+
title={isExecuting ? "Cannot move while executing" : "Move cell up"}
|
|
615
|
+
disabled={isExecuting || index === 0}
|
|
604
616
|
/>
|
|
605
617
|
<CellButton
|
|
606
618
|
icon={<ChevronDownIcon className="w-6 h-6" />}
|
|
@@ -608,16 +620,25 @@ export const MonacoCell: React.FC<CellProps> = ({
|
|
|
608
620
|
e.stopPropagation();
|
|
609
621
|
onMoveDown(indexRef.current);
|
|
610
622
|
}}
|
|
611
|
-
title="Move cell down"
|
|
612
|
-
disabled={index === totalCells - 1}
|
|
623
|
+
title={isExecuting ? "Cannot move while executing" : "Move cell down"}
|
|
624
|
+
disabled={isExecuting || index === totalCells - 1}
|
|
613
625
|
/>
|
|
614
626
|
<CellButton
|
|
615
627
|
icon={<LinkBreak2Icon className="w-5 h-5" />}
|
|
616
628
|
onClick={(e) => {
|
|
617
629
|
e.stopPropagation();
|
|
618
|
-
|
|
630
|
+
// If cell is executing, interrupt it first
|
|
631
|
+
if (isExecuting) {
|
|
632
|
+
onInterrupt(indexRef.current);
|
|
633
|
+
// Wait a bit for interrupt to complete, then delete
|
|
634
|
+
setTimeout(() => {
|
|
635
|
+
onDelete(indexRef.current);
|
|
636
|
+
}, 500);
|
|
637
|
+
} else {
|
|
638
|
+
onDelete(indexRef.current);
|
|
639
|
+
}
|
|
619
640
|
}}
|
|
620
|
-
title="Delete cell"
|
|
641
|
+
title={isExecuting ? "Stop and delete cell" : "Delete cell"}
|
|
621
642
|
/>
|
|
622
643
|
</div>
|
|
623
644
|
</div>
|
|
@@ -165,7 +165,20 @@ const TypedErrorDisplay: FC<{ error: ErrorOutput }> = ({ error }) => {
|
|
|
165
165
|
margin: 0
|
|
166
166
|
}}
|
|
167
167
|
>
|
|
168
|
-
{error
|
|
168
|
+
{/* Always show error name and message */}
|
|
169
|
+
{error.ename && (
|
|
170
|
+
<div style={{ fontWeight: 600, marginBottom: '4px' }}>
|
|
171
|
+
{error.ename}: {error.evalue}
|
|
172
|
+
</div>
|
|
173
|
+
)}
|
|
174
|
+
{/* Show traceback if available */}
|
|
175
|
+
{error.traceback && error.traceback.length > 0 && (
|
|
176
|
+
<div>{error.traceback.join('\n')}</div>
|
|
177
|
+
)}
|
|
178
|
+
{/* Fallback if no traceback */}
|
|
179
|
+
{(!error.traceback || error.traceback.length === 0) && !error.ename && (
|
|
180
|
+
<div>An unknown error occurred</div>
|
|
181
|
+
)}
|
|
169
182
|
</div>
|
|
170
183
|
</div>
|
|
171
184
|
</div>
|
|
@@ -95,7 +95,7 @@ export const PodWebSocketProvider: React.FC<PodWebSocketProviderProps> = ({ chil
|
|
|
95
95
|
wsRef.current = null;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
const wsUrl = 'ws://127.0.0.1:
|
|
98
|
+
const wsUrl = 'ws://127.0.0.1:3141/ws';
|
|
99
99
|
const ws = new WebSocket(wsUrl);
|
|
100
100
|
|
|
101
101
|
ws.onopen = () => {
|
|
@@ -53,12 +53,12 @@ export class WebSocketService {
|
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
connect(url: string = 'ws://localhost:
|
|
56
|
+
connect(url: string = 'ws://localhost:3141'): Promise<void> {
|
|
57
57
|
return new Promise((resolve, reject) => {
|
|
58
58
|
// For development, connect directly to the backend WebSocket
|
|
59
59
|
const wsUrl = process.env.NODE_ENV === 'production'
|
|
60
60
|
? '/ws'
|
|
61
|
-
: 'ws://localhost:
|
|
61
|
+
: 'ws://localhost:3141/ws';
|
|
62
62
|
|
|
63
63
|
// Use native WebSocket for FastAPI compatibility
|
|
64
64
|
const ws = new WebSocket(wsUrl);
|
|
@@ -4,11 +4,11 @@ const nextConfig = {
|
|
|
4
4
|
return [
|
|
5
5
|
{
|
|
6
6
|
source: '/ws/:path*',
|
|
7
|
-
destination: 'http://localhost:
|
|
7
|
+
destination: 'http://localhost:3141/ws/:path*',
|
|
8
8
|
},
|
|
9
9
|
{
|
|
10
10
|
source: '/api/:path*',
|
|
11
|
-
destination: 'http://localhost:
|
|
11
|
+
destination: 'http://localhost:3141/api/:path*',
|
|
12
12
|
},
|
|
13
13
|
];
|
|
14
14
|
},
|