nebula-notebook 0.1.1 → 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 (78) hide show
  1. package/README.md +90 -11
  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 -6
  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/headless-handler.d.ts +2 -0
  48. package/node-server/dist/notebook/headless-handler.js +70 -24
  49. package/node-server/dist/notebook/operation-router.js +7 -2
  50. package/node-server/dist/notebook/undoRedoManager.d.ts +4 -1
  51. package/node-server/dist/notebook/undoRedoManager.js +10 -2
  52. package/node-server/dist/output/display-data.js +2 -0
  53. package/node-server/dist/routes/cluster.js +2 -2
  54. package/node-server/dist/routes/compute.d.ts +8 -0
  55. package/node-server/dist/routes/compute.js +136 -0
  56. package/node-server/dist/routes/fs.js +2 -2
  57. package/node-server/dist/routes/kernel.js +111 -1
  58. package/node-server/dist/routes/notebook.js +29 -1
  59. package/node-server/dist/scheduler/allocation-service.d.ts +43 -0
  60. package/node-server/dist/scheduler/allocation-service.js +169 -0
  61. package/node-server/dist/scheduler/job-template.d.ts +30 -0
  62. package/node-server/dist/scheduler/job-template.js +85 -0
  63. package/node-server/dist/scheduler/mock-scheduler.d.ts +30 -0
  64. package/node-server/dist/scheduler/mock-scheduler.js +121 -0
  65. package/node-server/dist/scheduler/slurm-scheduler.d.ts +31 -0
  66. package/node-server/dist/scheduler/slurm-scheduler.js +393 -0
  67. package/node-server/dist/scheduler/types.d.ts +117 -0
  68. package/node-server/dist/scheduler/types.js +8 -0
  69. package/node-server/dist/scheduler/util.d.ts +7 -0
  70. package/node-server/dist/scheduler/util.js +20 -0
  71. package/node-server/dist/terminal/pty-manager.js +8 -0
  72. package/node-server/dist/terminal/server.js +43 -2
  73. package/node-server/dist/update-check.d.ts +20 -0
  74. package/node-server/dist/update-check.js +114 -0
  75. package/node-server/package.json +1 -0
  76. package/package.json +2 -1
  77. package/dist/assets/index-BvrHu37J.js +0 -648
  78. package/dist/assets/index-Dfj_xsKU.css +0 -32
package/README.md CHANGED
@@ -1,26 +1,93 @@
1
1
  # Nebula Notebook
2
2
 
3
- Nebula is an agent-native notebook computing environment built for what's coming next: real Jupyter kernels, real filesystem access, and a notebook that agents (Claude Code, Codex, …) can drive end-to-end through MCP — while staying a fast, polished notebook even if you never touch the AI features.
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
4
 
5
- ![Nebula Notebook — agents drive the notebook via MCP](https://raw.githubusercontent.com/jzthree/nebula-notebook/main/docs/assets/nebula-hero.svg)
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>
6
54
 
7
55
  ## Quick Start
8
56
 
57
+ ### On your machine
58
+
9
59
  ```bash
10
60
  npx nebula-notebook
11
61
  ```
12
62
 
13
- 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.
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.
14
66
 
15
- Open http://localhost:3000 and enter your 6-digit code.
67
+ ### On a cluster / remote server
16
68
 
17
- To let agents (Claude Code, Codex, Cursor, Gemini CLI, …) drive your notebooks, register the Nebula MCP on the machine where your agent runs:
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:
18
85
 
19
86
  ```bash
20
87
  npx nebula-notebook-mcp setup-mcp
21
88
  ```
22
89
 
23
- Then open a notebook, click **Agent**, and launch Claude Code or Codex right in the notebook's terminal.
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.
24
91
 
25
92
  ### From source (latest)
26
93
 
@@ -47,8 +114,8 @@ This root is used for the file browser and terminals. You can also change it fro
47
114
  ## Features
48
115
 
49
116
  **Core**
50
- - Real Jupyter kernel execution (Python, Julia, R, etc.)
51
- - 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
52
119
  - Autosave with crash recovery
53
120
  - Undo/redo with full edit history
54
121
 
@@ -87,8 +154,12 @@ See [docs/RICH_OUTPUTS.md](docs/RICH_OUTPUTS.md) for examples, payload format, s
87
154
 
88
155
  ## Prerequisites
89
156
 
90
- - Node.js 18+
91
- - 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.
92
163
 
93
164
  ## Project Structure
94
165
 
@@ -222,6 +293,14 @@ Servers without the correct secret will be rejected during registration.
222
293
  - Client servers need access to the same filesystem paths as the main server (for notebook files)
223
294
  - Each server runs its own Jupyter kernels locally
224
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
+
225
304
  ## Tips
226
305
 
227
306
  **Persistent Terminals**: Access standalone terminals via URL:
@@ -236,7 +315,7 @@ Terminals persist as long as the server runs. Bookmark different terminals for q
236
315
  - **Frontend**: React 19, TypeScript, Vite, Tailwind CSS, CodeMirror
237
316
  - **Backend**: Node.js, Fastify, ZeroMQ (Jupyter kernel protocol)
238
317
  - **Auth**: TOTP (otplib), JWT (jsonwebtoken)
239
- - **Agents**: MCP (`nebula-notebook-mcp`) driven by Claude Code, Codex, and other agent CLIs
318
+ - **Agents**: MCP (`nebula-notebook-mcp`), used by Claude Code, Codex, and other agent CLIs
240
319
 
241
320
  ## License
242
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};