diff --git a/src/vs/sessions/contrib/chat/browser/sessionChatInputToolbar.ts b/src/vs/sessions/contrib/chat/browser/sessionChatInputToolbar.ts index 17285abb69f71b..d6a99c549c2ee2 100644 --- a/src/vs/sessions/contrib/chat/browser/sessionChatInputToolbar.ts +++ b/src/vs/sessions/contrib/chat/browser/sessionChatInputToolbar.ts @@ -28,7 +28,7 @@ import { VIEW_SESSION_CHANGES_COMMAND_ID } from '../../changes/common/changes.js import { OPEN_ISSUE_ACTION_ID, OPEN_PULL_REQUEST_ACTION_ID } from '../../github/common/types.js'; import { getSessionChatPillMenu, SessionChatPillKind, SessionChatPillVisibility, type ISessionChatPillMenuEntry } from '../common/sessionChatPills.js'; import { ISessionsService } from '../../../services/sessions/browser/sessionsService.js'; -import { IChat } from '../../../services/sessions/common/session.js'; +import { ChatOriginKind, IChat } from '../../../services/sessions/common/session.js'; import { IActiveSession } from '../../../services/sessions/common/sessionsManagement.js'; import { SessionBackgroundActivitiesControl, sessionSubagentsPillOptions } from './sessionBackgroundActivitiesControl.js'; import { SessionBrowsersControl, sessionBrowsersPillOptions } from './sessionBrowsersControl.js'; @@ -128,6 +128,7 @@ export class SessionChatInputToolbar extends Disposable { } return this._findOwningSession(chat.resource, reader); }); + private readonly _isSubagentChat: IObservable = derived(this, reader => this._chat.read(reader)?.origin?.kind === ChatOriginKind.Tool); /** The current turn's diff stats. */ private readonly _diffStats: IObservable; @@ -181,7 +182,7 @@ export class SessionChatInputToolbar extends Disposable { const sessionCustomizations = this._register(instantiationService.createInstance(SessionCustomizations, this._chat, this._session)); this._customizationSections = sessionCustomizations.sections; - const pillsEnabled = derived(reader => this._debugData.read(reader) !== undefined || turnStatusPillsEnabled.read(reader)); + const pillsEnabled = derived(reader => this._debugData.read(reader) !== undefined || (turnStatusPillsEnabled.read(reader) && !this._isSubagentChat.read(reader))); const model: IChatTurnPillsModel = { stats: this._diffStats, artifacts: this._artifactSections, diff --git a/src/vs/sessions/contrib/chat/test/browser/sessionChatInputToolbar.test.ts b/src/vs/sessions/contrib/chat/test/browser/sessionChatInputToolbar.test.ts index f8743c0f92e48f..77d7b008df39bf 100644 --- a/src/vs/sessions/contrib/chat/test/browser/sessionChatInputToolbar.test.ts +++ b/src/vs/sessions/contrib/chat/test/browser/sessionChatInputToolbar.test.ts @@ -4,16 +4,30 @@ *--------------------------------------------------------------------------------------------*/ import assert from 'assert'; +import { Event } from '../../../../../base/common/event.js'; +import { constObservable } from '../../../../../base/common/observable.js'; +import { URI } from '../../../../../base/common/uri.js'; +import { upcastPartial } from '../../../../../base/test/common/mock.js'; import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js'; +import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js'; +import { TestConfigurationService } from '../../../../../platform/configuration/test/common/testConfigurationService.js'; +import { IBrowserViewWorkbenchService } from '../../../../../workbench/contrib/browserView/common/browserView.js'; +import { ChatConfiguration } from '../../../../../workbench/contrib/chat/common/constants.js'; +import { workbenchInstantiationService } from '../../../../../workbench/test/browser/workbenchTestServices.js'; +import { ISessionsProvidersService } from '../../../../services/sessions/browser/sessionsProvidersService.js'; +import { ISessionsService } from '../../../../services/sessions/browser/sessionsService.js'; +import { ISessionChangesStatsCache } from '../../../../services/sessions/common/sessionChangesStatsCache.js'; +import { ChatOriginKind, SessionStatus, type IChat, type ISessionWorkspace } from '../../../../services/sessions/common/session.js'; +import { IActiveSession } from '../../../../services/sessions/common/sessionsManagement.js'; import { CHAT_TURN_ARTIFACT_PILL_ID, CHAT_TURN_CHANGES_PILL_ID } from '../../../../../workbench/contrib/chat/browser/widget/chatTurnPills.js'; import { VIEW_SESSION_CHANGES_COMMAND_ID } from '../../../changes/common/changes.js'; import { OPEN_ISSUE_ACTION_ID, OPEN_PULL_REQUEST_ACTION_ID } from '../../../github/common/types.js'; import { SessionChatPillKind } from '../../common/sessionChatPills.js'; -import { getSessionChatPillKindForAction, SESSION_BROWSERS_PILL_ID, SESSION_SUBAGENTS_PILL_ID } from '../../browser/sessionChatInputToolbar.js'; +import { getSessionChatPillKindForAction, SessionChatInputToolbar, SESSION_BROWSERS_PILL_ID, SESSION_SUBAGENTS_PILL_ID } from '../../browser/sessionChatInputToolbar.js'; import { SESSION_CUSTOMIZATIONS_PILL_ID } from '../../browser/sessionCustomizations.js'; suite('SessionChatInputToolbar', () => { - ensureNoDisposablesAreLeakedInTestSuite(); + const store = ensureNoDisposablesAreLeakedInTestSuite(); test('maps turn-status and hosted pill actions onto togglable pill kinds', () => { assert.deepStrictEqual([ @@ -36,4 +50,90 @@ suite('SessionChatInputToolbar', () => { SessionChatPillKind.Subagents, ]); }); + + test('hides the pills in a subagent chat', () => { + const instantiationService = workbenchInstantiationService(undefined, store); + (instantiationService.get(IConfigurationService) as TestConfigurationService).setUserConfiguration(ChatConfiguration.TurnStatusPills, true); + const chat = upcastPartial({ + resource: URI.parse('chat:main'), + title: constObservable('Main chat'), + status: constObservable(SessionStatus.InProgress), + lastTurnChanges: constObservable([{ + uri: URI.file('/session-change.ts'), + modifiedUri: URI.file('/session-change.ts'), + insertions: 10, + deletions: 4, + isOutsideWorkspace: false, + }]), + }); + const subagentChat = upcastPartial({ + resource: URI.parse('chat:subagent'), + title: constObservable('Subagent'), + status: constObservable(SessionStatus.InProgress), + origin: { kind: ChatOriginKind.Tool, parentChat: chat.resource }, + }); + const forkedChat = upcastPartial({ + resource: URI.parse('chat:fork'), + title: constObservable('Fork'), + status: constObservable(SessionStatus.InProgress), + origin: { kind: ChatOriginKind.Fork, parentChat: chat.resource }, + lastTurnChanges: constObservable([{ + uri: URI.file('/fork-change.ts'), + modifiedUri: URI.file('/fork-change.ts'), + insertions: 10, + deletions: 4, + isOutsideWorkspace: false, + }]), + }); + const forkSubagentChat = upcastPartial({ + resource: URI.parse('chat:fork-subagent'), + title: constObservable('Fork subagent'), + status: constObservable(SessionStatus.InProgress), + origin: { kind: ChatOriginKind.Tool, parentChat: forkedChat.resource }, + }); + const session = upcastPartial({ + sessionId: 'provider:session', + providerId: 'provider', + sessionType: 'test', + resource: URI.parse('session:1'), + status: constObservable(SessionStatus.InProgress), + isArchived: constObservable(false), + isRead: constObservable(true), + capabilities: constObservable({ supportsMultipleChats: true }), + chats: constObservable([chat, subagentChat, forkedChat, forkSubagentChat]), + activeChat: constObservable(chat), + mainChat: constObservable(chat), + visibleChatTabs: constObservable([chat]), + workspace: constObservable(upcastPartial({ folders: [] })), + worktreePending: constObservable(false), + changesets: constObservable([]), + changes: constObservable([]), + isCreated: constObservable(true), + sticky: constObservable(false), + shouldShowChatTabs: constObservable(false), + }); + instantiationService.stub(IBrowserViewWorkbenchService, upcastPartial({ + onDidChangeBrowserViews: Event.None, + getKnownBrowserViews: () => new Map(), + })); + instantiationService.stub(ISessionChangesStatsCache, upcastPartial({ get: () => undefined })); + instantiationService.stub(ISessionsProvidersService, upcastPartial({ getProvider: () => undefined })); + instantiationService.stub(ISessionsService, upcastPartial({ + visibleSessions: constObservable([]), + activeSession: constObservable(undefined), + })); + const toolbar = store.add(instantiationService.createInstance(SessionChatInputToolbar)); + + toolbar.setSession(session, chat); + const main = toolbar.visible; + toolbar.setSession(session, subagentChat); + const subagent = toolbar.visible; + toolbar.setSession(session, forkedChat); + + assert.deepStrictEqual({ main, subagent, fork: toolbar.visible }, { + main: true, + subagent: false, + fork: true, + }); + }); });