mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-11 17:43:43 -10:00
feat/btw-qodercli-alignment
1
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
24b53add50 |
feat(web-shell): add a Workspaces overview panel (#10589)
* feat(web-shell): add a Workspaces overview panel Layer B2 of #10399: a full-page table of every registered workspace — name with primary/untrusted badges, path, active session counts, MCP health (unknown while the runtime is not initialized, never zero), branch with a dirty counter, and last activity — with New task and Remove actions per row. Entries: a Manage workspaces row at the end of the Projects section (hidden for a locked sidebar) and an opt-in workspacesOverview footer item outside the default set. Daemon-owned live runtimes are not rows. The sidebar's inline removal state machine moves verbatim into a shared useWorkspaceRemoval hook plus WorkspaceRemovalDialog so both surfaces run the same confirm/busy/force/mismatch/in-progress flow; the sidebar keeps its reconciliation as the hook's onRemoved callback. Cells reuse layer-A plumbing: catalog-store session counts deduplicated with the sidebar's queries, useWorkspaceOverview for MCP, and the git chip's fetch discipline for the branch column. Untrusted rows fetch nothing. * fix(web-shell): align the Workspaces panel's cells and gates with review round 1 Three behavioural fixes: a capabilities-refresh rejection after a daemon-confirmed removal is no longer misreported as a removal failure (the panel's onRemoved guards the refresh the way the sidebar's reconcile does); the MCP fraction excludes disabled servers from its denominator, matching the sidebar chip's connected/enabled convention; and last activity falls back to createdAt like the daemon's getSummaryActivityTime, so a live session that has not published a terminal still counts. Smaller alignments: session counts treat a nextCursor page as a lower bound (the sidebar's union); the opt-in footer entry honours the locked gate and carries a testid; the panel gets its aria-label and heading focus when opened; the dedup comment states what actually dedupes. Coverage the review asked for: the in-progress retry loop (converges, busy mid-retry, dismissed, exhausted), submitting reset across sequential removals, the active-session force block through the panel, the per-row query and facet shape, the New-task double-submit guard and its App wiring, the footer entry, an MCP-cell-scoped unknown assertion, and a cross-workspace facet witness in the e2e spec. * fix(web-shell): stabilize the removal controller and pin review round 2 The one behavioural change: useWorkspaceRemoval reads its options through a ref and memoizes the controller it returns, and App passes createNewSession directly, so the panel's column definitions stop rebuilding on every render — a rebuilt column set is a new component type per cell, which unmounted every row cell and re-fired their git fetches on any App re-render while the panel was open. The rest is coverage round 2 asked for: both remaining retry-loop exits (mid-retry mismatch reconciles, a non-transient error surfaces itself rather than the synthetic exhaustion message), the dismissed flag reset and stale busy-state reset in request(), the reconcile-before-clear ordering (a hung reconcile keeps the dialog open), the allow direction of the panel's force gate, hook-level blockForce at both call sites past the disabled attribute (invoking the button's props directly, as a stale reference would), the global cross-row New-task guard, the wait:true git contract, the truncated-without-cursor lower bound, the unwired footer opt-in rendering nothing, heading focus on panel open, and an honest scope note on the e2e cross-wiring witness. * test(web-shell): pin fresh option reads and submitting across the reconcile Two review-round-3 pins on the removal hook. Options are read through a ref so blockForce observes the connection state at confirm time — a busy dialog whose candidate gains the active session between renders must refuse the forced retry; the new test re-renders the probe with a flipped blockForce and goes red if the ref assignment is dropped. And submitting stays true for the whole reconcile window, keeping every dialog gate locked during the caller's capability round-trip; the hung-reconcile test now asserts it mid-flight and goes red if confirm stops awaiting handleRemoved. * test(web-shell): pin the busy report across a blocked forced confirm force derives from activity, so a block branch that cleared it would silently downgrade the next click to a non-forced attempt and restart the consent flow; the blocked-confirm test now asserts the report and candidate both survive the refusal. |