chore: auto-commit (43 archivos)

- .mcp.json
- bash/functions/infra/write_mcp_jupyter_config.md
- bash/functions/infra/write_mcp_jupyter_config.sh
- cpp/CMakeLists.txt
- cpp/apps/chart_demo
- cpp/apps/shaders_lab
- cpp/functions/gfx/gl_framebuffer.cpp
- cpp/functions/gfx/gl_framebuffer.h
- cpp/functions/gfx/gl_framebuffer.md
- cpp/functions/gfx/mesh_gpu.md
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 17:28:47 +02:00
parent a2efdcf003
commit fd5787c55f
44 changed files with 3924 additions and 64 deletions
@@ -0,0 +1,94 @@
---
name: jupyter_run_cells
kind: function
lang: py
domain: notebook
version: "1.0.0"
purity: impure
signature: "jupyter_run_cells(notebook_path: str, cell_indices: list[int], server_url: str, token: str, stop_on_error: bool, timeout_per_cell_s: int) -> dict"
description: "Ejecuta un lote de celdas existentes (por indice) en una sola conexion WebSocket. Un GET inicial + un PUT final. Latencia fija ~3s en vez de ~3s * N de jupyter_execute_cell individual."
tags: [jupyter, notebook, kernel, websocket, execution, cells, batch, notebook]
uses_functions: [jupyter_exec_py_notebook]
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [jupyter_kernel_client, notebook.jupyter_exec]
params:
- name: notebook_path
desc: "Ruta relativa al notebook (relativa a la raiz del servidor Jupyter)"
- name: cell_indices
desc: "Lista de indices de celdas a ejecutar (0-based, en orden). Solo celdas de tipo code."
- name: server_url
desc: "URL del servidor Jupyter (default http://localhost:8888)"
- name: token
desc: "Token de autenticacion (default vacio = sin auth)"
- name: stop_on_error
desc: "Si True, para al primer output de tipo error. El PUT se hace con lo ejecutado hasta ese punto."
- name: timeout_per_cell_s
desc: "Timeout en segundos por cada ejecucion individual de celda (default 600)"
output: "Dict con notebook, executed (lista de resultados por celda), stopped_at, kernel_id y total_duration_s"
tested: true
tests:
- "test_run_cells_single_cell_returns_output"
- "test_run_cells_stops_on_error_by_default"
- "test_run_cells_no_stop_on_error_continues"
- "test_run_cells_invalid_index_raises"
- "test_run_cells_non_code_cell_raises"
- "e2e: test_e2e_run_cells_batch"
- "e2e: test_e2e_run_cells_stop_on_error"
test_file_path: "python/functions/notebook/tests/test_jupyter_run_cells.py"
file_path: "python/functions/notebook/jupyter_run_cells.py"
---
## Ejemplo
```python
from notebook.jupyter_run_cells import jupyter_run_cells
result = jupyter_run_cells(
notebook_path="notebooks/analisis.ipynb",
cell_indices=[0, 1, 2, 5],
server_url="http://localhost:8888",
token="",
stop_on_error=True,
)
# {
# "notebook": "notebooks/analisis.ipynb",
# "executed": [
# {"cell_index": 0, "execution_count": 1, "outputs": ["import ok"], "error": None, "duration_s": 1.2},
# {"cell_index": 1, "execution_count": 2, "outputs": ["42"], "error": None, "duration_s": 0.1},
# ...
# ],
# "stopped_at": None,
# "kernel_id": "abc-123",
# "total_duration_s": 4.8,
# }
```
CLI:
```bash
# Indices como argumentos posicionales
python python/functions/notebook/jupyter_run_cells.py notebooks/analisis.ipynb 0 1 2 5
# Indices via stdin JSON (util desde scripts)
echo '[0, 1, 2, 5]' | python python/functions/notebook/jupyter_run_cells.py notebooks/analisis.ipynb
# No parar en error + timeout custom
python python/functions/notebook/jupyter_run_cells.py notebooks/analisis.ipynb 0 1 2 \
--no-stop-on-error --timeout 120
```
## Cuando usarla
Cuando necesites re-ejecutar varias celdas de un notebook existente y el overhead de abrir/cerrar N conexiones WS sea inaceptable (>3 celdas, celdas pesadas, o en pipelines automatizados). Sustituye a llamar `jupyter_execute_cell` N veces en bucle desde el agente.
## Gotchas
- Las celdas deben existir previamente en el notebook. Para anadir y ejecutar celdas nuevas, usar `jupyter_append_execute` de `jupyter_exec`.
- Solo ejecuta celdas de tipo `code`. Pasar el indice de una celda markdown lanza `ValueError` antes de abrir el WS.
- El `PUT` final se hace siempre, incluso si `stop_on_error` detiene el lote. El notebook queda con los outputs de las celdas ejecutadas hasta el punto de parada.
- `KernelClient` ignora `timeout_per_cell_s` si la implementacion subyacente no lo soporta (depende de la version de `jupyter-kernel-client`). En ese caso el timeout global del proceso es el unico limite.
- Si el servidor Jupyter no esta corriendo, `_ensure_session` lanza `URLError` inmediatamente (no hay retry incorporado).
- El WS se abre con el `kernel_id` de la sesion activa del notebook. Si el kernel muere entre el `_ensure_session` y la ejecucion, `KernelClient` lanzara una excepcion.