Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -2389,6 +2389,13 @@ configurationRegistry.registerConfiguration({
description: nls.localize('chat.titleBar.openInAgentsWindow.enabled', "Controls whether the Open in Agents Window button is shown in the title bar."),
default: true,
},
[ChatConfiguration.OpenInAgentsWindowRevealCurrentSession]: {
type: 'boolean',
description: nls.localize('chat.experimental.openInAgentsWindow.revealCurrentSession', "Controls whether Open in Agents Window reveals the current local Agent Host session instead of opening a new session."),
default: false,
tags: ['experimental'],
experiment: { mode: 'auto' },
},
'chat.approvedAccountOrganizations': {
type: 'array',
items: { type: 'string' },
Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/contrib/chat/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export enum ChatConfiguration {
GrowthNotificationEnabled = 'chat.growthNotification.enabled',
TitleBarSignInEnabled = 'chat.titleBar.signIn.enabled',
TitleBarOpenInAgentsWindowEnabled = 'chat.titleBar.openInAgentsWindow.enabled',
OpenInAgentsWindowRevealCurrentSession = 'chat.experimental.openInAgentsWindow.revealCurrentSession',

ChatCustomizationsStructuredPreviewEnabled = 'chat.customizations.structuredPreview.enabled',
ChatCustomizationsPromptMigrationEnabled = 'chat.customizations.promptMigration.enabled',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { IWorkbenchContribution } from '../../../../common/contributions.js';
import { CHAT_CATEGORY } from '../../browser/actions/chatActions.js';
import { IChatWidgetService } from '../../browser/chat.js';
import { ChatContextKeys } from '../../common/actions/chatContextKeys.js';
import { SessionType } from '../../common/chatSessionsService.js';
import { isLocalAgentHostTarget, SessionType } from '../../common/chatSessionsService.js';
import { IChatViewTitleActionContext } from '../../common/actions/chatActions.js';
import { getChatSessionType, isUntitledChatSession } from '../../common/model/chatUri.js';
import { ChatInputNotificationActionKind, ChatInputNotificationSeverity, IChatInputNotificationService } from '../../browser/widget/input/chatInputNotificationService.js';
Expand Down Expand Up @@ -115,6 +115,20 @@ export class OpenWorkspaceInAgentsWindowTitleBarAction extends Action2 {
}

async run(accessor: ServicesAccessor): Promise<void> {
const configurationService = accessor.get(IConfigurationService);
const sessionResource = accessor.get(IChatWidgetService).lastFocusedWidget?.viewModel?.sessionResource;
if (configurationService.getValue<boolean>(ChatConfiguration.OpenInAgentsWindowRevealCurrentSession) === true
&& sessionResource
&& !isUntitledChatSession(sessionResource)
&& isLocalAgentHostTarget(getChatSessionType(sessionResource))) {
await accessor.get(ICommandService).executeCommand(
OpenChatSessionInAgentsWindowAction.ID,
{ agentsWindowOpenSource: AgentsWindowOpenSource.TitleBar },
sessionResource,
);
return;
}

await accessor.get(ICommandService).executeCommand(OPEN_WORKSPACE_IN_AGENTS_WINDOW_COMMAND_ID, { source: AgentsWindowOpenSource.TitleBar });
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,28 @@ import { encodeHex, VSBuffer } from '../../../../../base/common/buffer.js';
import { DisposableStore } from '../../../../../base/common/lifecycle.js';
import { Schemas } from '../../../../../base/common/network.js';
import { URI } from '../../../../../base/common/uri.js';
import { upcastPartial } from '../../../../../base/test/common/mock.js';
import { mock, upcastPartial } from '../../../../../base/test/common/mock.js';
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';
import { ICommandService } from '../../../../../platform/commands/common/commands.js';
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js';
import { TestConfigurationService } from '../../../../../platform/configuration/test/common/testConfigurationService.js';
import { TestInstantiationService } from '../../../../../platform/instantiation/test/common/instantiationServiceMock.js';
import { INativeHostService, IOpenAgentsWindowOptions } from '../../../../../platform/native/common/native.js';
import { AgentsWindowOpenSource } from '../../../../../platform/window/common/window.js';
import { IWorkspaceContextService } from '../../../../../platform/workspace/common/workspace.js';
import { OpenWorkspaceInAgentsWindowAction } from '../../electron-browser/agentSessions/agentSessionsActions.js';
import { IChatWidget, IChatWidgetService } from '../../browser/chat.js';
import { ChatConfiguration, OPEN_WORKSPACE_IN_AGENTS_WINDOW_COMMAND_ID } from '../../common/constants.js';
import { IChatViewModel } from '../../common/model/chatViewModel.js';
import { OpenChatSessionInAgentsWindowAction, OpenWorkspaceInAgentsWindowAction, OpenWorkspaceInAgentsWindowTitleBarAction } from '../../electron-browser/agentSessions/agentSessionsActions.js';

class TestCommandService extends mock<ICommandService>() {
readonly calls: { readonly commandId: string; readonly args: readonly unknown[] }[] = [];

override async executeCommand<T = unknown>(commandId: string, ...args: unknown[]): Promise<T | undefined> {
this.calls.push({ commandId, args });
return undefined;
}
}

suite('OpenWorkspaceInAgentsWindowAction', () => {
const disposables = ensureNoDisposablesAreLeakedInTestSuite();
Expand Down Expand Up @@ -64,3 +79,64 @@ suite('OpenWorkspaceInAgentsWindowAction', () => {
}]);
});
});

suite('OpenWorkspaceInAgentsWindowTitleBarAction', () => {
const disposables = ensureNoDisposablesAreLeakedInTestSuite();

async function run(sessionResource: URI | undefined, revealCurrentSession = true) {
const instantiationService = disposables.add(new TestInstantiationService());
const commandService = new TestCommandService();
const configurationService = new TestConfigurationService({
[ChatConfiguration.OpenInAgentsWindowRevealCurrentSession]: revealCurrentSession,
});
instantiationService.stub(ICommandService, commandService);
instantiationService.stub(IConfigurationService, configurationService);
instantiationService.stub(IChatWidgetService, upcastPartial<IChatWidgetService>({
lastFocusedWidget: sessionResource ? upcastPartial<IChatWidget>({
viewModel: upcastPartial<IChatViewModel>({ sessionResource }),
}) : undefined,
}));

const action = new OpenWorkspaceInAgentsWindowTitleBarAction();
await instantiationService.invokeFunction(accessor => action.run(accessor));
return commandService.calls;
}

test('reveals a persisted local Agent Host session and otherwise opens a workspace draft', async () => {
const localSession = URI.from({ scheme: 'agent-host-claude', path: '/session' });

assert.deepStrictEqual({
localSession: await run(localSession),
disabled: await run(localSession, false),
untitledLocalSession: await run(URI.from({ scheme: 'agent-host-claude', path: '/untitled-session' })),
remoteSession: await run(URI.from({ scheme: 'remote-host-claude', path: '/session' })),
regularSession: await run(URI.from({ scheme: 'vscode-chat-session', path: '/session' })),
noSession: await run(undefined),
}, {
localSession: [{
commandId: OpenChatSessionInAgentsWindowAction.ID,
args: [{ agentsWindowOpenSource: AgentsWindowOpenSource.TitleBar }, localSession],
}],
disabled: [{
commandId: OPEN_WORKSPACE_IN_AGENTS_WINDOW_COMMAND_ID,
args: [{ source: AgentsWindowOpenSource.TitleBar }],
}],
untitledLocalSession: [{
commandId: OPEN_WORKSPACE_IN_AGENTS_WINDOW_COMMAND_ID,
args: [{ source: AgentsWindowOpenSource.TitleBar }],
}],
remoteSession: [{
commandId: OPEN_WORKSPACE_IN_AGENTS_WINDOW_COMMAND_ID,
args: [{ source: AgentsWindowOpenSource.TitleBar }],
}],
regularSession: [{
commandId: OPEN_WORKSPACE_IN_AGENTS_WINDOW_COMMAND_ID,
args: [{ source: AgentsWindowOpenSource.TitleBar }],
}],
noSession: [{
commandId: OPEN_WORKSPACE_IN_AGENTS_WINDOW_COMMAND_ID,
args: [{ source: AgentsWindowOpenSource.TitleBar }],
}],
});
});
});