3.9 KiB
@deepseek-ai/dsh-client-ui-workspace
English | 中文
Shared Workspace picker plugin. WorkspaceBrowser is registered into the sidebar's sidebar.workspaces slot and WorkspacePicker into the page-local Session Intent hero's conversation.hero.workspace slot, so both surfaces use the same menu and creation flow.
The picker lists real Host Workspace entities through the global useWorkspaces hook. Selecting a Workspace invokes the slot owner's onPick callback to retarget the frontend Session object. Each registration declares a directory-flow child hole (single kind: conversation.hero.workspace.directoryFlow / sidebar.workspaces.directoryFlow) that the composed picker package's client half fills with its picking interaction — the -native backend's renderless OS-chooser driver today, an in-app browsing dialog under a -browse composition. The flat Open local folder... action renders only while the surface's hole is occupied (occupancy read per menu render; an empty hole means the composition has no picking affordance — the seam's documented no-flow default). This package owns the trigger and the adoption: the occupant reports one picked path per open through the hole's owner conversation (open/busy/onPicked/onCancel/onError), and the owner adopts it through the object layer, selecting the committed Workspace only after its list projection has refreshed; cancellation is silent, and errors land in the retryable folder dialog whose Choose again reopens the flow. Create a new workspace retains the name dialog and disables names already present in that list, while the Host remains authoritative for concurrent or non-UI callers. The runtime Session and Workspace services own materialization. The Workspace row's Delete action opens a confirmation that states the retention boundary, blocks duplicate submission, and keeps failures open; success removes the group while its Sessions remain under Ungrouped. The Session row's Rename action opens the same browser-owned dialog pattern prefilled with the row's display title: no client-side conflict rule exists (the host normalizes and may reject with title-invalid, rendered in the dialog alert), and confirming an unchanged title is deliberately allowed — it pins the current automatic title against regeneration.
Session rows distinguish the runtime's live waitingApproval approval-request fact from an otherwise blue in-flight Session: an amber warning dot takes precedence over the running indicator, and the hover card reports Waiting for approval until the request is resolved. Every lit state carries a visually hidden label (Waiting for approval or Running) for assistive technology; an idle row leaves the reserved status slot empty. Question waits are tracked separately and do not set waitingApproval.
Both target slots are declared by other plugins, so apply registers through declaration-aware deferral and re-registers after a declaring slot is restored.
Model Experience
None, as the picker is browser chrome; nothing here reaches a model request.
KV Cache effect
None; this package neither assembles nor sends a provider request.
Known Limitations and Deferred Work
- No Session deletion or fork control — the Session menu's Fork and Delete rows remain visual-only (Rename is wired); Workspace registration deletion does not delete Sessions.
- Approval waiting is not aggregated into hidden ancestors — a waiting child Session under a folded parent, or any waiting row inside a collapsed group, becomes visible only after that container is expanded.
- Native folder selection depends on the local Host carrier — under the
-nativecomposition, fixture-only or remote browser deployments cannot open a local operating-system dialog; platform failures are shown in a retryable modal. Remote-capable picking is the-browsecomposition's in-app flow.