You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: named text streams, canonical nebo:// refs, and UI/perf work
Implements the NEW.md batch. The through-line is that text becomes a
first-class named stream like metrics and media, and every resource gets
an unambiguous, clickable identifier.
Text redesign (breaking):
- nb.log(message, name=) -> nb.log_text(name, message, step=), with name
a required first positional, matching the metric helpers. There is no
level/severity anywhere; the old info/warn/error UI was dead code for
every SDK-produced run. nb.log() survives only as a deprecated shim
that forwards and warns once per process.
- Wire/file type is now "text" (entry code 9). The legacy "log" spelling
(code 0) stays readable forever: ingest normalizes it, so existing
.nebo files decode unchanged.
- Renamed through every surface: /runs/{id}/text, `nebo text ls`,
nebo_get_text, cache table `texts` (schema v6), ?text=NAME embeds.
- Text renders like images: one card per stream name, each entry a
header row (name, step, timestamp, actions) over the payload.
Canonical nebo:// references:
- nebo://run/<id>[/<loggable>[/<name...>]][@<step>] and
nebo://group/<path>, parsed by twin implementations in
nebo/core/refs.py and ui/src/lib/refs.ts. The loggable is always one
segment, so stream names containing '/' need no escaping.
- Deep links navigate deterministically: force the flat view, open the
tab/filter owning the card, scroll to it, flash it for 3s. Shared
modality order keeps desktop and mobile in lockstep.
- New GET /resolve?ref= returns parsed components plus existence.
- @nb.fn now guarantees unique loggable ids: two different functions
claiming the same qualname no longer merge into one node.
Performance (a 112 MB / 858k-point run opened slowly):
- GET /runs/{id}/metrics decimates per series (min/max buckets, ~2k
points, ?points=0 for full) and reports total_points/downsampled.
The UI paints the decimated response, then fetches full fidelity so
every datapoint still reaches the user.
- Watcher deepening no longer broadcasts a file's whole history over
WebSocket, ingest yields between slices, and the store pools metric
appends per series per batch.
- Measured: /metrics 69.7 MB -> 5.2 MB, warm read 6.9s -> 0.77s.
UI:
- DAG auto-layout fixes on desktop and the mobile canvas (links to a run
could render unlaid-out), horizontal desktop default, solid edges, no
pane context menu.
- Right panel hosts Markdown / Config / Settings as icon tabs, open by
default and resizable; config renders as a structured tree.
- Top bar reduced to <group>/<name> <id> <date>.
- Groups only expand in the tree; their docs are tree leaves opening a
dedicated viewer. No client-side run rename; tooltips drop counts that
read 0 for shallow runs.
- Tracker: step navigation works while collapsed, modality chips moved
under the stream search, collapsed branches merge their datapoints.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XrJfA61nnwkwJ86UiSvYYN
0 commit comments