Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 32 additions & 8 deletions src/vs/workbench/contrib/chat/browser/chatViewPane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import './media/chatViewPane.css';
import { $, getWindow } from '../../../../base/browser/dom.js';
import { $, append, getWindow } from '../../../../base/browser/dom.js';
import { CancellationToken } from '../../../../base/common/cancellation.js';
import { MutableDisposable, toDisposable } from '../../../../base/common/lifecycle.js';
import { MarshalledId } from '../../../../base/common/marshallingIds.js';
Expand Down Expand Up @@ -36,11 +36,15 @@ import { CHAT_PROVIDER_ID } from '../common/chatParticipantContribTypes.js';
import { IChatModelReference, IChatService } from '../common/chatService.js';
import { IChatSessionsExtensionPoint, IChatSessionsService, localChatSessionType } from '../common/chatSessionsService.js';
import { LocalChatSessionUri } from '../common/chatUri.js';
import { ChatAgentLocation, ChatConfiguration, ChatModeKind } from '../common/constants.js';
import { ChatAgentLocation, ChatConfiguration, ChatModeKind, LEGACY_AGENT_SESSIONS_VIEW_ID } from '../common/constants.js';
import { AGENT_SESSIONS_VIEW_ID } from './agentSessions/agentSessions.js';
import { showCloseActiveChatNotification } from './actions/chatCloseNotification.js';
import { ChatWidget } from './chatWidget.js';
import { Link } from '../../../../platform/opener/browser/link.js';
import { localize } from '../../../../nls.js';
import { ChatViewWelcomeController, IViewWelcomeDelegate } from './viewsWelcome/chatViewWelcomeController.js';
import { AgentSessionsControl } from './agentSessions/agentSessionsControl.js';
import { ICommandService } from '../../../../platform/commands/common/commands.js';
Comment on lines +43 to +47
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imports should be grouped and ordered consistently. The newly added imports should be placed with their respective groups:

  • Link (line 43) should be with other platform imports (lines 13-26)
  • localize (line 44) should be earlier, typically near the top with base imports
  • ICommandService (line 47) should be with other platform imports (lines 13-26)

Suggested order:

import { localize } from '../../../../nls.js';
// ... other base imports ...
import { ICommandService } from '../../../../platform/commands/common/commands.js';
// ... other platform imports ...
import { Link } from '../../../../platform/opener/browser/link.js';

Copilot uses AI. Check for mistakes.

interface IChatViewPaneState extends Partial<IChatModelInputState> {
sessionId?: string;
Expand All @@ -64,6 +68,7 @@ export class ChatViewPane extends ViewPane implements IViewWelcomeDelegate {

private sessionsContainer: HTMLElement | undefined;
private sessionsControl: AgentSessionsControl | undefined;
private sessionsLinkContainer: HTMLElement | undefined;

private restoringSession: Promise<void> | undefined;

Expand All @@ -88,6 +93,7 @@ export class ChatViewPane extends ViewPane implements IViewWelcomeDelegate {
@ILayoutService private readonly layoutService: ILayoutService,
@IChatSessionsService private readonly chatSessionsService: IChatSessionsService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@ICommandService private readonly commandService: ICommandService,
) {
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, hoverService);

Expand Down Expand Up @@ -247,9 +253,24 @@ export class ChatViewPane extends ViewPane implements IViewWelcomeDelegate {
}

private createSessionsControl(parent: HTMLElement): void {
this.sessionsContainer = parent.appendChild($('.chat-viewpane-sessions-container'));

// Sessions Control
this.sessionsContainer = parent.appendChild($('.agent-sessions-container'));
this.sessionsControl = this._register(this.instantiationService.createInstance(AgentSessionsControl, this.sessionsContainer, undefined));

// Link to Sessions View
this.sessionsLinkContainer = append(this.sessionsContainer, $('.agent-sessions-link-container'));
this._register(this.instantiationService.createInstance(Link, this.sessionsLinkContainer, { label: localize('openAgentSessionsView', "Show All Sessions"), href: '', }, {
opener: () => {
// TODO@bpasero remove this check once settled
if (this.configurationService.getValue('chat.agentSessionsViewLocation') === 'single-view') {
this.commandService.executeCommand(AGENT_SESSIONS_VIEW_ID);
} else {
this.commandService.executeCommand(LEGACY_AGENT_SESSIONS_VIEW_ID);
Comment on lines +264 to +269
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider making the opener callback async to be consistent with other usages in the codebase (e.g., searchMessage.ts), even though the Link class doesn't await the result:

opener: async () => {
	// TODO@bpasero remove this check once settled
	if (this.configurationService.getValue('chat.agentSessionsViewLocation') === 'single-view') {
		await this.commandService.executeCommand(AGENT_SESSIONS_VIEW_ID);
	} else {
		await this.commandService.executeCommand(LEGACY_AGENT_SESSIONS_VIEW_ID);
	}
}
Suggested change
opener: () => {
// TODO@bpasero remove this check once settled
if (this.configurationService.getValue('chat.agentSessionsViewLocation') === 'single-view') {
this.commandService.executeCommand(AGENT_SESSIONS_VIEW_ID);
} else {
this.commandService.executeCommand(LEGACY_AGENT_SESSIONS_VIEW_ID);
opener: async () => {
// TODO@bpasero remove this check once settled
if (this.configurationService.getValue('chat.agentSessionsViewLocation') === 'single-view') {
await this.commandService.executeCommand(AGENT_SESSIONS_VIEW_ID);
} else {
await this.commandService.executeCommand(LEGACY_AGENT_SESSIONS_VIEW_ID);

Copilot uses AI. Check for mistakes.
}
}
}));

this.updateSessionsControlVisibility(false);

this._register(this.onDidChangeBodyVisibility(() => this.updateSessionsControlVisibility(true)));
Expand Down Expand Up @@ -373,14 +394,17 @@ export class ChatViewPane extends ViewPane implements IViewWelcomeDelegate {

this.lastDimensions = { height, width };

let widgetHeight = height;
let remainingHeight = height;

// Sessions Control
const sessionsControlHeight = this.sessionsContainer?.offsetHeight ?? 0;
widgetHeight -= sessionsControlHeight;
this.sessionsControl?.layout(sessionsControlHeight, width);
const sessionsContainerHeight = this.sessionsContainer?.offsetHeight ?? 0;
remainingHeight -= sessionsContainerHeight;

this._widget.layout(widgetHeight, width);
const sessionsLinkHeight = this.sessionsLinkContainer?.offsetHeight ?? 0;
this.sessionsControl?.layout(sessionsContainerHeight - sessionsLinkHeight, width);

// Chat Widget
this._widget.layout(remainingHeight, width);
}

override saveState(): void {
Expand Down
15 changes: 13 additions & 2 deletions src/vs/workbench/contrib/chat/browser/media/chatViewPane.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,18 @@
display: flex;
flex-direction: column;

.chat-viewpane-sessions-container {
height: calc(3 * 44px); /* TODO@bpasero revisit: show at most 3 sessions */
.agent-sessions-container {
display: flex;
flex-direction: column;

.agent-sessions-viewer {
height: calc(3 * 44px); /* TODO@bpasero revisit: show at most 3 sessions */
}

.agent-sessions-link-container {
padding: 4px 12px;
font-size: 12px;
text-align: center;
}
}
}
Loading