Implement when clause for remoteCodingAgents (#252366)

implement when clause for remoteCodingAgents
This commit is contained in:
Josh Spicer
2025-06-24 21:52:40 -07:00
committed by GitHub
parent cf75ff528c
commit e2d78c850f
3 changed files with 55 additions and 11 deletions
@@ -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
@@ -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);
@@ -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<IRemoteCodingAgentsService>('remoteCodingAgentsService');
export class RemoteCodingAgentsService implements IRemoteCodingAgentsService {
export class RemoteCodingAgentsService extends Disposable implements IRemoteCodingAgentsService {
readonly _serviceBrand: undefined;
private readonly _ctxHasRemoteCodingAgent: IContextKey<boolean>;
private readonly agents: IRemoteCodingAgent[] = [];
private readonly contextKeys = new Set<string>();
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);
}
}