Conversation
When both chat.unifiedAgentsBar.enabled and chat.agentsControl.enabled are true: - Command center shows left-aligned workspace title, no search icon - Agent status badge sections render inline inside the pill (not separate) - Section order is reversed: [active, unread, sparkle] (populating inward) - Hover only applies to input area, not badge sections When either setting is off, behavior is unchanged.
There was a problem hiding this comment.
Pull request overview
This PR introduces a “compact” titlebar experience when both chat.unifiedAgentsBar.enabled and chat.agentsControl.enabled are enabled, aligning the unified agents pill and agent status indicators into a tighter, inline layout.
Changes:
- Adds a compact rendering mode for the unified agents pill (left-aligned label, inline status sections, reversed indicator order, hover scoped to input area).
- Updates command center quick pick rendering to hide the search icon and left-align the workspace label when both settings are enabled.
- Adds CSS to support compact styling/layout in both the agent titlebar widget and the workbench titlebar.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| src/vs/workbench/contrib/chat/browser/agentSessions/experiments/media/agenttitlebarstatuswidget.css | Adds compact-mode styling and new input-area wrapper styling for hover behavior and inline badge sections. |
| src/vs/workbench/contrib/chat/browser/agentSessions/experiments/agentTitleBarStatusWidget.ts | Implements compact-mode DOM structure, hover scoping, inline badge rendering, and reversed section order. |
| src/vs/workbench/browser/parts/titlebar/media/titlebarpart.css | Adds titlebar CSS rules for compact-mode layout when the command center quick pick is compact. |
| src/vs/workbench/browser/parts/titlebar/commandCenterControl.ts | Adds config-driven compact-mode rendering for the command center quick pick (no icon, label-only). |
| // Input area wrapper - hover only activates here, not on badge sections | ||
| const inputArea = $('div.agent-status-input-area'); | ||
| pill.appendChild(inputArea); | ||
|
|
There was a problem hiding this comment.
agent-status-input-area is always created and becomes the hover/tooltip target, even when isCompactMode is false. That changes behavior compared to hovering the whole pill (e.g., hovering the left icon no longer triggers placeholder/send-icon/tooltip) in the unified agents bar when Agent Status is disabled, which contradicts the PR description that behavior is unchanged when either setting is off. Consider keeping the pre-existing hover/tooltip listeners on pill when !isCompactMode, or include the left icon inside the input area so the hover target remains effectively the whole pill.
| // When both unified agents bar and agent status are enabled, show status indicators | ||
| // before the sparkle button: [active, unread, sparkle] (populating inward) | ||
| // Otherwise, keep original order: [sparkle, unread, active] | ||
| const unifiedAgentsBarEnabled = this.configurationService.getValue<boolean>(ChatConfiguration.UnifiedAgentsBar) === true; | ||
| const agentStatusEnabled = this.configurationService.getValue<boolean>(ChatConfiguration.AgentStatusEnabled) === true; | ||
| const reverseOrder = unifiedAgentsBarEnabled && agentStatusEnabled; | ||
|
|
||
| if (!reverseOrder) { | ||
| // Original order: sparkle first | ||
| badge.appendChild(sparkleContainer); | ||
| } |
There was a problem hiding this comment.
With reverseOrder the sparkle section becomes the last section in compact mode, but the existing CSS for .agent-status-badge-section.sparkle .action-container applies a left border-radius that assumes sparkle is the first/leftmost segment. This can lead to incorrect rounding/visual seams when the sparkle section is appended last. Consider adding compact-mode specific CSS (or a class) to adjust the sparkle segment border radii based on its position when using the reversed order.
| /* Compact mode: inline status sections inside the pill */ | ||
| .agent-status-pill.compact-mode .agent-status-badge-section { | ||
| flex-shrink: 0; | ||
| } | ||
|
|
||
| /* First badge section in compact mode also gets a left separator */ | ||
| .agent-status-pill.compact-mode .agent-status-badge-section:first-of-type::before { | ||
| content: ''; | ||
| position: absolute; | ||
| left: 0; | ||
| top: 4px; | ||
| bottom: 4px; | ||
| width: 1px; | ||
| background-color: var(--vscode-commandCenter-border, rgba(128, 128, 128, 0.35)); | ||
| } | ||
|
|
||
| /* Input hover target - only this area triggers hover, not badge sections */ | ||
| .agent-status-pill .agent-status-input-area { | ||
| display: flex; | ||
| align-items: center; | ||
| flex: 1; | ||
| min-width: 0; | ||
| overflow: hidden; | ||
| cursor: pointer; | ||
| gap: 6px; | ||
| } | ||
|
|
||
| .agent-status-pill .agent-status-input-area:hover { | ||
| background-color: var(--vscode-commandCenter-activeBackground); | ||
| } |
There was a problem hiding this comment.
In compact mode, badge sections are appended directly into .agent-status-pill, but the pill still has gap: 6px (from the base .agent-status-pill rule). That will insert spacing between each badge segment and makes the existing segment separators (::before) look misaligned. Also, the new .agent-status-input-area:hover rule doesn’t prevent the existing .agent-status-pill:hover styling from applying when hovering the badge sections, so hover won’t be limited to the input area as intended. Consider setting gap: 0 for .agent-status-pill.compact-mode (and adding explicit spacing where needed), and scoping the pill hover styles to :not(.compact-mode) or toggling a class on the pill when the input area is hovered.
| // When both unified agents bar and agent status are enabled, | ||
| // hide search icon and left-align the label | ||
| const isCompactMode = that._configurationService.getValue<boolean>('chat.unifiedAgentsBar.enabled') === true | ||
| && that._configurationService.getValue<boolean>('chat.agentsControl.enabled') === true; | ||
| container.classList.toggle('compact-mode', isCompactMode); | ||
|
|
There was a problem hiding this comment.
isCompactMode is computed only during render() and there’s no listener to update the DOM if either setting changes at runtime. As a result, toggling chat.unifiedAgentsBar.enabled / chat.agentsControl.enabled may leave the command center in the wrong visual mode until a full re-render happens for unrelated reasons. Consider subscribing to configurationService.onDidChangeConfiguration for these keys and re-rendering or updating the element/class accordingly.
| // Status badge - only when Agent Status is enabled | ||
| // In compact mode, render inline within the pill instead of as a separate badge | ||
| if (this.configurationService.getValue<boolean>(ChatConfiguration.AgentStatusEnabled) === true) { | ||
| this._renderStatusBadge(disposables, activeSessions, unreadSessions, attentionNeededSessions); | ||
| this._renderStatusBadge(disposables, activeSessions, unreadSessions, attentionNeededSessions, isCompactMode ? pill : undefined); | ||
| } |
There was a problem hiding this comment.
In compact mode the status sections are rendered inline into the pill (via inlineContainer), but the pill itself is also a focusable role="button" (see earlier in _renderChatInputMode). That results in nested interactive controls (button containing other buttons/links), which is problematic for accessibility/screen readers. Consider making the input area the only role="button" region in compact mode and treating the pill as a non-interactive container (e.g. role="group"), so the inline badge sections remain independent focus targets.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.
Comments suppressed due to low confidence (1)
src/vs/workbench/contrib/chat/browser/chat.contribution.ts:241
- Changing the default from
trueto'compact'will affect all users who never explicitly set this value (defaults apply globally, not only to “new installs”). If the intent is to keep existing users on the prior badge-only behavior, consider defaulting to'badge'and/or adding an explicit migration.
default: 'compact',
tags: ['experimental']
| // Needs-input section - shows sessions requiring user attention (approval/confirmation/input) | ||
| if (viewSessionsEnabled && hasAttentionNeeded) { | ||
| needsInputSection = $('span.agent-status-badge-section.active.needs-input'); | ||
| needsInputSection.setAttribute('role', 'button'); | ||
| needsInputSection.tabIndex = 0; |
There was a problem hiding this comment.
needsInputSection is part of the same 'inProgress' filter (see _openSessionsWithFilter, which includes NeedsInput), but it never gets filtered styling when isFilteredToInProgress is active. This can leave the UI without any visible “filtered” indicator when only needs-input sessions exist. Consider applying filtered to needsInputSection when isFilteredToInProgress is true.
| // When both unified agents bar and agent status are enabled, show status indicators | ||
| // before the sparkle button: [active, unread, sparkle] (populating inward) | ||
| // Otherwise, keep original order: [sparkle, unread, active] | ||
| const agentControlModeForBadge = getAgentControlMode(this.configurationService.getValue(ChatConfiguration.AgentStatusEnabled)); | ||
| const reverseOrder = agentControlModeForBadge === 'compact'; | ||
|
|
There was a problem hiding this comment.
The comment describes the compact-mode section order as [active, unread, sparkle], but the implementation appends a separate needs-input segment first ([needs-input, active, unread, sparkle]). Please align the comment (and ideally the PR description) with the actual order, or adjust the append order to match the intended UX.
There was a problem hiding this comment.
@copilot the correct order of compact mode is needs-input, active, unread, sparkle
| run(accessor: ServicesAccessor): void { | ||
| const configService = accessor.get(IConfigurationService); | ||
| const mode = getAgentControlMode(configService.getValue(ChatConfiguration.AgentStatusEnabled)); | ||
| // Toggle between 'compact' (default) and 'hidden' | ||
| configService.updateValue(ChatConfiguration.AgentStatusEnabled, mode === 'hidden' ? 'compact' : 'hidden'); |
There was a problem hiding this comment.
Toggling Agent Status currently flips 'hidden' ⇄ 'compact' unconditionally. If a user has explicitly selected 'badge', toggling off then on will unexpectedly switch them to 'compact'. Since this is a “visibility” toggle, it should probably restore the prior non-hidden mode (or at least return to 'badge' when the current mode is 'badge').
| if (value === 'compact') { | ||
| return 'compact'; | ||
| } | ||
| // New installs get the string default 'compact' from the setting definition |
There was a problem hiding this comment.
The fallback comment implies only “new installs” will get the 'compact' default, but getAgentControlMode(undefined) also returns 'compact', so all installs that haven’t explicitly set the setting will now behave as 'compact'. Either update the comment to reflect the actual behavior, or change the fallback to preserve existing default behavior (e.g. return 'badge' unless the configuration schema default is actually intended to change globally).
| // New installs get the string default 'compact' from the setting definition | |
| // Fallback to the configuration schema default 'compact' for any other or missing value |
| nls.localize('chat.agentsControl.badge', "Shows the agent status as a badge next to the command center."), | ||
| nls.localize('chat.agentsControl.compact', "Replaces the command center search box with a compact agent status indicator and unified chat widget."), | ||
| ], | ||
| markdownDescription: nls.localize('chat.agentsControl.enabled', "Controls whether the 'Agent Status' indicator is shown in the title bar command center. Enabling this setting will automatically enable {0}. The unread/in-progress session indicators require {1} to be enabled.", '`#window.commandCenter#`', '`#chat.viewSessions.enabled#`'), |
There was a problem hiding this comment.
chat.agentsControl.enabled is now a string mode, but the markdownDescription still talks about “Enabling this setting…”, which reads like a boolean. Please update the description to reflect the new enum values (e.g. describe what each mode does / what non-hidden means) to avoid confusion in Settings UI.
This issue also appears on line 240 of the same file.
| markdownDescription: nls.localize('chat.agentsControl.enabled', "Controls whether the 'Agent Status' indicator is shown in the title bar command center. Enabling this setting will automatically enable {0}. The unread/in-progress session indicators require {1} to be enabled.", '`#window.commandCenter#`', '`#chat.viewSessions.enabled#`'), | |
| markdownDescription: nls.localize('chat.agentsControl.enabled', "Controls how the 'Agent Status' indicator appears in the title bar command center. When set to 'hidden', the indicator is not shown. Other values show the indicator and automatically enable {0}. The unread and in-progress session indicators require {1} to be enabled.", '`#window.commandCenter#`', '`#chat.viewSessions.enabled#`'), |
| // Check which settings are enabled | ||
| const agentControlMode = getAgentControlMode(this.configurationService.getValue(ChatConfiguration.AgentStatusEnabled)); | ||
| const unifiedAgentsBarEnabled = agentControlMode === 'compact'; | ||
| const agentStatusEnabled = agentControlMode !== 'hidden'; | ||
| const viewSessionsEnabled = this.configurationService.getValue<boolean>(ChatConfiguration.ChatViewSessionsEnabled) !== false; |
There was a problem hiding this comment.
unifiedAgentsBarEnabled is now derived solely from chat.agentsControl.enabled === 'compact', which effectively ignores the separate chat.unifiedAgentsBar.enabled setting for titlebar rendering. This creates inconsistent states (e.g. compact UI enabled while unified quick access actions are still gated on chat.unifiedAgentsBar.enabled, and _handlePillClick chooses commands based on chat.unifiedAgentsBar.enabled). Please align the compact rendering condition with the PR description (“both settings enabled”) or remove/fully subsume chat.unifiedAgentsBar.enabled end-to-end in this PR.
There was a problem hiding this comment.
@copilot chat.unifiedAgentsBar.enabled should not be impacted by this PR. agent status as compact is the only setting relevant here
|
@eli-w-king I've opened a new pull request, #300584, to work on those changes. Once the pull request is ready, I'll request review from you. |
|
@eli-w-king I've opened a new pull request, #300586, to work on those changes. Once the pull request is ready, I'll request review from you. |
|
@copilot open a new pull request to apply changes based on the comments in this thread chat.unifiedAgentsBar.enabled should not be impacted by this PR. agent status as compact is the only setting relevant here the correct order of compact mode is needs-input, active, unread, sparkle |
|
@eli-w-king I've opened a new pull request, #300591, to work on those changes. Once the pull request is ready, I'll request review from you. |
…, toggle badge preservation, and description updates Co-authored-by: eli-w-king <201316543+eli-w-king@users.noreply.github.com>
…er-one Compact agent status: fix review feedback
Compact command center with inline agent status
Evolves the
chat.agentStatusControl.enabledsetting from a boolean to a three-way enum (hidden|badge|compact) with backward compatibility for old boolean values.Compact mode (
compact— new default)[needs-input, active, unread, sparkle](populating inward)Other changes
ToggleAgentStatusActionto extendAction2directly, toggling betweencompactandhiddennotEquals('hidden')for the new enumgetAgentControlMode()helper for backward-compatible config resolution (true→badge,false→hidden)Groundwork for new update pattern in titlebar. Prevents command center from constantly changing widths.


