galaxyproject / galaxyproject/loom
Orbit: remote control of local instances via Galaxy as relay (status, prompt, stop from any device)
- Dominant language
- TypeScript
- Stars
- 14
- Forks
- 12
- Avg merge
- 6d 5h
- Merged PRs (30d)
- 17
Description
## Idea
Allow remote monitoring and control of a locally-running Orbit instance via Galaxy as a relay. Use cases:
- Kicked off a long pipeline on the workstation, want to check status from a phone / laptop at a coffee shop.
- Collaborator wants to peek at the analysis state without screen-share.
- Trigger a follow-up action ("when alignment finishes, run multiqc") from another device.
- Pause/stop a runaway local job remotely.
The constraint that makes this interesting: Orbit is a local Electron app on a personal machine, not reachable from the public internet. Punching holes (ngrok-style tunnels, opening ports) is unfriendly and security-fraught. Galaxy already has the user's identity, persistent storage, and is reachable from anywhere — use it as the relay.
## Why Galaxy as relay
- **Auth and identity already solved** — only the user's own Galaxy account can post commands, no new auth surface.
- **Persistent** — survives Orbit restart, laptop suspend, etc.
- **Cross-device** — any browser logged into Galaxy can interact.
- **No inbound network on the local machine** — Orbit only ever makes outbound HTTPS to Galaxy.
- **Dovetails with #69** (stashing project context in Galaxy history) — same mechanism, broader purpose.
## Proposed shape
Per Orbit session, allocate a dedicated "control" history (or a hidden dataset collection within the project history). Two roles:
1. **Commands inbox** — datasets containing queued instructions written by remote clients.
2. **Events outbox** — datasets containing status snapshots, recent activity, log tails, written by Orbit.
### Local Orbit side
Background poller (10–30s interval) in main process:
- `GET /api/histories/{control_id}/contents?since={last_seen}` — fetch new command datasets.
- For each command: parse, dispatch (route to brain as a synthetic user message, or handle in-shell for control verbs like `status`, `stop`, `pause`).
- Write a result dataset back acknowledging the command.
Heartbeat: every N seconds, write/update an "alive" dataset with timestamp, current model, current tool, last activity, top processes. Remote clients show "last seen Xs ago."
### Remote client side
Initial cut: a small static page hosted by Galaxy (or even a Galaxy tool wrapper) that:
- Lists the user's active Orbit sessions (histories tagged `orbit-control`).
- Shows the latest "alive" snapshot.
- Has an input box that creates a new command dataset.
- Polls events outbox for replies.
No new server code on Galaxy — uses the existing API.
## Command vocabulary (v1)
- `status` — return alive snapshot now.
- `tail N` — return last N lines of activity.
- `prompt "..."` — inject a prompt as if the user typed it.
- `stop` — abort current turn.
- `pause` / `resume` — gate further auto-execution.
## Files (sketch)
- `extensions/loom/galaxy/control-channel.ts` — new module: poll commands, dispatch, write events. Reuses the existing Galaxy client.
- `extensions/loom/index.ts` — register the poller alongside the existing Galaxy bootstrap, gated on a setting `enableRemoteControl`.
- `app/src/main/agent.ts` — accept synthetic prompts from the control channel the same way the IPC `prompt` handler does today.
- A tiny static client (Galaxy tool, or a `web/remote-control.html` served by the existing `web/server.ts`).
## Tradeoffs
- **Latency.** Polling at 10–30s means the remote view lags. Acceptable for "is it still working" / "kick off next step" — bad for live streaming. WebSocket relay through Galaxy would be cleaner but needs server-side work that doesn't exist yet. Start with polling; upgrade later if Galaxy grows real-time channels.
- **API quota.** A constant 10s poll is ~8.6k requests/day per session. Fine for one user, watch out if everyone enables it. Mitigate with adaptive backoff: poll fast (5s) right after a command is sent, slow (60s) when idle for N minutes.
- **Security model.** Anyone with the user's Galaxy API key can drive Orbit. That's already the trust boundary for everything else Galaxy-side, but worth being explicit: enabling remote control means "my Galaxy account ≈ root on Orbit's process."
- **Ordering / races.** Two remote clients submitting commands simultaneously: serialize via dataset creation order; reject conflicting verbs (two `stop`s become a no-op).
## Edge cases
- Orbit offline / laptop closed: commands accumulate in the inbox; processed when Orbit reconnects. Heartbeat going stale > N min → remote UI shows "offline."
- Galaxy down: control channel fails closed, Orbit keeps running locally as today.
- Stale commands (queued days ago): include a TTL on each command; skip if older than the threshold.
## Out of scope (for v1)
- Real-time event streaming (covered later, possibly with a server-side relay).
- File transfer between remote client and local Orbit (separate concern; Galaxy datasets already handle this for analysis files).
- Multi-user shared sessions (one Galaxy account = one session for now).
## Related
- #69 — stash project context in Galaxy history (same plumbing, complementary purpose).
- #70 — process monitor for detached PIDs (the heartbeat snapshot would naturally include these).
- #71 — liveness indicator (remote clients have the same "is this thing alive" question).
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.