Commit graph

7 commits

Author SHA1 Message Date
qqqys
090b213ad8
feat(web-shell): add native workspace folder picker (#7849)
* feat(web-shell): add native workspace folder picker

* fix(serve): harden native directory picker and add coverage (#7849)

Add a 5-minute timeout to each native picker subprocess and to the
webui action so a dismissed dialog cannot leave an orphaned GUI process,
and distinguish a headless Linux "cannot open display" failure from a
deliberate zenity cancellation. Cover pickNativeDirectory's platform
branches, the route's 501/500 error paths, and the dialog's picker
failure path with focused tests.

* fix(serve): log directory picker failures to daemon stderr (#7849)

* fix(serve): abort directory picker on client disconnect and stagger timeouts (#7849)

* test(webui): add unit tests for pickWorkspaceDirectory action (#7849)

* fix(serve): set UTF-8 console encoding for PowerShell picker and treat timeout kills as cancels (#7849)

* fix(serve): abort directory picker on response close, not request close (#7849)

---------

Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>
Co-authored-by: Qwen Code Bot <qwen-code-bot@users.noreply.github.com>
Co-authored-by: Qwen Code CI <qwen-code-ci@users.noreply.github.com>
2026-07-28 05:58:13 +00:00
Heyang Wang
6f5d6dfd65
feat(web-shell): add workspace selector button with add/switch dropdown in composer toolbar (#7390)
* feat(web-shell): add managed workspace selector

Let Web Shell create and select daemon-managed workspaces without
changing ownership of existing sessions.

- Add capability-gated existing and scratch workspace registration
- Validate scratch roots, trust provenance, capacity, and shutdown races
- Serialize workspace mutations, session switching, and refresh results
- Add SDK/WebUI wiring and focused cross-package regression coverage

# Conflicts:
#	packages/web-shell/client/App.tsx
#	packages/web-shell/client/components/sidebar/WebShellSidebar.tsx

# Conflicts:
#	packages/cli/src/serve/capabilities.ts
#	packages/cli/src/serve/routes/workspace-management.ts
#	packages/cli/src/serve/server.test.ts
#	packages/sdk-typescript/src/daemon/DaemonClient.ts
#	packages/web-shell/client/App.tsx
#	packages/web-shell/client/components/dialogs/AddWorkspaceDialog.tsx
#	packages/web-shell/client/components/sidebar/WebShellSidebar.tsx

* fix(web-shell): revalidate workspace before session creation

Prevent a stale workspace selection from bypassing the latest trusted
capability snapshot during lazy session creation.

- Validate the selected workspace before passing it to the daemon
- Fall back to the primary workspace when trust has been revoked
- Add a regression test for the pre-effect race window
- Remove stale branch state and clarify add-workspace ownership

* fix(web-shell): improve workspace removal feedback

Keep workspace removal controls legible and make blocked force removals
visibly inactive.

- Size the action menu independently from its narrow icon trigger
- Add a disabled affordance and suppress destructive hover styling
- Cover the removal menu width override with a regression test

* fix(web-shell): centralize existing workspace registration

Route sidebar and composer entry points through the App-owned dialog so
capability gating and workspace reconciliation remain consistent.

- Forward display names only when the daemon advertises support
- Hide and suppress persistence when registration is runtime-only
- Mark directory registrations with existing-workspace provenance
- Cover both entry points and capability combinations with tests

* fix(web-shell): address review feedback on workspace dialogs and capability docs (#7390)

- Document dynamic_workspace_registration and scratch_workspace_registration
  in the conditional serve-features table so the capabilities-docs-contract
  test passes.
- Gate DialogShell backdrop-click and Escape dismissal on the dismissible
  prop so non-dismissible dialogs ignore both gestures.
- Surface an inline error when an added folder registers but the capability
  refresh fails, mirroring the scratch recovery path.
- Add coverage for the active-session workspace switch and the add-folder
  refresh-failure paths.

* fix(web-shell): address review feedback on workspace dialogs and capability docs (#7390)

---------

Co-authored-by: heyang.why <heyang.why@alibaba-inc.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>
Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com>
2026-07-22 01:10:18 +00:00
samuelhsin
9e822d6004
feat: support workspace display names (#7179)
* feat(sdk): support workspace display names

* docs: add Web Shell screenshot

* feat(web-shell): add workspace display names

* fix(serve): harden workspace display name updates

* refactor(serve): simplify workspace display names

* fix(serve): validate trimmed workspace display names

* feat(serve): add workspace update API

* docs(serve): clarify workspace display name null handling

* docs(sdk): list addWorkspace in daemon client methods
2026-07-20 15:16:44 +00:00
Nothing Chan
620effef09
feat(web-shell): add directory autocomplete to the Add Workspace dialog (#7125)
Typing the full absolute path of a project by hand into the Add
Workspace dialog was slow and error-prone, and the only feedback was a
generic error after submitting. The existing GET /list route could not
back an autocomplete here because it resolves paths through a
registered workspace's filesystem boundary, and the path being picked
is not a workspace yet.

Add a deliberately narrow read-only daemon route,
GET /workspace-path-suggestions?prefix=<absolute>, that returns only
the names of subdirectories matching the prefix (case-insensitive on
the final segment, dot-directories only once the filter starts with a
dot, symlinked directories included, capped at 50 entries). It shares
the trust surface of POST /workspaces, which already lets an
authenticated client stat and register any absolute directory.

The dialog's path field becomes a combobox fed by that route through
DaemonClient.workspacePathSuggestions() and a new
suggestWorkspacePaths workspace action: suggestions render in a
listbox under the input (debounced 150ms, stale responses dropped),
ArrowUp/Down move the highlight, Enter/Tab or click accepts a
directory and descends into it, and Escape closes just the list —
intercepted on window capture so Radix does not close the whole
dialog.

Fixes #7102

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 22:25:22 +00:00
ytahdn
2071508eaf
fix(web-shell): restore packaged dialog styles on React 18 (#6827)
* fix(web-shell): restore packaged dialog styles on React 18

* docs(web-shell): document UI component conventions

* test(web-shell): verify workspace input focus

* test(web-shell): verify button ref binding

---------

Co-authored-by: 钉萁 <dingqi.jww@alibaba-inc.com>
2026-07-13 15:57:23 +00:00
ytahdn
79ae054bb8
feat(web-shell): modernize multi-workspace sidebar (#6804)
* feat(web-shell): modernize multi-workspace sidebar

* fix(web-shell): address sidebar review feedback

* fix(web-shell): address remaining review feedback

---------

Co-authored-by: ytahdn <ytahdn@gmail.com>
2026-07-13 11:45:20 +00:00
Shaojin Wen
732d85df39
fix(web-shell): correct Add Workspace dialog theming and multi-workspace session rows (#6705)
* fix(web-shell): theme and lay out the Add Workspace dialog correctly

The dialog's stylesheet referenced CSS variables that are defined nowhere
(--text-secondary, --input-bg, --border-color, --accent-color, --hover-bg), so
they fell back to hardcoded dark values — in light mode the input rendered
dark-on-light with a purple focus ring, inconsistent with every other dialog. It
also reused a two-column form-row grid meant for label/value pairs, which cramped
the path input into a narrow column.

Rebuild the dialog on the shared dialog primitives (themed .dialog-form input,
dialog-inline-button, dialog-primary-button) so it tracks the active theme in
both light and dark and gives the path a full-width input. Add a proactive
absolute-path hint, an accessible inline error (role="alert", aria-describedby,
aria-invalid) that clears as you type, and a localized "Adding…" state. Keep the
hint and error as siblings of the input rather than nested in the label, so their
text stays out of the input's accessible name.

* fix(web-shell): render full session rows for every workspace in the sidebar

Registering a second workspace switched the sidebar to the multi-workspace view,
which rendered each workspace's sessions with a bespoke minimal row: a smaller
font (12px vs 14px) and no per-session actions. The rich single-workspace row
(hover actions, current-session highlight, inline rename, running/unread state)
was hidden entirely, so even the primary workspace's list degraded.

Render sessions through the sidebar's shared renderSessionRow so every workspace
matches the single-workspace list. Gate the mutation actions to the primary
(daemon-bound) workspace: the daemon can't resolve another workspace's session
for pin/archive/export/delete (they 404 or silently no-op), so non-primary rows
are read-only — they keep click-to-load and the font/highlight but drop the
action buttons. Session mutations now also bump the per-workspace poll token so
those lists refresh promptly.

* refactor(web-shell): move Add Workspace footer padding into a CSS class

The footer sits inside .dialog-form (which already pads its sides) and reuses the
shared dialog-footer-actions primitive, doubling the horizontal padding; the
override lived as an inline style, hiding the deviation from the stylesheet. Move
it to a local .footer class applied alongside the shared class. A doubled
selector keeps it winning over the primitive regardless of stylesheet order.

* test(web-shell): cover workspace read-only gating and Add Workspace dialog

Add tests for the behaviors introduced by the sidebar and dialog fixes:
- non-primary workspace rows render the session but expose no action buttons
  (the daemon, bound to the primary workspace, can't service their mutations),
  while the primary workspace keeps its full actions;
- a session mutation re-polls the per-workspace list instead of waiting for the
  10s interval;
- the Add Workspace dialog's absolute-path validation, accessible error wiring
  (role="alert", aria-describedby/aria-invalid), error-clear-on-edit, trimmed
  submit, and onAdd-failure handling.

* refactor(web-shell): centralize the workspace reload-token bump in a helper

Per review: the setWorkspaceSessionsReloadToken bump was repeated verbatim across
the session-mutation handlers. Extract a stable bumpWorkspaceReload() helper and
route every site through it, including assignSessionGroup and assignSessionColor
— the two organization mutations that were missing the bump — so assigning a
group or color now also re-polls the per-workspace session lists instead of
waiting for the 10s interval.

* test(web-shell): cover Windows paths and non-Error rejections in Add Workspace dialog

Per review: add the two untested handleSubmit branches — a Windows-style absolute
path accepted by the drive-letter regex, and a non-Error onAdd rejection falling
back to the generic error message.

* fix(web-shell): gate inline rename on readOnly and refresh on group-create assign

Per review: the readOnly option hid the hover action buttons but not the inline
rename — onDoubleClick and the isEditing branch still fired on read-only rows, so
a session shown in multiple workspaces could render an editable rename input on
its non-primary (read-only) copy. Gate both on !readOnly. Also add the missing
bumpWorkspaceReload() to saveGroupEditor's create-with-target-session path so
that organization mutation refreshes the per-workspace lists like the others.

* test(web-shell): cover readOnly rename gating and dialog submitting state

Per review: assert the read-only (non-primary) row does not open the inline
rename form when the shared session is renamed from the primary row, and that the
Add Workspace dialog shows the localized "Adding…" label with disabled controls
while onAdd is pending.
2026-07-11 11:19:32 +00:00