[RFC][WIP] Early, early draft of displaying Galaxy notebooks in Loom & auto-syncing.#351
Draft
jmchilton wants to merge 7 commits into
Draft
[RFC][WIP] Early, early draft of displaying Galaxy notebooks in Loom & auto-syncing.#351jmchilton wants to merge 7 commits into
jmchilton wants to merge 7 commits into
Conversation
Shell-neutral brain side of the Orbit iframe-embed feature.
- galaxy-embed.ts: absolute embed-URL builder (API embed_url is path-
relative) + NotebookEmbed projection + token refresh-timing math.
- shared contract: NotebookEmbed + EmbedToken widget keys, payloads,
codecs. EmbedToken never reaches the renderer (privileged-process only).
- galaxy-pages-api: mintEmbedToken (POST /pages/{id}/embed_token).
- embed-token-manager: mint-on-bind, refresh-before-expiry, retry,
cancel/abort/stale-drop; transport-agnostic sink.
- embed-token-bridge: drive the manager off notebook+connection state,
emit token on the EmbedToken key (bound && connected only).
- ui-bridge: emit NotebookEmbed widget, deduped, before the hidden gate.
Tests green; brain stays shell-neutral.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…hase 3) Consumes the brain's NotebookEmbed/EmbedToken widgets. - main intercepts the EmbedToken widget in agent.handleLine, holds it in EmbedTokenStore, never forwards to the renderer. - embed-partition: pure trust boundary (sameGalaxyOrigin, nav block, frame-header strip) + session wiring; inject X-Galaxy-Embed-Token for the Galaxy origin only, strip frame dirs, block off-origin nav. - main.ts wires the persist:galaxy-embed partition; webviewTag enabled; CSP frame-src adds https:. - renderer: Markdown/Galaxy toggle, <webview> in the locked partition, fallback states, persisted mode, reload-on-rev. notebook-view-model is pure + tested. Vehicle is <webview> not <iframe> (iframe can't take a custom partition); Galaxy postMessage bridge no-ops in a webview, so native events stand in. Unit + typecheck green; not yet live-verified in a running app. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Found running the server-side embed E2E (Galaxy Page in Orbit's locked-down
<webview>, authed by the scoped per-page embed token). All three live-verified.
Bug 1 (critical): the webview's /published/page load seated an anonymous
galaxysession cookie in the persist:galaxy-embed partition; Galaxy resolved that
cookie session ahead of the injected embed token, so /api/pages/{id} 403'd
despite a valid token. Strip Cookie (request) and Set-Cookie (response) on
Galaxy-origin requests so the partition is stateless and Galaxy auths by the
token alone. New pure stripHeader helper + wiring. Live: in-webview /api/pages
now 200, document.cookie empty.
Bug 2: Galaxy returns expires_at as naive UTC with no Z/offset; Date.parse read
it as local time -> expiry in the past -> refresh delay floored -> re-mint ~1/s.
New parseExpiryMs appends Z to a tz-less ISO datetime so it parses UTC.
Bug 3: NotebookEmbed/token emission was gated on onNotebookChange + a ctx only
captured in before_agent_start; a --continue resume of an already-bound notebook
never re-emitted -> Galaxy toggle "unavailable". Bridges now also capture ctx on
session_start and replay the current notebook (readCurrentNotebook), order-
independent vs init's existing notifyNotebookChange. Mint gate moved to new
isGalaxyEffectivelyConnected (env creds OR in-session flag); context.ts and the
/execute init-gate precondition refactored onto it (the raw flag is false on an
env-creds resume until a Galaxy tool runs).
995 tests green, root+app typecheck + lint clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
getEmbedUrl appends &theme=<id> (default DEFAULT_EMBED_THEME "orbit"; null omits) so Galaxy renders the embedded page dark to match Orbit's shell. No-op on a Galaxy without the orbit built-in theme. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
loom-session housekeeping blocks leaked into the pushed page, where Galaxy
markdown read them as an unknown cell directive ("This cell type `loom-session`
is not available"). Add stripSessionSummaryBlocks and apply it to the Galaxy
projection only (galaxyBody); the local re-persist keeps the blocks, so durable
session history survives.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The local Markdown view rendered raw notebook.md, so the loom-session (session history) and loom-galaxy-page (binding) blocks showed as visible metadata. The Galaxy push already strips them; do the same for display. Add stripHousekeepingBlocks and apply it to the Notebook widget projection in emitNotebook -- raw content still drives the embed/binding derivation. Blocks stay on disk; only the rendered view hides them. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Debounced push of a bound+connected notebook to its Galaxy page so the embedded Galaxy view tracks local edits without a manual /sync push. Off by default (LOOM_AUTO_PUSH=1 / experiments.autoPush): push is local-wins and clobbers server edits, so opting in accepts that. Dedup on the housekeeping-stripped body breaks the push's own self-write loop. Mirrors the embed-token bridge/manager split; debounce + in-flight coalesce + prime-on-bind. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
The Loom/Orbit side of rendering a Galaxy notebook as the Galaxy server renders it inside Orbit's notebook pane — full fidelity (live dataset displays, visualizations, charts) for a private, history-attached page — plus an opt-in auto-sync so the embedded view tracks local edits.
Paired with the Galaxy server changes (embed-token auth + embeddable surface): galaxyproject/galaxy#22988.
Pieces (high level)
getEmbedUrl+NotebookEmbedshell contract emitted from the notebook watcher;mintEmbedTokenclient + a token refresh manager. The embed token is delivered out of band to Orbit main (a swallowedEmbedTokenwidget key the privileged process intercepts and never forwards to the renderer) — never the API key.<webview partition="persist:galaxy-embed">that injects the scoped embed token on Galaxy-origin requests, strips frame headers, blocks off-origin navigation, and is stateless (no ambientgalaxysessioncookie).LOOM_AUTO_PUSH=1/experiments.autoPush, off by default), a genuine edit to a bound + connected notebook is debounce-pushed to its Galaxy page so the embed tracks local edits without a manual/sync push. Dedups on the housekeeping-stripped body so the push's own self-write doesn't loop. Local-wins, so it clobbers server-side edits — hence opt-in; safer gates (revision/previous-hash precondition, last-writer-was-Orbit) are deliberately deferred.Status / asks
🤖 Generated with Claude Code