Add support for allowed session targets in chat components

- Introduced `SessionsChatViewPane` to restrict session targets to Local and Cloud.
- Updated interfaces and classes to include optional `allowedSessionTargets` for session target and delegation pickers.
- Enhanced visibility logic in `DelegationSessionPickerActionItem` and `SessionTypePickerActionItem` to respect allowed targets.
This commit is contained in:
Osvaldo Ortega
2026-02-25 11:25:06 -08:00
parent 7c127d91a5
commit 275b8adcee
7 changed files with 56 additions and 1 deletions
@@ -37,6 +37,17 @@ import { ViewPaneContainer } from '../../../../workbench/browser/parts/views/vie
import { registerIcon } from '../../../../platform/theme/common/iconRegistry.js';
import { ChatViewPane } from '../../../../workbench/contrib/chat/browser/widgetHosts/viewPane/chatViewPane.js';
/**
* Sessions-window subclass of {@link ChatViewPane} that restricts the session
* target and delegation pickers to only show targets supported by the agent
* sessions window (Local and Cloud).
*/
class SessionsChatViewPane extends ChatViewPane {
protected override getAllowedSessionTargets(): ReadonlySet<AgentSessionProviders> {
return new Set([AgentSessionProviders.Local, AgentSessionProviders.Cloud]);
}
}
export class OpenSessionWorktreeInVSCodeAction extends Action2 {
static readonly ID = 'chat.openSessionWorktreeInVSCode';
@@ -201,7 +212,7 @@ class RegisterChatViewContainerContribution implements IWorkbenchContribution {
name: localize2('chat.viewContainer.label', "Chat"),
canToggleVisibility: false,
canMoveView: false,
ctorDescriptor: new SyncDescriptor(ChatViewPane),
ctorDescriptor: new SyncDescriptor(SessionsChatViewPane),
when: IsNewChatSessionContext.negate(),
windowVisibility: WindowVisibility.Sessions
}, {
@@ -91,6 +91,13 @@ export interface ISessionTypePickerDelegate {
* this stores the target for delegation on the next submit instead of immediately creating a new session.
*/
setPendingDelegationTarget?(provider: AgentSessionProviders): void;
/**
* Optional getter for the set of allowed session targets.
* When provided, the session target and delegation pickers will only show targets
* in this set. This allows host contexts (e.g. the agent sessions window) to restrict
* visible targets without adding host-specific dependencies to chat core.
*/
getAllowedTargets?(): ReadonlySet<AgentSessionProviders> | undefined;
/**
* Optional event that fires when the active session provider changes.
* When provided, listeners (like chatInputPart) can react to session type changes
@@ -272,6 +279,14 @@ export interface IChatWidgetViewOptions {
*/
sessionTypePickerDelegate?: ISessionTypePickerDelegate;
/**
* Optional set of allowed session targets for the pickers.
* When provided, only targets in this set will be visible in the session target
* and delegation pickers. This allows host contexts (e.g. the agent sessions window)
* to restrict the available targets.
*/
allowedSessionTargets?: ReadonlySet<AgentSessionProviders>;
/**
* Optional delegate for the workspace picker.
* When provided, shows a workspace picker in the chat input allowing users to select
@@ -1832,6 +1832,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
widgetViewKindTag: this.getWidgetViewKindTag(),
defaultMode: this.viewOptions.defaultMode,
sessionTypePickerDelegate: this.viewOptions.sessionTypePickerDelegate,
allowedSessionTargets: this.viewOptions.allowedSessionTargets,
workspacePickerDelegate: this.viewOptions.workspacePickerDelegate,
};
@@ -159,6 +159,12 @@ export interface IChatInputPartOptions {
* When provided, allows the input part to maintain independent state for the selected session type.
*/
sessionTypePickerDelegate?: ISessionTypePickerDelegate;
/**
* Optional set of allowed session targets for the pickers.
* When provided, only targets in this set will be visible in the session target
* and delegation pickers.
*/
allowedSessionTargets?: ReadonlySet<AgentSessionProviders>;
/**
* Optional delegate for the workspace picker.
* When provided, shows a workspace picker allowing users to select a target workspace
@@ -2199,6 +2205,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
const sessionResource = this._widget?.viewModel?.sessionResource;
return sessionResource ? getAgentSessionProvider(sessionResource) : undefined;
};
const allowedSessionTargets = this.options.allowedSessionTargets;
const delegate: ISessionTypePickerDelegate = this.options.sessionTypePickerDelegate ?? {
getActiveSessionProvider: () => {
return getActiveSessionType();
@@ -2213,6 +2220,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
this.updateAgentSessionTypeContextKey();
this.refreshChatSessionPickers();
},
getAllowedTargets: allowedSessionTargets ? () => allowedSessionTargets : undefined,
};
const isWelcomeViewMode = !!this.options.sessionTypePickerDelegate?.setActiveSessionProvider;
const Picker = (action.id === OpenSessionTargetPickerAction.ID || isWelcomeViewMode) ? SessionTypePickerActionItem : DelegationSessionPickerActionItem;
@@ -50,6 +50,11 @@ export class DelegationSessionPickerActionItem extends SessionTypePickerActionIt
}
protected override _isVisible(type: AgentSessionProviders): boolean {
const allowedTargets = this.delegate.getAllowedTargets?.();
if (allowedTargets && !allowedTargets.has(type)) {
return false;
}
if (this.delegate.getActiveSessionProvider() === type) {
return true; // Always show active session type
}
@@ -181,6 +181,10 @@ export class SessionTypePickerActionItem extends ChatInputPickerActionViewItem {
}
protected _isVisible(type: AgentSessionProviders): boolean {
const allowedTargets = this.delegate.getAllowedTargets?.();
if (allowedTargets && !allowedTargets.has(type)) {
return false;
}
return true;
}
@@ -49,6 +49,7 @@ import { IChatSessionsService, localChatSessionType } from '../../../common/chat
import { LocalChatSessionUri, getChatSessionType } from '../../../common/model/chatUri.js';
import { ChatAgentLocation, ChatConfiguration, ChatModeKind } from '../../../common/constants.js';
import { AgentSessionsControl } from '../../agentSessions/agentSessionsControl.js';
import { AgentSessionProviders } from '../../agentSessions/agentSessions.js';
import { ACTION_ID_NEW_CHAT } from '../../actions/chatActions.js';
import { ChatWidget } from '../../widget/chatWidget.js';
import { ChatViewWelcomeController, IViewWelcomeDelegate } from '../../viewsWelcome/chatViewWelcomeController.js';
@@ -530,6 +531,7 @@ export class ChatViewPane extends ViewPane implements IViewWelcomeDelegate {
: 'explicit',
supportsChangingModes: true,
dndContainer: parent,
allowedSessionTargets: this.getAllowedSessionTargets(),
},
{
listForeground: SIDE_BAR_FOREGROUND,
@@ -547,6 +549,15 @@ export class ChatViewPane extends ViewPane implements IViewWelcomeDelegate {
return this._widget;
}
/**
* Returns the set of allowed session targets for the pickers, or undefined to allow all.
* Subclasses (e.g. in the agent sessions window) can override this to restrict
* the visible targets in the session target and delegation pickers.
*/
protected getAllowedSessionTargets(): ReadonlySet<AgentSessionProviders> | undefined {
return undefined;
}
private createChatTitleControl(parent: HTMLElement): void {
this.titleControl = this._register(this.instantiationService.createInstance(ChatViewTitleControl,
parent,