feat(workspaces): IPC API and extension-side data layer for the panel - #1099
Draft
EhabY wants to merge 1 commit into
Draft
feat(workspaces): IPC API and extension-side data layer for the panel#1099EhabY wants to merge 1 commit into
EhabY wants to merge 1 commit into
Conversation
EhabY
force-pushed
the
ehab/devex-622-workspaces-ipc-api-extension-side-provider-with-data-layer
branch
11 times, most recently
from
August 26, 2026 20:27
8b0ad5e to
a17482e
Compare
Adds the typed IPC contract for the experimental Workspaces panel and the extension-side provider that owns its data, porting the tree views' behaviors to push through IPC. `packages/shared/src/workspaces` defines the contract: `stateUpdated` out; `ready`, `openWorkspace`, `viewInDashboard`, `refresh`, `setFilter` and `watchAgents` back. State is pushed as one update carrying only the fields that changed, and the payloads carry decisions rather than facts to derive, so the webview holds no data and applies no policy: it asks for the state with `ready` and renders what arrives. `WorkspaceStore` lists the active filter while visible, backs off on failures, watches metadata for the agents the panel is showing, and reports what changed. A cancellation token per fetch drops superseded results, the list is pushed before sockets open, and a structural diff keeps quiet polls off the wire. Filters that a deployment rejects stop being offered. Split by concern, in their own layers: - `src/workspace/agentMetadataTracker.ts`: the watched set and its sockets, which linger briefly after release so toggling a row reuses them - `src/workspace/filters.ts`: each filter's query, presentation, role requirement and poll policy, shared with the tree views instead of duplicated `isOwner(user)` moved to `src/api/api-helper.ts` for both `deploymentManager` and the panel, since the `coder.isOwner` context is written after the session change fires. Existing tree views are untouched. The webview's placeholder App prints the pushed state; the UI lands with the tree components.
EhabY
force-pushed
the
ehab/devex-622-workspaces-ipc-api-extension-side-provider-with-data-layer
branch
from
August 26, 2026 20:36
a17482e to
5ae7bef
Compare
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.
Closes DEVEX-622.
Extension side of the new Workspaces view, behind
coder.experimental.workspacesPanel. No UI components: the panel prints the pushed state so the data flow can be verified, and the tree component library lands separately.The contract
packages/shared/src/workspaces/holds the typed API both sides import:types.tsfor every type,api.tsfor the messages.stateUpdatedready,openWorkspace,viewInDashboard,refresh,setFilter,watchAgentsOne notification carries only the fields that changed, so a change to two of them lands as one message and one render. Payloads carry decisions, not facts to derive:
capabilitieslists the filters the user may select, so the webview applies no owner or deployment-support rules, and a filter that cannot load is never offeredloading, true only for fetches someone waits on (a first list, a filter switch, a deliberate refresh) and never for a poll, so nothing flickersloadingtoo, so an expanded row can tell "waiting on the socket" from "this agent reports no metadata"readyis the one addition to the ticket's list: without it the first push races the webview's script load. It replays the whole state, so a webview that reloaded needs no data of its own.The data layer
WorkspaceStorelists the active filter while visible and reports what changed. Oneupdate()records the change, diffs the state structurally and pushes only the fields the webview lacks, so quiet polls cost nothing downstream. Ported from the tree views: polling stopped while hidden, exponential backoff, per-agent metadata over SSE, owner gating, and the HTTP 400 signal that a deployment predates a filter's query.What it does differently, all in the data layer:
CancellationTokenSourceper fetch drops results of superseded fetches, replacing the tree'sfetching/refetchPending/session-identity bookkeepingpollkeep polling; Shared and All list on demand, keeping expensive queries off the timerFailures each have one owner and one visible outcome: a failed fetch clears the list, reports the message and retries with backoff; a rejected query becomes an unavailable filter, not an error; a metadata socket reports against its agent and never reads as a failure to list; user actions report in a dialog. Anything unexpected on the listing path is caught in one place, so
loadcannot reject into a timer callback.Split by concern:
src/workspace/agentMetadataTracker.tsowns the watched set and its sockets, andsrc/workspace/filters.tsowns each filter's query, presentation, role requirement and poll policy, shared with the tree views instead of duplicated (the only change toworkspacesProvider.ts).isOwner(user)moved tosrc/api/api-helper.tsfor bothdeploymentManagerand the panel, since thecoder.isOwnercontext is written after the session change fires.Where the lines go
webviews/workspaces/store.tswebviews/workspaces/panelProvider.tsworkspace/agentMetadataTracker.tsshared/workspaces/{types,api}.tsworkspace/filters.tsuseWorkspaces, placeholder,extension.tswebviews/workspaces/*.test.ts+ harnessworkspace/{agentMetadataTracker,filters}.test.tswebview/workspaces,api/api-helper, mocksisOwner, factoriesFull suite: 2538 passed. Typecheck, lint, format and build clean. Existing tree views untouched and functional.
Notes for review
Task[]for the same reason.retainContextWhenHidden, and there is no visibility or theme re-send: the DOM survives hiding,useVscodeThemein@repo/uialready re-renders on theme changes, and a discarded webview re-hydrates throughready.openWorkspacereports telemetry assidebar_workspace/sidebar_agent, so panel opens are not distinguishable from tree opens. A distinctWorkspaceOpenSourcefelt outside this ticket.webviews/workspaces/store.ts,workspace/filters.ts), which diverges fromtasks,netcheckandspeedtest. Happy to rename those in a separate pass.test/unit/webviews/workspaces/harness.tsbuilds a mockWebviewView, as the Tasks panel test does inline. Worth promoting totest/mocks/testHelpers.tsnext tocreateMockWebviewPanel, but that means touching the Tasks test, so I left it.