nb-lab-runtime 0.1.0__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.
- nb_lab_runtime-0.1.0/.github/workflows/openapi.yml +20 -0
- nb_lab_runtime-0.1.0/.gitignore +7 -0
- nb_lab_runtime-0.1.0/LICENSE +21 -0
- nb_lab_runtime-0.1.0/PKG-INFO +276 -0
- nb_lab_runtime-0.1.0/README.md +264 -0
- nb_lab_runtime-0.1.0/docs/agent-prompting.md +56 -0
- nb_lab_runtime-0.1.0/docs/agent-tools.md +99 -0
- nb_lab_runtime-0.1.0/docs/demo-transcript.md +35 -0
- nb_lab_runtime-0.1.0/docs/mcp-hosting.md +9 -0
- nb_lab_runtime-0.1.0/docs/mcp.json +88 -0
- nb_lab_runtime-0.1.0/docs/openapi.json +794 -0
- nb_lab_runtime-0.1.0/docs/tool-examples.md +35 -0
- nb_lab_runtime-0.1.0/examples/demo.py +24 -0
- nb_lab_runtime-0.1.0/pyproject.toml +30 -0
- nb_lab_runtime-0.1.0/scripts/gen_openapi.sh +15 -0
- nb_lab_runtime-0.1.0/scripts/install_tool.sh +8 -0
- nb_lab_runtime-0.1.0/scripts/release_check.sh +9 -0
- nb_lab_runtime-0.1.0/scripts/smoke_demo.sh +54 -0
- nb_lab_runtime-0.1.0/src/nb_lab/__init__.py +28 -0
- nb_lab_runtime-0.1.0/src/nb_lab/cell_model.py +299 -0
- nb_lab_runtime-0.1.0/src/nb_lab/cli.py +310 -0
- nb_lab_runtime-0.1.0/src/nb_lab/executor.py +397 -0
- nb_lab_runtime-0.1.0/src/nb_lab/models.py +25 -0
- nb_lab_runtime-0.1.0/src/nb_lab/notebook_edit.py +85 -0
- nb_lab_runtime-0.1.0/src/nb_lab/notebook_state.py +71 -0
- nb_lab_runtime-0.1.0/src/nb_lab/plot_meta.py +162 -0
- nb_lab_runtime-0.1.0/src/nb_lab/server.py +279 -0
- nb_lab_runtime-0.1.0/src/nb_lab/watcher.py +119 -0
- nb_lab_runtime-0.1.0/tests/conftest.py +7 -0
- nb_lab_runtime-0.1.0/tests/test_cache.py +17 -0
- nb_lab_runtime-0.1.0/tests/test_cell_model.py +70 -0
- nb_lab_runtime-0.1.0/tests/test_cli_helpers.py +148 -0
- nb_lab_runtime-0.1.0/tests/test_executor.py +29 -0
- nb_lab_runtime-0.1.0/tests/test_incremental_run.py +17 -0
- nb_lab_runtime-0.1.0/tests/test_notebook_edit.py +25 -0
- nb_lab_runtime-0.1.0/tests/test_notebook_state.py +23 -0
- nb_lab_runtime-0.1.0/tests/test_plot_meta.py +53 -0
- nb_lab_runtime-0.1.0/tests/test_watcher.py +20 -0
- nb_lab_runtime-0.1.0/uv.lock +741 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
name: OpenAPI Check
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
openapi:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: astral-sh/setup-uv@v4
|
|
15
|
+
- name: Install dependencies
|
|
16
|
+
run: uv sync
|
|
17
|
+
- name: Generate OpenAPI schema
|
|
18
|
+
run: bash scripts/gen_openapi.sh
|
|
19
|
+
- name: Check for diffs
|
|
20
|
+
run: git diff --exit-code docs/openapi.json
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nb-lab-runtime
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AI-native notebooks from plain Python files.
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Requires-Dist: fastapi>=0.135.1
|
|
8
|
+
Requires-Dist: matplotlib>=3.10.8
|
|
9
|
+
Requires-Dist: uvicorn>=0.42.0
|
|
10
|
+
Requires-Dist: watchdog>=6.0.0
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# nb-lab
|
|
14
|
+
|
|
15
|
+
AI-native notebooks from plain Python files.
|
|
16
|
+
|
|
17
|
+
`nb-lab` turns `.py:percent` scripts (with `# %%` cells) into notebook-style sessions with a simple HTTP API so humans and AI agents can read, edit, and run cells, and understand plots without `.ipynb`.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
Package name on PyPI is `nb-lab-runtime`; the CLI remains `nb-lab`.
|
|
21
|
+
|
|
22
|
+
Use uv:
|
|
23
|
+
```bash
|
|
24
|
+
uv add nb-lab-runtime
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
For local development:
|
|
28
|
+
```bash
|
|
29
|
+
uv sync
|
|
30
|
+
```
|
|
31
|
+
This installs the `nb-lab` CLI entry point.
|
|
32
|
+
If you prefer, you can also use `uv run nb-lab ...` without installing globally.
|
|
33
|
+
|
|
34
|
+
## Recommended (after release): uvx
|
|
35
|
+
Once `nb-lab-runtime` is published, you can run it without cloning:
|
|
36
|
+
```bash
|
|
37
|
+
uvx --from nb-lab-runtime nb-lab serve /path/to/your-ds-repo/notebook.py
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Quick start
|
|
41
|
+
Create a `.py` file with `# %%` cells:
|
|
42
|
+
```python
|
|
43
|
+
# %% [markdown]
|
|
44
|
+
# Simple example
|
|
45
|
+
|
|
46
|
+
# %%
|
|
47
|
+
import matplotlib.pyplot as plt
|
|
48
|
+
import numpy as np
|
|
49
|
+
|
|
50
|
+
x = np.linspace(0, 10, 200)
|
|
51
|
+
y = np.sin(x)
|
|
52
|
+
|
|
53
|
+
# %%
|
|
54
|
+
plt.plot(x, y)
|
|
55
|
+
plt.title("Sine wave")
|
|
56
|
+
plt.show()
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Start the server:
|
|
60
|
+
```bash
|
|
61
|
+
nb-lab serve path/to/script.py
|
|
62
|
+
```
|
|
63
|
+
If binding fails, use an ephemeral port:
|
|
64
|
+
```bash
|
|
65
|
+
nb-lab serve path/to/script.py --port 0
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Troubleshooting (restricted environments)
|
|
69
|
+
If you see cache or permission errors, set writable cache directories:
|
|
70
|
+
```bash
|
|
71
|
+
export NB_LAB_CACHE_DIR=/tmp/nb-lab-cache
|
|
72
|
+
export MPLCONFIGDIR=/tmp/mpl-cache
|
|
73
|
+
export UV_CACHE_DIR=/tmp/uv-cache
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Using nb-lab with another repo
|
|
77
|
+
Run nb-lab from this repo but point at a different project:
|
|
78
|
+
```bash
|
|
79
|
+
cd /path/to/nb-lab
|
|
80
|
+
uv sync
|
|
81
|
+
nb-lab serve /path/to/your-ds-repo/notebook.py
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
If `nb-lab` is not on your PATH, re-run `uv sync`.
|
|
85
|
+
|
|
86
|
+
### Recommended for multi-repo use (uv tool install)
|
|
87
|
+
Install nb-lab once and use it across projects:
|
|
88
|
+
```bash
|
|
89
|
+
uv tool install -e /path/to/nb-lab
|
|
90
|
+
nb-lab serve /path/to/your-ds-repo/notebook.py
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
This keeps your data science repo’s dependencies separate from nb-lab’s runtime.
|
|
94
|
+
|
|
95
|
+
Helper script:
|
|
96
|
+
```bash
|
|
97
|
+
bash scripts/install_tool.sh
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
List cells:
|
|
101
|
+
```bash
|
|
102
|
+
nb-lab list
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Run a cell:
|
|
106
|
+
```bash
|
|
107
|
+
nb-lab run <CELL_ID> --mode incremental
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Show outputs:
|
|
111
|
+
```bash
|
|
112
|
+
nb-lab show <CELL_ID>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Suppress image payloads:
|
|
116
|
+
```bash
|
|
117
|
+
nb-lab run <CELL_ID> --no-images
|
|
118
|
+
nb-lab show <CELL_ID> --compact
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Check server status:
|
|
122
|
+
```bash
|
|
123
|
+
nb-lab status
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Tip: `--base-version` is optional. If omitted, nb-lab fetches the latest version automatically.
|
|
127
|
+
You can also use `--cell-index N` to refer to the Nth cell in `nb-lab list`.
|
|
128
|
+
|
|
129
|
+
## Cache commands
|
|
130
|
+
```bash
|
|
131
|
+
nb-lab cache info
|
|
132
|
+
nb-lab cache list
|
|
133
|
+
nb-lab cache clear --yes
|
|
134
|
+
nb-lab cache clear --all
|
|
135
|
+
nb-lab cache clear --path path/to/notebook.py
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Smoke demo
|
|
139
|
+
Run an end-to-end demo that starts the server, runs a cell, and fetches outputs:
|
|
140
|
+
```bash
|
|
141
|
+
uv sync
|
|
142
|
+
bash scripts/smoke_demo.sh
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Live workflow demo (agent-in-the-loop)
|
|
146
|
+
Here is a concrete end-to-end workflow that shows why nb-lab exists. The agent never touches `.ipynb` and still iterates like a notebook.
|
|
147
|
+
|
|
148
|
+
1. Start the server on a real `.py:percent` notebook:
|
|
149
|
+
```bash
|
|
150
|
+
nb-lab serve examples/demo.py
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
2. List cells and grab the current version:
|
|
154
|
+
```bash
|
|
155
|
+
nb-lab list
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
3. Pick a target cell and run it (incremental, no full replay):
|
|
159
|
+
```bash
|
|
160
|
+
nb-lab run --cell-index 1 --mode incremental
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
4. Fetch outputs and inspect both text and plot metadata:
|
|
164
|
+
```bash
|
|
165
|
+
nb-lab show <CELL_ID>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
5. Let the agent edit a cell in the middle and rerun just what’s needed:
|
|
169
|
+
```bash
|
|
170
|
+
cat <<'PY' | nb-lab edit --cell-index 1 --from-stdin
|
|
171
|
+
<NEW_CODE>
|
|
172
|
+
PY
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
6. Re-run the changed cell; nb-lab replays only the dirty prefix:
|
|
176
|
+
```bash
|
|
177
|
+
nb-lab run --cell-index 1
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
This is the critical workflow: the agent can read/edit/run cells and reason about plots via `plot_meta` without JSON notebooks or manual state management.
|
|
181
|
+
|
|
182
|
+
### Mini transcript (agent loop)
|
|
183
|
+
```
|
|
184
|
+
User: "Check if the sine plot has a mean offset, and annotate it."
|
|
185
|
+
|
|
186
|
+
Agent -> GET /cells
|
|
187
|
+
Agent: Finds plot cell id = c3, base_version = 7
|
|
188
|
+
|
|
189
|
+
Agent -> POST /cells/c3/run
|
|
190
|
+
Agent -> GET /outputs/c3
|
|
191
|
+
Agent: Sees plot_meta.summary_text = "Line plot with 1 series."
|
|
192
|
+
|
|
193
|
+
Agent -> POST /cells/c2/edit
|
|
194
|
+
Agent: Inserts mean calculation and axhline overlay
|
|
195
|
+
|
|
196
|
+
Agent -> POST /cells/c3/run
|
|
197
|
+
Agent: Receives updated plot_meta + image_png
|
|
198
|
+
|
|
199
|
+
User: "Looks good—ship it."
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Execution semantics
|
|
203
|
+
- The `.py` file is the source of truth. Any edit (API or manual) writes to disk and triggers a reparse.
|
|
204
|
+
- Runs are incremental: when you run a cell, nb-lab replays only the minimal dirty prefix (cells whose source changed) up to the target cell.
|
|
205
|
+
- If nothing is dirty, nb-lab returns the cached output for that cell.
|
|
206
|
+
|
|
207
|
+
This favors iteration speed over strict correctness and mirrors how users actually iterate in notebooks.
|
|
208
|
+
|
|
209
|
+
## Cell ID storage
|
|
210
|
+
Stable cell IDs are stored in a user cache directory (default `~/.cache/nb-lab`). Set `NB_LAB_CACHE_DIR` to override.
|
|
211
|
+
|
|
212
|
+
## HTTP API (MVP)
|
|
213
|
+
Base URL: `http://localhost:8787`
|
|
214
|
+
|
|
215
|
+
- `GET /cells`
|
|
216
|
+
Returns `{ "version": int, "cells": [CellSummary...] }`
|
|
217
|
+
|
|
218
|
+
- `GET /status`
|
|
219
|
+
Returns `{ "version": int, "running_cell_id": string | null, "running_since": float | null }`
|
|
220
|
+
|
|
221
|
+
- `GET /cells/{cell_id}`
|
|
222
|
+
Returns full `Cell`.
|
|
223
|
+
|
|
224
|
+
- `POST /cells/{cell_id}/run`
|
|
225
|
+
Body: `{ "mode": "incremental" | "run_above" | "single", "timeout_ms": 60000, "base_version": int }`
|
|
226
|
+
Returns `ExecutionResult`.
|
|
227
|
+
|
|
228
|
+
- `POST /run_up_to/{cell_id}`
|
|
229
|
+
Same body as above. Runs prefix up to `cell_id` based on mode.
|
|
230
|
+
|
|
231
|
+
- `GET /outputs/{cell_id}`
|
|
232
|
+
Returns `{ "cell_id": str, "result": ExecutionResult }`.
|
|
233
|
+
|
|
234
|
+
- `POST /cells/{cell_id}/edit`
|
|
235
|
+
Body: `{ "new_source": "...", "base_version": int }`
|
|
236
|
+
Returns updated `Cell`.
|
|
237
|
+
|
|
238
|
+
- `POST /cells/insert_after`
|
|
239
|
+
Body: `{ "after_id": "cell-id-or-null", "source": "...", "kind": "code" | "markdown", "base_version": int }`
|
|
240
|
+
Returns new `Cell`.
|
|
241
|
+
|
|
242
|
+
- `DELETE /cells/{cell_id}`
|
|
243
|
+
Body: `{ "base_version": int }`
|
|
244
|
+
Returns updated cell list.
|
|
245
|
+
|
|
246
|
+
Concurrency: If `base_version` does not match the current notebook version, the server returns `409`.
|
|
247
|
+
|
|
248
|
+
## Output payloads
|
|
249
|
+
`ExecutionResult.outputs` is a list of `OutputItem`:
|
|
250
|
+
- `text`: captured stdout
|
|
251
|
+
- `stderr`: captured stderr
|
|
252
|
+
- `repr`: last expression repr
|
|
253
|
+
- `plot_meta`: JSON summary of plot structure and data
|
|
254
|
+
- `image_png`: PNG image encoded as hex
|
|
255
|
+
|
|
256
|
+
Note: `plot_meta.series[].sample` is downsampled (default max 200 points), while `n_points` reports the full series length.
|
|
257
|
+
|
|
258
|
+
## Agent tooling
|
|
259
|
+
See `docs/agent-tools.md` for function-calling tool definitions and suggested usage patterns.
|
|
260
|
+
|
|
261
|
+
For a copy-pasteable, agent-ready prompt that drives a full analysis run, see `docs/agent-prompting.md`.
|
|
262
|
+
For a human-readable demo flow, see `docs/demo-transcript.md`.
|
|
263
|
+
|
|
264
|
+
## OpenAPI + MCP
|
|
265
|
+
- OpenAPI schema: `docs/openapi.json`
|
|
266
|
+
- MCP manifest: `docs/mcp.json`
|
|
267
|
+
- Tool examples: `docs/tool-examples.md`
|
|
268
|
+
- MCP hosting note: `docs/mcp-hosting.md`
|
|
269
|
+
|
|
270
|
+
To regenerate the OpenAPI schema:
|
|
271
|
+
```bash
|
|
272
|
+
bash scripts/gen_openapi.sh
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Status
|
|
276
|
+
nb-lab is early and experimental. Contributions, issues, and ideas are welcome.
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# nb-lab
|
|
2
|
+
|
|
3
|
+
AI-native notebooks from plain Python files.
|
|
4
|
+
|
|
5
|
+
`nb-lab` turns `.py:percent` scripts (with `# %%` cells) into notebook-style sessions with a simple HTTP API so humans and AI agents can read, edit, and run cells, and understand plots without `.ipynb`.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
Package name on PyPI is `nb-lab-runtime`; the CLI remains `nb-lab`.
|
|
9
|
+
|
|
10
|
+
Use uv:
|
|
11
|
+
```bash
|
|
12
|
+
uv add nb-lab-runtime
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
For local development:
|
|
16
|
+
```bash
|
|
17
|
+
uv sync
|
|
18
|
+
```
|
|
19
|
+
This installs the `nb-lab` CLI entry point.
|
|
20
|
+
If you prefer, you can also use `uv run nb-lab ...` without installing globally.
|
|
21
|
+
|
|
22
|
+
## Recommended (after release): uvx
|
|
23
|
+
Once `nb-lab-runtime` is published, you can run it without cloning:
|
|
24
|
+
```bash
|
|
25
|
+
uvx --from nb-lab-runtime nb-lab serve /path/to/your-ds-repo/notebook.py
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick start
|
|
29
|
+
Create a `.py` file with `# %%` cells:
|
|
30
|
+
```python
|
|
31
|
+
# %% [markdown]
|
|
32
|
+
# Simple example
|
|
33
|
+
|
|
34
|
+
# %%
|
|
35
|
+
import matplotlib.pyplot as plt
|
|
36
|
+
import numpy as np
|
|
37
|
+
|
|
38
|
+
x = np.linspace(0, 10, 200)
|
|
39
|
+
y = np.sin(x)
|
|
40
|
+
|
|
41
|
+
# %%
|
|
42
|
+
plt.plot(x, y)
|
|
43
|
+
plt.title("Sine wave")
|
|
44
|
+
plt.show()
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Start the server:
|
|
48
|
+
```bash
|
|
49
|
+
nb-lab serve path/to/script.py
|
|
50
|
+
```
|
|
51
|
+
If binding fails, use an ephemeral port:
|
|
52
|
+
```bash
|
|
53
|
+
nb-lab serve path/to/script.py --port 0
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Troubleshooting (restricted environments)
|
|
57
|
+
If you see cache or permission errors, set writable cache directories:
|
|
58
|
+
```bash
|
|
59
|
+
export NB_LAB_CACHE_DIR=/tmp/nb-lab-cache
|
|
60
|
+
export MPLCONFIGDIR=/tmp/mpl-cache
|
|
61
|
+
export UV_CACHE_DIR=/tmp/uv-cache
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Using nb-lab with another repo
|
|
65
|
+
Run nb-lab from this repo but point at a different project:
|
|
66
|
+
```bash
|
|
67
|
+
cd /path/to/nb-lab
|
|
68
|
+
uv sync
|
|
69
|
+
nb-lab serve /path/to/your-ds-repo/notebook.py
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
If `nb-lab` is not on your PATH, re-run `uv sync`.
|
|
73
|
+
|
|
74
|
+
### Recommended for multi-repo use (uv tool install)
|
|
75
|
+
Install nb-lab once and use it across projects:
|
|
76
|
+
```bash
|
|
77
|
+
uv tool install -e /path/to/nb-lab
|
|
78
|
+
nb-lab serve /path/to/your-ds-repo/notebook.py
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
This keeps your data science repo’s dependencies separate from nb-lab’s runtime.
|
|
82
|
+
|
|
83
|
+
Helper script:
|
|
84
|
+
```bash
|
|
85
|
+
bash scripts/install_tool.sh
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
List cells:
|
|
89
|
+
```bash
|
|
90
|
+
nb-lab list
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Run a cell:
|
|
94
|
+
```bash
|
|
95
|
+
nb-lab run <CELL_ID> --mode incremental
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Show outputs:
|
|
99
|
+
```bash
|
|
100
|
+
nb-lab show <CELL_ID>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Suppress image payloads:
|
|
104
|
+
```bash
|
|
105
|
+
nb-lab run <CELL_ID> --no-images
|
|
106
|
+
nb-lab show <CELL_ID> --compact
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Check server status:
|
|
110
|
+
```bash
|
|
111
|
+
nb-lab status
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Tip: `--base-version` is optional. If omitted, nb-lab fetches the latest version automatically.
|
|
115
|
+
You can also use `--cell-index N` to refer to the Nth cell in `nb-lab list`.
|
|
116
|
+
|
|
117
|
+
## Cache commands
|
|
118
|
+
```bash
|
|
119
|
+
nb-lab cache info
|
|
120
|
+
nb-lab cache list
|
|
121
|
+
nb-lab cache clear --yes
|
|
122
|
+
nb-lab cache clear --all
|
|
123
|
+
nb-lab cache clear --path path/to/notebook.py
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Smoke demo
|
|
127
|
+
Run an end-to-end demo that starts the server, runs a cell, and fetches outputs:
|
|
128
|
+
```bash
|
|
129
|
+
uv sync
|
|
130
|
+
bash scripts/smoke_demo.sh
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Live workflow demo (agent-in-the-loop)
|
|
134
|
+
Here is a concrete end-to-end workflow that shows why nb-lab exists. The agent never touches `.ipynb` and still iterates like a notebook.
|
|
135
|
+
|
|
136
|
+
1. Start the server on a real `.py:percent` notebook:
|
|
137
|
+
```bash
|
|
138
|
+
nb-lab serve examples/demo.py
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
2. List cells and grab the current version:
|
|
142
|
+
```bash
|
|
143
|
+
nb-lab list
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
3. Pick a target cell and run it (incremental, no full replay):
|
|
147
|
+
```bash
|
|
148
|
+
nb-lab run --cell-index 1 --mode incremental
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
4. Fetch outputs and inspect both text and plot metadata:
|
|
152
|
+
```bash
|
|
153
|
+
nb-lab show <CELL_ID>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
5. Let the agent edit a cell in the middle and rerun just what’s needed:
|
|
157
|
+
```bash
|
|
158
|
+
cat <<'PY' | nb-lab edit --cell-index 1 --from-stdin
|
|
159
|
+
<NEW_CODE>
|
|
160
|
+
PY
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
6. Re-run the changed cell; nb-lab replays only the dirty prefix:
|
|
164
|
+
```bash
|
|
165
|
+
nb-lab run --cell-index 1
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
This is the critical workflow: the agent can read/edit/run cells and reason about plots via `plot_meta` without JSON notebooks or manual state management.
|
|
169
|
+
|
|
170
|
+
### Mini transcript (agent loop)
|
|
171
|
+
```
|
|
172
|
+
User: "Check if the sine plot has a mean offset, and annotate it."
|
|
173
|
+
|
|
174
|
+
Agent -> GET /cells
|
|
175
|
+
Agent: Finds plot cell id = c3, base_version = 7
|
|
176
|
+
|
|
177
|
+
Agent -> POST /cells/c3/run
|
|
178
|
+
Agent -> GET /outputs/c3
|
|
179
|
+
Agent: Sees plot_meta.summary_text = "Line plot with 1 series."
|
|
180
|
+
|
|
181
|
+
Agent -> POST /cells/c2/edit
|
|
182
|
+
Agent: Inserts mean calculation and axhline overlay
|
|
183
|
+
|
|
184
|
+
Agent -> POST /cells/c3/run
|
|
185
|
+
Agent: Receives updated plot_meta + image_png
|
|
186
|
+
|
|
187
|
+
User: "Looks good—ship it."
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Execution semantics
|
|
191
|
+
- The `.py` file is the source of truth. Any edit (API or manual) writes to disk and triggers a reparse.
|
|
192
|
+
- Runs are incremental: when you run a cell, nb-lab replays only the minimal dirty prefix (cells whose source changed) up to the target cell.
|
|
193
|
+
- If nothing is dirty, nb-lab returns the cached output for that cell.
|
|
194
|
+
|
|
195
|
+
This favors iteration speed over strict correctness and mirrors how users actually iterate in notebooks.
|
|
196
|
+
|
|
197
|
+
## Cell ID storage
|
|
198
|
+
Stable cell IDs are stored in a user cache directory (default `~/.cache/nb-lab`). Set `NB_LAB_CACHE_DIR` to override.
|
|
199
|
+
|
|
200
|
+
## HTTP API (MVP)
|
|
201
|
+
Base URL: `http://localhost:8787`
|
|
202
|
+
|
|
203
|
+
- `GET /cells`
|
|
204
|
+
Returns `{ "version": int, "cells": [CellSummary...] }`
|
|
205
|
+
|
|
206
|
+
- `GET /status`
|
|
207
|
+
Returns `{ "version": int, "running_cell_id": string | null, "running_since": float | null }`
|
|
208
|
+
|
|
209
|
+
- `GET /cells/{cell_id}`
|
|
210
|
+
Returns full `Cell`.
|
|
211
|
+
|
|
212
|
+
- `POST /cells/{cell_id}/run`
|
|
213
|
+
Body: `{ "mode": "incremental" | "run_above" | "single", "timeout_ms": 60000, "base_version": int }`
|
|
214
|
+
Returns `ExecutionResult`.
|
|
215
|
+
|
|
216
|
+
- `POST /run_up_to/{cell_id}`
|
|
217
|
+
Same body as above. Runs prefix up to `cell_id` based on mode.
|
|
218
|
+
|
|
219
|
+
- `GET /outputs/{cell_id}`
|
|
220
|
+
Returns `{ "cell_id": str, "result": ExecutionResult }`.
|
|
221
|
+
|
|
222
|
+
- `POST /cells/{cell_id}/edit`
|
|
223
|
+
Body: `{ "new_source": "...", "base_version": int }`
|
|
224
|
+
Returns updated `Cell`.
|
|
225
|
+
|
|
226
|
+
- `POST /cells/insert_after`
|
|
227
|
+
Body: `{ "after_id": "cell-id-or-null", "source": "...", "kind": "code" | "markdown", "base_version": int }`
|
|
228
|
+
Returns new `Cell`.
|
|
229
|
+
|
|
230
|
+
- `DELETE /cells/{cell_id}`
|
|
231
|
+
Body: `{ "base_version": int }`
|
|
232
|
+
Returns updated cell list.
|
|
233
|
+
|
|
234
|
+
Concurrency: If `base_version` does not match the current notebook version, the server returns `409`.
|
|
235
|
+
|
|
236
|
+
## Output payloads
|
|
237
|
+
`ExecutionResult.outputs` is a list of `OutputItem`:
|
|
238
|
+
- `text`: captured stdout
|
|
239
|
+
- `stderr`: captured stderr
|
|
240
|
+
- `repr`: last expression repr
|
|
241
|
+
- `plot_meta`: JSON summary of plot structure and data
|
|
242
|
+
- `image_png`: PNG image encoded as hex
|
|
243
|
+
|
|
244
|
+
Note: `plot_meta.series[].sample` is downsampled (default max 200 points), while `n_points` reports the full series length.
|
|
245
|
+
|
|
246
|
+
## Agent tooling
|
|
247
|
+
See `docs/agent-tools.md` for function-calling tool definitions and suggested usage patterns.
|
|
248
|
+
|
|
249
|
+
For a copy-pasteable, agent-ready prompt that drives a full analysis run, see `docs/agent-prompting.md`.
|
|
250
|
+
For a human-readable demo flow, see `docs/demo-transcript.md`.
|
|
251
|
+
|
|
252
|
+
## OpenAPI + MCP
|
|
253
|
+
- OpenAPI schema: `docs/openapi.json`
|
|
254
|
+
- MCP manifest: `docs/mcp.json`
|
|
255
|
+
- Tool examples: `docs/tool-examples.md`
|
|
256
|
+
- MCP hosting note: `docs/mcp-hosting.md`
|
|
257
|
+
|
|
258
|
+
To regenerate the OpenAPI schema:
|
|
259
|
+
```bash
|
|
260
|
+
bash scripts/gen_openapi.sh
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Status
|
|
264
|
+
nb-lab is early and experimental. Contributions, issues, and ideas are welcome.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Prompting an AI Agent to Use nb-lab
|
|
2
|
+
|
|
3
|
+
This doc is the canonical, copy-pasteable instruction set for getting an AI agent to run a real analysis using nb-lab. It is designed to be used as a system or developer prompt in an agent thread.
|
|
4
|
+
|
|
5
|
+
## 1) Minimal agent prompt (copy/paste)
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
You are an AI research assistant. You have access to a local nb-lab server that exposes a notebook-style API over HTTP.
|
|
9
|
+
|
|
10
|
+
Rules:
|
|
11
|
+
- The .py file is the source of truth. If you edit code, use the nb-lab edit/insert/delete endpoints.
|
|
12
|
+
- Always start by listing cells and reading the target cell before editing.
|
|
13
|
+
- Prefer incremental runs: run only the cell you need, and rely on nb-lab to replay dirty prefixes.
|
|
14
|
+
- After each run, fetch outputs and summarize text + plot_meta in plain English.
|
|
15
|
+
|
|
16
|
+
Workflow:
|
|
17
|
+
1. GET /cells to list cells and get base_version.
|
|
18
|
+
2. For a target cell: GET /cells/{cell_id} to see its source.
|
|
19
|
+
3. If needed, edit or insert a cell via POST /cells/{cell_id}/edit or /cells/insert_after.
|
|
20
|
+
4. Run with POST /cells/{cell_id}/run using base_version and mode (incremental by default). Set include_images=false when you only need text/plot_meta.
|
|
21
|
+
5. Fetch outputs with GET /outputs/{cell_id} and summarize.
|
|
22
|
+
|
|
23
|
+
You must show your work: include the exact API calls you make and the short summaries of outputs.
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 2) Expanded prompt with tool wrappers
|
|
27
|
+
|
|
28
|
+
If your agent supports tool definitions, you can provide these high-level tools (see `docs/agent-tools.md` for details):
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
Tools:
|
|
32
|
+
- list_notebook_cells(notebook_path)
|
|
33
|
+
- get_notebook_context(notebook_path, focus_cell_ids)
|
|
34
|
+
- edit_notebook_cell(notebook_path, cell_id, new_source)
|
|
35
|
+
- insert_notebook_cell(notebook_path, after_cell_id, source, kind)
|
|
36
|
+
- run_notebook_cell(notebook_path, cell_id, mode="stateful_from_top")
|
|
37
|
+
- get_plot_meta(notebook_path, cell_id)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 3) Example task prompt
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Task: Open the notebook, find the cell that makes the plot, compute the mean of the series, overlay it on the plot as a dashed red line, and re-run the plot cell. Summarize the change and the updated plot_meta summary.
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## 4) Agent output expectations
|
|
47
|
+
|
|
48
|
+
A strong agent run should:
|
|
49
|
+
- Show the initial cell list with IDs and a chosen target.
|
|
50
|
+
- Edit/insert the mean computation safely.
|
|
51
|
+
- Re-run the plot cell and retrieve plot_meta.
|
|
52
|
+
- Explain what changed and what the plot_meta summary says.
|
|
53
|
+
|
|
54
|
+
## 5) Notes for evaluators
|
|
55
|
+
- We value iteration speed over strict correctness in MVP; the agent can re-run a cell without replaying the full notebook if it’s already clean.
|
|
56
|
+
- If a base_version conflict occurs, the agent should re-list cells and retry.
|