Skip to content

Commit 1d1a373

Browse files
Copilotjoshspicer
andauthored
Implement GitHub Coding Agent availability and assignability context setting (#7105)
* Initial plan * Changes before error encountered Co-authored-by: joshspicer <23246594+joshspicer@users.noreply.github.com> * Remove excessive tests to simplify implementation Co-authored-by: joshspicer <23246594+joshspicer@users.noreply.github.com> * remove gate for pr tool * Initial plan * Implement GitHub Coding Agent availability and assignability context setting Co-authored-by: joshspicer <23246594+joshspicer@users.noreply.github.com> * Update remoteCodingAgents contribution with id and context condition Co-authored-by: joshspicer <23246594+joshspicer@users.noreply.github.com> * tidy up --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: joshspicer <23246594+joshspicer@users.noreply.github.com>
1 parent bb5eaa8 commit 1d1a373

3 files changed

Lines changed: 95 additions & 1 deletion

File tree

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,11 @@
6767
"contributes": {
6868
"remoteCodingAgents": [
6969
{
70+
"id": "githubCodingAgent",
7071
"command": "githubpr.remoteAgent",
7172
"displayName": "GitHub Coding Agent",
7273
"description": "The GitHub Coding Agent.",
73-
"when": "config.githubPullRequests.codingAgent.enabled"
74+
"when": "config.githubPullRequests.codingAgent.enabled && copilotCodingAgentAssignable"
7475
}
7576
],
7677
"chatParticipants": [

src/github/copilotRemoteAgent.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import vscode from 'vscode';
77
import { Repository } from '../api/api';
88
import { AuthProvider } from '../common/authentication';
9+
import { COPILOT_LOGINS } from '../common/copilot';
10+
import { commands } from '../common/executeCommands';
911
import { Disposable } from '../common/lifecycle';
1012
import { Remote } from '../common/remote';
1113
import { CODING_AGENT, CODING_AGENT_AUTO_COMMIT_AND_PUSH, CODING_AGENT_ENABLED } from '../common/settingKeys';
@@ -55,6 +57,28 @@ export class CopilotRemoteAgentManager extends Disposable {
5557
this._register(new CopilotPRWatcher(this.repositoriesManager, this._stateModel));
5658
this._register(this._stateModel.onDidChangeStates(() => this._onDidChangeStates.fire()));
5759
this._register(this._stateModel.onDidChangeNotifications(() => this._onDidChangeNotifications.fire()));
60+
61+
this._register(this.repositoriesManager.onDidChangeFolderRepositories((event) => {
62+
if (event.added) {
63+
this._register(event.added.onDidChangeAssignableUsers(() => {
64+
this.updateAssignabilityContext();
65+
}));
66+
}
67+
this.updateAssignabilityContext();
68+
}));
69+
this.repositoriesManager.folderManagers.forEach(manager => {
70+
this._register(manager.onDidChangeAssignableUsers(() => {
71+
this.updateAssignabilityContext();
72+
}));
73+
});
74+
this._register(vscode.workspace.onDidChangeConfiguration((e) => {
75+
if (e.affectsConfiguration(CODING_AGENT)) {
76+
this.updateAssignabilityContext();
77+
}
78+
}));
79+
80+
// Set initial context
81+
this.updateAssignabilityContext();
5882
}
5983

6084
private _copilotApiPromise: Promise<CopilotApi | undefined> | undefined;
@@ -79,6 +103,61 @@ export class CopilotRemoteAgentManager extends Disposable {
79103
.getConfiguration(CODING_AGENT).get(CODING_AGENT_ENABLED, false);
80104
}
81105

106+
async isAssignable(): Promise<boolean> {
107+
const repoInfo = await this.repoInfo();
108+
if (!repoInfo) {
109+
return false;
110+
}
111+
112+
const { owner, repo } = repoInfo;
113+
const folderManager = this.getFolderManagerForRepo(owner, repo);
114+
115+
try {
116+
// Ensure assignable users are loaded
117+
await folderManager.getAssignableUsers();
118+
const allAssignableUsers = folderManager.getAllAssignableUsers();
119+
120+
if (!allAssignableUsers) {
121+
return false;
122+
}
123+
124+
// Check if any of the copilot logins are in the assignable users
125+
return allAssignableUsers.some(user => COPILOT_LOGINS.includes(user.login));
126+
} catch (error) {
127+
// If there's an error fetching assignable users, assume not assignable
128+
return false;
129+
}
130+
}
131+
132+
async isAvailable(): Promise<boolean> {
133+
// Check if the manager is enabled, copilot API is available, and it's assignable
134+
if (!this.enabled()) {
135+
return false;
136+
}
137+
138+
const repoInfo = await this.repoInfo();
139+
if (!repoInfo) {
140+
return false;
141+
}
142+
143+
const copilotApi = await this.copilotApi;
144+
if (!copilotApi) {
145+
return false;
146+
}
147+
148+
return await this.isAssignable();
149+
}
150+
151+
private async updateAssignabilityContext(): Promise<void> {
152+
try {
153+
const available = await this.isAvailable();
154+
commands.setContext('copilotCodingAgentAssignable', available);
155+
} catch (error) {
156+
// Presume false
157+
commands.setContext('copilotCodingAgentAssignable', false);
158+
}
159+
}
160+
82161
autoCommitAndPushEnabled(): boolean {
83162
return vscode.workspace
84163
.getConfiguration(CODING_AGENT).get(CODING_AGENT_AUTO_COMMIT_AND_PUSH, false);
@@ -114,6 +193,13 @@ export class CopilotRemoteAgentManager extends Disposable {
114193
}
115194

116195
async commandImpl(args?: any) {
196+
// Check if the coding agent is available (enabled and assignable)
197+
const isAvailable = await this.isAvailable();
198+
if (!isAvailable) {
199+
vscode.window.showWarningMessage(vscode.l10n.t('GitHub Coding Agent is not available for this repository. Make sure the agent is enabled and assignable to this repository.'));
200+
return;
201+
}
202+
117203
// https://github.com/microsoft/vscode-copilot/issues/18918
118204
const userPrompt: string | undefined = args.userPrompt;
119205
const summary: string | undefined = args.summary;

src/lm/tools/copilotRemoteAgentTool.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ export class CopilotRemoteAgentTool implements vscode.LanguageModelTool<CopilotR
2525

2626
async prepareInvocation(options: vscode.LanguageModelToolInvocationPrepareOptions<CopilotRemoteAgentToolParameters>): Promise<vscode.PreparedToolInvocation> {
2727
const { title } = options.input;
28+
29+
// Check if the coding agent is available (enabled and assignable)
30+
const isAvailable = await this.manager.isAvailable();
31+
if (!isAvailable) {
32+
throw new Error(vscode.l10n.t('GitHub Coding Agent is not available for this repository. Make sure the agent is enabled and assignable to this repository.'));
33+
}
34+
2835
const targetRepo = await this.manager.repoInfo();
2936
const autoPushEnabled = this.manager.autoCommitAndPushEnabled();
3037
return {

0 commit comments

Comments
 (0)