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
The OpenCode embed surfaces in the dashboard don't expose their content well. Three related issues:
1. Chat popup → workbench thread is a dead end
When OpenCode is shown in the worker-detail panel (small inline view of an active OpenCode session inside the AgentWorkers page), there's no way to escape into the full workbench experience for the same thread. Good for quick glance, bad for actual work.
Proposed: add an "Open in Workbench" link next to the existing OpenCodeDirectLink in the worker-detail panel header. Routes to a new /workbench/$thread sub-route filtered to that single thread.
2. Workbench WorkerColumns aren't resizable
Each WorkerColumn is a fixed w-[560px]. With multiple workers running, the screen partitions arbitrarily and the user can't widen the column they're actively reading.
Proposed: add drag handles between columns using the existing Resizable primitive (@spacedrive/primitives/Resizable, wraps react-resizable-layout). Persist widths to localStorage by column position, not worker id, so the layout is stable across worker churn.
3. Workbench columns don't fill the available width
The container is flex-1 gap-[10px] overflow-x-auto (Workbench.tsx:179) and each column is flex-shrink-0 w-[560px]. With N×560 < viewport width there's wasted horizontal space at the right edge; with N×560 > viewport, the page scrolls horizontally instead of letting columns share remaining space.
Proposed: flex columns to fill 100% of the workbench pane, with a per-column min-width (~360px) so they only fall back to horizontal scroll when there are genuinely too many. User-set widths from #2 take precedence.
Why this matters
The workbench is the primary workspace for multi-worker sessions. Friction here pushes users back to the worker-detail popup (read-only-ish, less capable), undercutting the workbench's whole purpose. Each issue compounds the others — without (3) you don't have the room to want (2), and without (2) the popup-vs-workbench tradeoff in (1) tilts even more toward "stay in the popup."
Implementation plan
Files involved
Concern
File
Lines (approx)
Worker-detail panel rendering OpenCode (the "chat popup")
Routing for filtered workbench: sub-route /workbench/$thread, using TanStack Router's native History integration (back/forward/deep-link/refresh all work out of the box).
Resize implementation: JS-based react-resizable-layout via the existing Resizable primitive — gives a thin draggable divider between columns, more polished than native CSS resize.
Width persistence: keyed by column position (spacebot-workbench-column-widths = Record<positionIndex, number>), so layout is stable across worker churn.
Issue 1 — Open-in-Workbench link
Routing change in interface/src/router.tsx:
// Add a child route under /workbench{path: "/workbench/$thread",component: functionWorkbenchThreadPage(){const{ thread }=useParams({from: "/workbench/$thread"});return<WorkbenchfilterThread={thread}/>;},}
Workbench accepts an optional filterThread prop that narrows the visible columns to that session id. When set, the sidebar shows a "Showing 1 of N workers — clear filter" affordance that links back to /workbench.
The link itself in AgentWorkers.tsx ~471:
{hasOpenCodeEmbed&&detail.opencode_session_id&&(<Linkto="/workbench/$thread"params={{thread: detail.opencode_session_id}}className={cx(badgeVariants({variant: "outline",size: "sm"}),"w-fit")}>
Open in Workbench →
</Link>)}
UX touch (non-blocking): when workbench loads filtered to one thread, scroll that column into view + flash the border briefly so the user knows they landed on the right one.
Issue 2 — Resizable columns
Convert WorkerColumn's wrapper to participate in a horizontal Resizable chain. The primitive's useResizable hook returns a position value driven by drag; we feed the resulting widths into a Map<positionIndex, number> and persist on debounce.
useColumnWidths: reads/writes localStorage["spacebot-workbench-column-widths"] as JSON. Debounce writes (~250ms) to avoid spamming localStorage during drag. No migration needed — fresh feature.
Summary
The OpenCode embed surfaces in the dashboard don't expose their content well. Three related issues:
1. Chat popup → workbench thread is a dead end
When OpenCode is shown in the worker-detail panel (small inline view of an active OpenCode session inside the AgentWorkers page), there's no way to escape into the full workbench experience for the same thread. Good for quick glance, bad for actual work.
Proposed: add an "Open in Workbench" link next to the existing
OpenCodeDirectLinkin the worker-detail panel header. Routes to a new/workbench/$threadsub-route filtered to that single thread.2. Workbench
WorkerColumns aren't resizableEach
WorkerColumnis a fixedw-[560px]. With multiple workers running, the screen partitions arbitrarily and the user can't widen the column they're actively reading.Proposed: add drag handles between columns using the existing
Resizableprimitive (@spacedrive/primitives/Resizable, wrapsreact-resizable-layout). Persist widths to localStorage by column position, not worker id, so the layout is stable across worker churn.3. Workbench columns don't fill the available width
The container is
flex-1 gap-[10px] overflow-x-auto(Workbench.tsx:179) and each column isflex-shrink-0 w-[560px]. With N×560 < viewport width there's wasted horizontal space at the right edge; with N×560 > viewport, the page scrolls horizontally instead of letting columns share remaining space.Proposed: flex columns to fill 100% of the workbench pane, with a per-column min-width (~360px) so they only fall back to horizontal scroll when there are genuinely too many. User-set widths from #2 take precedence.
Why this matters
The workbench is the primary workspace for multi-worker sessions. Friction here pushes users back to the worker-detail popup (read-only-ish, less capable), undercutting the workbench's whole purpose. Each issue compounds the others — without (3) you don't have the room to want (2), and without (2) the popup-vs-workbench tradeoff in (1) tilts even more toward "stay in the popup."
Implementation plan
Files involved
interface/src/routes/AgentWorkers.tsxOpenCodeDirectLink), 633 (impl)interface/src/routes/Workbench.tsxinterface/src/components/workbench/WorkerColumn.tsxw-[560px] flex-shrink-0)interface/src/router.tsxpath: "/workbench")@spacedrive/primitives/src/Resizable.tsxreact-resizable-layoutDecisions
/workbench/$thread, using TanStack Router's native History integration (back/forward/deep-link/refresh all work out of the box).react-resizable-layoutvia the existingResizableprimitive — gives a thin draggable divider between columns, more polished than native CSSresize.spacebot-workbench-column-widths=Record<positionIndex, number>), so layout is stable across worker churn.Issue 1 — Open-in-Workbench link
Routing change in
interface/src/router.tsx:Workbench accepts an optional
filterThreadprop that narrows the visible columns to that session id. When set, the sidebar shows a "Showing 1 of N workers — clear filter" affordance that links back to/workbench.The link itself in
AgentWorkers.tsx~471:UX touch (non-blocking): when workbench loads filtered to one thread, scroll that column into view + flash the border briefly so the user knows they landed on the right one.
Issue 2 — Resizable columns
Convert
WorkerColumn's wrapper to participate in a horizontalResizablechain. The primitive'suseResizablehook returns apositionvalue driven by drag; we feed the resulting widths into aMap<positionIndex, number>and persist on debounce.Sketch (
Workbench.tsx):useColumnWidths: reads/writeslocalStorage["spacebot-workbench-column-widths"]as JSON. Debounce writes (~250ms) to avoid spamming localStorage during drag. No migration needed — fresh feature.Issue 3 — Fill width by default
Workbench.tsx:179:(Keep
overflow-x-auto— only kicks in when columns' min-widths sum to more than viewport.)WorkerColumn.tsx:18:When #2's resizer assigns an explicit width to a column, it takes precedence (
flex-[0_0_<px>]).Order to ship
flex-1to explicit widths.router.tsx+Workbench.tsx+AgentWorkers.tsx. Adds the new sub-route and thefilterThreadprop.Each can ship as its own PR or combined.
Out of scope