nebula-notebook 0.1.0 → 0.2.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 (81) hide show
  1. package/README.md +124 -24
  2. package/dist/assets/errorwidget-C4r2j2DQ.js +5 -0
  3. package/dist/assets/fa-brands-400-CEJbCg16.woff +0 -0
  4. package/dist/assets/fa-brands-400-CSYNqBb_.ttf +0 -0
  5. package/dist/assets/fa-brands-400-DnkPfk3o.eot +0 -0
  6. package/dist/assets/fa-brands-400-UxlILjvJ.woff2 +0 -0
  7. package/dist/assets/fa-brands-400-cH1MgKbP.svg +3717 -0
  8. package/dist/assets/fa-regular-400-BhTwtT8w.eot +0 -0
  9. package/dist/assets/fa-regular-400-D1vz6WBx.ttf +0 -0
  10. package/dist/assets/fa-regular-400-DFnMcJPd.woff +0 -0
  11. package/dist/assets/fa-regular-400-DGzu1beS.woff2 +0 -0
  12. package/dist/assets/fa-regular-400-gwj8Pxq-.svg +801 -0
  13. package/dist/assets/fa-solid-900-B4ZZ7kfP.svg +5034 -0
  14. package/dist/assets/fa-solid-900-B6Axprfb.eot +0 -0
  15. package/dist/assets/fa-solid-900-BUswJgRo.woff2 +0 -0
  16. package/dist/assets/fa-solid-900-DOXgCApm.woff +0 -0
  17. package/dist/assets/fa-solid-900-mxuxnBEa.ttf +0 -0
  18. package/dist/assets/index-7-YBurka.js +716 -0
  19. package/dist/assets/index-BtWv4MIT.css +7 -0
  20. package/dist/assets/index-CFBUnxSZ.css +32 -0
  21. package/dist/assets/index-CsHoPQy-.js +1 -0
  22. package/dist/assets/index-D5w21_Z8.js +81 -0
  23. package/dist/assets/index-Day3QcNs.js +1 -0
  24. package/dist/assets/services-shim-D6p_A67v.js +33 -0
  25. package/dist/assets/viewlist-uomDf7I7.js +1 -0
  26. package/dist/assets/widgets-X7J3NxEn.css +1 -0
  27. package/dist/index.html +2 -2
  28. package/node-server/dist/cluster/client-registration.js +3 -0
  29. package/node-server/dist/cluster/kernel-proxy.js +24 -9
  30. package/node-server/dist/cluster/server-registry.d.ts +8 -0
  31. package/node-server/dist/cluster/server-registry.js +31 -7
  32. package/node-server/dist/fs/fs-service.d.ts +55 -7
  33. package/node-server/dist/fs/fs-service.js +489 -80
  34. package/node-server/dist/fs/notebook-formats/percent.d.ts +25 -0
  35. package/node-server/dist/fs/notebook-formats/percent.js +286 -0
  36. package/node-server/dist/fs/notebook-formats/qmd.d.ts +29 -0
  37. package/node-server/dist/fs/notebook-formats/qmd.js +307 -0
  38. package/node-server/dist/fs/notebook-formats/registry.d.ts +12 -0
  39. package/node-server/dist/fs/notebook-formats/registry.js +77 -0
  40. package/node-server/dist/fs/notebook-formats/types.d.ts +37 -0
  41. package/node-server/dist/fs/notebook-formats/types.js +13 -0
  42. package/node-server/dist/idle-exit.d.ts +52 -0
  43. package/node-server/dist/idle-exit.js +83 -0
  44. package/node-server/dist/index.js +129 -9
  45. package/node-server/dist/kernel/kernel-service.d.ts +113 -2
  46. package/node-server/dist/kernel/kernel-service.js +762 -60
  47. package/node-server/dist/notebook/cell-hash.d.ts +13 -0
  48. package/node-server/dist/notebook/cell-hash.js +26 -0
  49. package/node-server/dist/notebook/headless-handler.d.ts +9 -0
  50. package/node-server/dist/notebook/headless-handler.js +124 -23
  51. package/node-server/dist/notebook/operation-router.d.ts +36 -0
  52. package/node-server/dist/notebook/operation-router.js +224 -9
  53. package/node-server/dist/notebook/undoRedoManager.d.ts +4 -1
  54. package/node-server/dist/notebook/undoRedoManager.js +10 -2
  55. package/node-server/dist/output/display-data.js +2 -0
  56. package/node-server/dist/routes/cluster.js +2 -2
  57. package/node-server/dist/routes/compute.d.ts +8 -0
  58. package/node-server/dist/routes/compute.js +136 -0
  59. package/node-server/dist/routes/fs.js +2 -2
  60. package/node-server/dist/routes/kernel.js +115 -3
  61. package/node-server/dist/routes/notebook.js +35 -1
  62. package/node-server/dist/scheduler/allocation-service.d.ts +43 -0
  63. package/node-server/dist/scheduler/allocation-service.js +169 -0
  64. package/node-server/dist/scheduler/job-template.d.ts +30 -0
  65. package/node-server/dist/scheduler/job-template.js +85 -0
  66. package/node-server/dist/scheduler/mock-scheduler.d.ts +30 -0
  67. package/node-server/dist/scheduler/mock-scheduler.js +121 -0
  68. package/node-server/dist/scheduler/slurm-scheduler.d.ts +31 -0
  69. package/node-server/dist/scheduler/slurm-scheduler.js +393 -0
  70. package/node-server/dist/scheduler/types.d.ts +117 -0
  71. package/node-server/dist/scheduler/types.js +8 -0
  72. package/node-server/dist/scheduler/util.d.ts +7 -0
  73. package/node-server/dist/scheduler/util.js +20 -0
  74. package/node-server/dist/terminal/pty-manager.js +8 -0
  75. package/node-server/dist/terminal/server.js +43 -2
  76. package/node-server/dist/update-check.d.ts +20 -0
  77. package/node-server/dist/update-check.js +114 -0
  78. package/node-server/package.json +1 -3
  79. package/package.json +3 -5
  80. package/dist/assets/index-C1h_sArD.css +0 -32
  81. package/dist/assets/index-CDSTBon8.js +0 -658
package/README.md CHANGED
@@ -1,9 +1,98 @@
1
1
  # Nebula Notebook
2
2
 
3
- Nebula is an AI-native notebook computing environment built for what's coming next. It also comes with an optimized user experience even if you use no AI features at all.
3
+ Nebula is an agent-native notebook built for you and your AI to work in the same cells, and a fast, polished one even if you never touch the AI.
4
+
5
+ <p align="center">
6
+ <!-- 2½-min product tour. Uploaded into the `demo-assets` release description, so GitHub
7
+ transcodes it and streams it inline via the user-attachments URL below (video/mp4,
8
+ range requests, no attachment disposition). The 12 MB original also stays attached to
9
+ that release as a downloadable asset. Neither is committed to the repo, so clones stay
10
+ lean. Renderers that strip <video> (npm, some mirrors) fall back to the link inside. -->
11
+ <video src="https://github.com/user-attachments/assets/4a9ec9ce-9ac0-4540-b35a-27c1b97a20b1" controls muted width="940" poster="https://raw.githubusercontent.com/jzthree/nebula-notebook/main/docs/assets/nebula-hero.svg">
12
+ <a href="https://github.com/jzthree/nebula-notebook/releases/download/demo-assets/nebula-demo-16x9-v10-hq.mp4">Watch the 2½-minute product tour</a>
13
+ </video>
14
+ </p>
15
+ <p align="center"><sub>▶ <a href="https://github.com/user-attachments/assets/4a9ec9ce-9ac0-4540-b35a-27c1b97a20b1">Watch the 2½-minute tour</a> · or skim the autoplay clips below</sub></p>
16
+
17
+ ## Highlights
18
+
19
+ - **Agent-native** — Claude Code, Codex, Cursor & friends operate notebooks through MCP (`npx nebula-notebook-mcp setup-mcp`); an agent terminal is built into every notebook, with one-click launch pre-briefed on your server and notebook
20
+ - **Edit while the agent edits** — per-cell optimistic concurrency: if an agent's write conflicts with yours, it's rejected and handed your current content to retry against — nothing is silently overwritten
21
+ - **"Fix with agent"** on any failing cell, plus per-cell prompts — both inject straight into the agent's terminal, context included
22
+ - **Jupyter kernels** over ZeroMQ (Python, Julia, R, …) that survive dev-server restarts and reattach
23
+ - **Rich outputs** — Plotly MIME rendering and Nebula-native interactive JS outputs, in a virtualized cell list that stays fast on large notebooks
24
+ - **Runs anywhere** — `npx nebula-notebook`, TOTP 2FA, and multi-server clusters behind a single UI
25
+ - **…and it runs where your compute lives** — on an HPC login node, allocate a scheduler job right from the kernel menu (partition/QoS/GPU, with a live queue-load monitor and soonest-queue hint) and your kernel runs on the compute node — no sbatch script, no SSH tunnel. Detection-gated: invisible off-cluster
26
+
27
+ ## See it in action
28
+
29
+ **A failing cell, fixed by the agent live** — the cell errors, the agent rewrites it (presence ring on the cell it's touching) and reruns it clean:
30
+
31
+ <p align="center">
32
+ <img src="https://raw.githubusercontent.com/jzthree/nebula-notebook/main/docs/assets/demo/scene-agent.gif" alt="A code cell throws a KeyError; an agent session starts, rewrites the cell live with a purple presence ring, reruns it, and the clean output appears" width="760">
33
+ </p>
34
+
35
+ **Interactive outputs, no widget plumbing** — `application/vnd.nebula.web+json` widgets respond to clicks:
36
+
37
+ <p align="center">
38
+ <img src="https://raw.githubusercontent.com/jzthree/nebula-notebook/main/docs/assets/demo/scene-widget.gif" alt="A Nebula-native interactive web output: clicking Resample re-rolls the bar chart live" width="760">
39
+ </p>
40
+
41
+ **Time-travel through your edit history** — preview any past moment with diff highlighting, then restore:
42
+
43
+ <p align="center">
44
+ <img src="https://raw.githubusercontent.com/jzthree/nebula-notebook/main/docs/assets/demo/scene-history.gif" alt="The History panel: clicking a past edit previews the notebook at that moment with an orange modified-cell highlight and a Restore option" width="760">
45
+ </p>
46
+
47
+ **Find across the whole notebook** — regex search with live match counts:
48
+
49
+ <p align="center">
50
+ <img src="https://raw.githubusercontent.com/jzthree/nebula-notebook/main/docs/assets/demo/scene-search.gif" alt="Notebook-wide search: typing a query highlights every match across cells with a running match count" width="760">
51
+ </p>
52
+
53
+ <sub>All clips captured headlessly from the running app — regenerate with <code>python scripts/demo-shoot.py all</code>.</sub>
4
54
 
5
55
  ## Quick Start
6
56
 
57
+ ### On your machine
58
+
59
+ ```bash
60
+ npx nebula-notebook
61
+ ```
62
+
63
+ On first start a QR code appears in the terminal — scan it with an authenticator app (Google Authenticator, Authy, …), then open http://localhost:3000 and enter the 6-digit code. A startup banner shows the URLs and what was detected.
64
+
65
+ Nebula itself is pure Node — but running notebooks needs a Python (3.10+) with `ipykernel` on the server machine. If none is found, the kernel menu detects your Python environments (venv, conda, uv, pixi, system) and shows the exact setup command for each; environments that already have `ipykernel` register with one click.
66
+
67
+ ### On a cluster / remote server
68
+
69
+ Run the server where your files and compute live; browse it through one SSH tunnel:
70
+
71
+ ```bash
72
+ # on the cluster login node (inside tmux so it outlives your session)
73
+ tmux new -s nebula
74
+ npx nebula-notebook
75
+
76
+ # from your laptop
77
+ ssh -L 3000:localhost:3000 <login-node> # then open http://localhost:3000
78
+ ```
79
+
80
+ If a SLURM scheduler is present, the kernel menu gains **New compute allocation** — your kernels run on compute nodes, no sbatch script, no extra tunnels. Full guide (bastions, persistent runs, agent placements, troubleshooting): [docs/CLUSTER_SETUP.md](docs/CLUSTER_SETUP.md).
81
+
82
+ ### Let agents in
83
+
84
+ To let agents (Claude Code, Codex, Cursor, Gemini CLI, …) operate your notebooks, register the Nebula MCP on the machine where your agent runs:
85
+
86
+ ```bash
87
+ npx nebula-notebook-mcp setup-mcp
88
+ ```
89
+
90
+ Then open a notebook, click **Agent**, and launch Claude Code or Codex right in the notebook's terminal — or use the `nebula` CLI (`npx -p nebula-notebook-mcp nebula --help`) for a lighter, shell-first integration.
91
+
92
+ ### From source (latest)
93
+
94
+ npm releases are point-in-time snapshots — to get the latest changes, install from source:
95
+
7
96
  ```bash
8
97
  git clone https://github.com/jzthree/nebula-notebook.git
9
98
  cd nebula-notebook
@@ -12,10 +101,6 @@ npm install
12
101
  npm run start
13
102
  ```
14
103
 
15
- On first start, a QR code will appear in the terminal. Scan it with an authenticator app (Google Authenticator, Authy, etc.) to set up 2FA.
16
-
17
- Open http://localhost:3000 and enter your 6-digit code.
18
-
19
104
  ## Root Directory
20
105
 
21
106
  Set the server root directory (default is your home directory):
@@ -29,8 +114,8 @@ This root is used for the file browser and terminals. You can also change it fro
29
114
  ## Features
30
115
 
31
116
  **Core**
32
- - Real Jupyter kernel execution (Python, Julia, R, etc.)
33
- - Real filesystem access - open notebooks from anywhere
117
+ - Jupyter kernel execution (Python, Julia, R, etc.)
118
+ - Built-in file browser open notebooks anywhere on disk
34
119
  - Autosave with crash recovery
35
120
  - Undo/redo with full edit history
36
121
 
@@ -39,10 +124,11 @@ This root is used for the file browser and terminals. You can also change it fro
39
124
  - Search & replace across all cells (Cmd/Ctrl+F)
40
125
  - Keyboard shortcuts (Shift+Enter to run, Cmd+S to save, etc.)
41
126
 
42
- **AI Assistant**
43
- - Multi-provider support: Gemini, OpenAI, Anthropic
44
- - Code generation and error fixing
45
- - Context-aware suggestions
127
+ **Agents**
128
+ - Agent terminal built into every notebook — one click launches Claude Code or Codex, pre-briefed with the server URL and notebook path
129
+ - "Fix with agent" on any failing cell, and per-cell prompts, injected straight into the agent's terminal
130
+ - Full MCP toolset ([`nebula-notebook-mcp`](https://www.npmjs.com/package/nebula-notebook-mcp)): read/edit/execute cells, manage kernels and files — from any agent on any machine
131
+ - Agent sessions lock the notebook during edits and sync live into the UI
46
132
 
47
133
  **Editor**
48
134
  - Syntax highlighting with CodeMirror
@@ -68,8 +154,12 @@ See [docs/RICH_OUTPUTS.md](docs/RICH_OUTPUTS.md) for examples, payload format, s
68
154
 
69
155
  ## Prerequisites
70
156
 
71
- - Node.js 18+
72
- - Python 3.10+ with Jupyter kernels (`pip install ipykernel`)
157
+ - Node.js 20+
158
+ - Python 3.10+ with `ipykernel`, on the machine running the server (other Jupyter kernels Julia, R, … — work too)
159
+
160
+ No ipykernel yet? Open the kernel menu in the UI: it detects your Python environments (venv, conda, uv, pixi, Homebrew, system), registers ready ones with one click, and shows the exact install command for the rest — including the PEP 668 "externally managed" cases (uv/Homebrew/system Python) where `pip install` is blocked and an isolated env is the right move.
161
+
162
+ Using **R** (or another non-Python kernel)? See [docs/R_KERNEL.md](docs/R_KERNEL.md) — registering IRkernel and the one-line fix for the common headless-server plotting error.
73
163
 
74
164
  ## Project Structure
75
165
 
@@ -93,19 +183,21 @@ nebula-notebook/
93
183
 
94
184
  ## MCP Adapter
95
185
 
96
- The MCP adapter now lives in this repository under `packages/mcp`. It remains a
97
- separate Node package so it can be installed on a local agent/client machine even
98
- when the Nebula Notebook server is running elsewhere.
186
+ The MCP adapter is published as [`nebula-notebook-mcp`](https://www.npmjs.com/package/nebula-notebook-mcp)
187
+ and lives in this repository under `packages/mcp`. It is a separate package so it
188
+ can be installed on a local agent/client machine even when the Nebula Notebook
189
+ server is running elsewhere.
99
190
 
100
191
  ```bash
101
- # From this repo: build or run the MCP server
192
+ # Register the MCP with your installed agent CLIs (Claude Code, Codex, …)
193
+ npx nebula-notebook-mcp setup-mcp
194
+
195
+ # Agents must call connect_server(base_url) once per session —
196
+ # the base_url is the URL you open Nebula at, e.g. http://localhost:3000
197
+
198
+ # From a repo checkout instead: build or run the MCP server
102
199
  npm run mcp:build
103
200
  npm run mcp
104
-
105
- # Client-only install from source
106
- cd packages/mcp
107
- npm install
108
- npm run build
109
201
  ```
110
202
 
111
203
  ## Authentication
@@ -201,6 +293,14 @@ Servers without the correct secret will be rejected during registration.
201
293
  - Client servers need access to the same filesystem paths as the main server (for notebook files)
202
294
  - Each server runs its own Jupyter kernels locally
203
295
 
296
+ ### Scheduler-backed compute (HPC)
297
+
298
+ On an HPC login node you don't launch client servers by hand — the scheduler does it for you. When Nebula detects a scheduler (SLURM first — `sbatch`/`squeue` on `PATH`), the kernel menu's **Server** section grows a **+ New compute allocation** entry:
299
+
300
+ - **Allocate from the notebook.** Pick a partition + QoS (only the ones your account may actually submit to), CPUs, memory, GPUs, and walltime. A **live cluster-load panel** sits beside the form — idle CPUs, idle GPUs *by type*, and per-queue backlog with your own jobs highlighted — and recommends the queue you'll land on soonest. Choosing a GPU queue narrows the GPU-type list to the models that queue actually has, so you can't request one it doesn't offer.
301
+ - **It just becomes a server.** Nebula submits the job; the allocation shows up in the Server list as *"Queued · waiting…"*, then flips to a normal online server the moment the job starts. Select it and your kernels run on the compute node — proxied over the same WebSocket path as any remote kernel, so ZeroMQ never crosses the network. One allocation hosts **many** kernels: queue once, run several notebooks in it. When the walltime ends (or you cancel), the server drops out of the list and its kernels are marked done.
302
+ - **Nothing changes off-cluster.** The whole feature is detection-gated — no scheduler on the machine, no compute UI. Design and internals in [docs/SLURM_COMPUTE.md](docs/SLURM_COMPUTE.md).
303
+
204
304
  ## Tips
205
305
 
206
306
  **Persistent Terminals**: Access standalone terminals via URL:
@@ -213,9 +313,9 @@ Terminals persist as long as the server runs. Bookmark different terminals for q
213
313
  ## Tech Stack
214
314
 
215
315
  - **Frontend**: React 19, TypeScript, Vite, Tailwind CSS, CodeMirror
216
- - **Backend**: Node.js, Express, ZeroMQ (Jupyter kernel protocol)
316
+ - **Backend**: Node.js, Fastify, ZeroMQ (Jupyter kernel protocol)
217
317
  - **Auth**: TOTP (otplib), JWT (jsonwebtoken)
218
- - **AI**: OpenAI, Anthropic, Google GenAI SDKs
318
+ - **Agents**: MCP (`nebula-notebook-mcp`), used by Claude Code, Codex, and other agent CLIs
219
319
 
220
320
  ## License
221
321
 
@@ -0,0 +1,5 @@
1
+ import{a as d,L as c,D as l,E as a}from"./services-shim-D6p_A67v.js";function h(t,s){class n extends l{constructor(r,i){r=Object.assign(Object.assign({},r),{_view_name:"ErrorWidgetView",_view_module:"@jupyter-widgets/base",_model_module_version:a,_view_module_version:a,msg:s,error:t}),super(r,i),this.comm_live=!0}}return n}class g extends d{generateErrorMessage(){return{msg:this.model.get("msg"),stack:String(this.model.get("error").stack)}}render(){const{msg:s,stack:n}=this.generateErrorMessage();this.el.classList.add("jupyter-widgets");const e=document.createElement("div");e.classList.add("jupyter-widgets-error-widget","icon-error"),e.innerHTML=c;const r=document.createElement("pre");r.style.textAlign="center",r.innerText="Click to show javascript error.",e.append(r),this.el.appendChild(e);let i,o;this.el.onclick=()=>{e.classList.contains("icon-error")&&(o=o||e.clientHeight,i=i||e.clientWidth,e.classList.remove("icon-error"),e.innerHTML=`
2
+ <pre>[Open Browser Console for more detailed log - Double click to close this message]
3
+ ${s}
4
+ ${n}</pre>
5
+ `,e.style.height=`${o}px`,e.style.width=`${i}px`,e.classList.add("text-error"))},this.el.ondblclick=()=>{e.classList.contains("text-error")&&(e.classList.remove("text-error"),e.innerHTML=c,e.append(r),e.classList.add("icon-error"))}}}function E(t,s){return class extends g{generateErrorMessage(){return{msg:s,stack:String(t instanceof Error?t.stack:t)}}}}export{g as E,E as a,h as c};