Run node code on the venv Fluksio was installed into

The workflow this serves: make a venv, install what you work with, then `pip
install fluksio` into the same one. Building a second environment beside it
was exactly wrong — the packages the nodes need are already here, and the
Modules screen was asking for them a second time.

`NODE_VENV=auto` (the default) adopts that venv. It declines in the three
cases where adopting would be wrong: `managed` says otherwise, a managed venv
already exists and may hold packages somebody installed on purpose, or the
engine is not running from a venv at all. The images set `managed`, since the
venv in them holds the app and nothing of anybody else's.

An adopted venv is never written to. `uv pip sync` makes a venv hold exactly
the manifest, so pointed at somebody's own environment it uninstalls their
work and the engine with it — `sync()` refuses outright and `reconcile()`
returns before it can be called at startup, which is where that would have
happened first. The Modules screen lists what is installed and drops its
editor; `pip` is how that environment changes.

`fluksio serve` now names the interpreter node code runs on, which is the
thing a data scientist most needs to know at that moment. `fluksio-worker`
already defaulted `--python` to its own interpreter, so a GPU box works the
same way — that was only ever undocumented.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ue1tkFWB1bcGy3aWhCKpU
This commit is contained in:
2026-08-24 10:35:13 +02:00
co-authored by Claude Fable 5
parent 68fa5527b1
commit fea57064f9
15 changed files with 357 additions and 69 deletions
+13
View File
@@ -191,11 +191,24 @@ def cmd_serve(args: argparse.Namespace) -> int:
import uvicorn
from fluksio.flow import modules
from fluksio.main import app
config = cloud_config.load()
_say(f"Fluksio {fluksio.__version__} — data in {data_dir}")
_say(f" API http://{args.host}:{args.port}{'/api/v1'}")
# Which environment node code imports from is the thing a data scientist
# most needs to know at this moment, and the answer differs depending on
# how Fluksio was installed. Saying it costs one line.
if modules.adopted() is not None:
_say(f" Nodes {modules.venv_python()}")
_say(" your environment, adopted. Add packages with pip.")
else:
# Not `venv_python()`: the managed venv is built when the engine comes
# up, which is after this prints, and until then that would answer with
# whatever interpreter happens to be running this.
_say(f" Nodes {modules.venv_dir() / 'bin' / 'python'}")
_say(" a venv of its own; the Modules screen installs into it.")
if config is not None:
_say(f" Portal {config.portal_url}, installation {config.installation_id}")
_say(" The dashboard is served by the portal; nothing is served here.")