diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts index 69bccb4843b..56c8f5f25e0 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts @@ -513,7 +513,7 @@ export class CreateRemoteAgentJobAction extends Action2 { const chatModel = widget.viewModel?.model; const chatRequests = chatModel.getRequests(); - const agents = remoteCodingAgent.getRegisteredAgents(); + const agents = remoteCodingAgent.getAvailableAgents(); const defaultAgent = chatAgentService.getDefaultAgent(ChatAgentLocation.Panel); const agent = agents[0]; // TODO: We just pick the first one for testing diff --git a/src/vs/workbench/contrib/remoteCodingAgents/browser/remoteCodingAgents.contribution.ts b/src/vs/workbench/contrib/remoteCodingAgents/browser/remoteCodingAgents.contribution.ts index 815d98a4a24..02b5833ccb1 100644 --- a/src/vs/workbench/contrib/remoteCodingAgents/browser/remoteCodingAgents.contribution.ts +++ b/src/vs/workbench/contrib/remoteCodingAgents/browser/remoteCodingAgents.contribution.ts @@ -76,13 +76,12 @@ export class RemoteCodingAgentsContribution extends Disposable implements IWorkb continue; } - // TODO: Handle 'when' clause - const agent: IRemoteCodingAgent = { id: contribution.id, command: contribution.command, displayName: contribution.displayName, - description: contribution.description + description: contribution.description, + when: contribution.when }; this.logService.info(`Registering remote coding agent: ${agent.displayName} (${agent.command})`); this.remoteCodingAgentsService.registerAgent(agent); diff --git a/src/vs/workbench/contrib/remoteCodingAgents/common/remoteCodingAgentsService.ts b/src/vs/workbench/contrib/remoteCodingAgents/common/remoteCodingAgentsService.ts index 492d00d92b6..8ce3fd7361e 100644 --- a/src/vs/workbench/contrib/remoteCodingAgents/common/remoteCodingAgentsService.ts +++ b/src/vs/workbench/contrib/remoteCodingAgents/common/remoteCodingAgentsService.ts @@ -3,7 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IContextKey, IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js'; +import { Disposable } from '../../../../base/common/lifecycle.js'; +import { Event } from '../../../../base/common/event.js'; +import { ContextKeyExpr, IContextKey, IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js'; import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js'; import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js'; import { ChatContextKeys } from '../../chat/common/chatContextKeys.js'; @@ -13,37 +15,80 @@ export interface IRemoteCodingAgent { command: string; displayName: string; description?: string; + when?: string; } export interface IRemoteCodingAgentsService { readonly _serviceBrand: undefined; getRegisteredAgents(): IRemoteCodingAgent[]; + getAvailableAgents(): IRemoteCodingAgent[]; registerAgent(agent: IRemoteCodingAgent): void; } export const IRemoteCodingAgentsService = createDecorator('remoteCodingAgentsService'); -export class RemoteCodingAgentsService implements IRemoteCodingAgentsService { +export class RemoteCodingAgentsService extends Disposable implements IRemoteCodingAgentsService { readonly _serviceBrand: undefined; private readonly _ctxHasRemoteCodingAgent: IContextKey; + private readonly agents: IRemoteCodingAgent[] = []; + private readonly contextKeys = new Set(); constructor( @IContextKeyService private readonly contextKeyService: IContextKeyService ) { + super(); this._ctxHasRemoteCodingAgent = ChatContextKeys.hasRemoteCodingAgent.bindTo(this.contextKeyService); + + // Listen for context changes and re-evaluate agent availability + this._register(Event.filter(contextKeyService.onDidChangeContext, e => e.affectsSome(this.contextKeys))(() => { + this.updateContextKeys(); + })); } - private agents: IRemoteCodingAgent[] = []; - getRegisteredAgents(): IRemoteCodingAgent[] { - return this.agents; + return [...this.agents]; + } + + getAvailableAgents(): IRemoteCodingAgent[] { + return this.agents.filter(agent => this.isAgentAvailable(agent)); } registerAgent(agent: IRemoteCodingAgent): void { - if (!this.agents.includes(agent)) { + // Check if agent already exists + const existingIndex = this.agents.findIndex(a => a.id === agent.id); + if (existingIndex >= 0) { + // Update existing agent + this.agents[existingIndex] = agent; + } else { + // Add new agent this.agents.push(agent); - this._ctxHasRemoteCodingAgent.set(true); } + + // Track context keys from the when condition + if (agent.when) { + const whenExpr = ContextKeyExpr.deserialize(agent.when); + if (whenExpr) { + for (const key of whenExpr.keys()) { + this.contextKeys.add(key); + } + } + } + + this.updateContextKeys(); + } + + private isAgentAvailable(agent: IRemoteCodingAgent): boolean { + if (!agent.when) { + return true; + } + + const whenExpr = ContextKeyExpr.deserialize(agent.when); + return !whenExpr || this.contextKeyService.contextMatchesRules(whenExpr); + } + + private updateContextKeys(): void { + const hasAvailableAgent = this.getAvailableAgents().length > 0; + this._ctxHasRemoteCodingAgent.set(hasAvailableAgent); } }