Skip to content

Commit 09e2d4a

Browse files
authored
Fix async octokit calls to check for auth first (#2423)
* fix * type
1 parent 3b825b0 commit 09e2d4a

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

src/extension/agents/vscode-node/organizationAndEnterpriseAgentProvider.ts

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ export class OrganizationAndEnterpriseAgentProvider extends Disposable implement
110110
}
111111
}
112112

113+
private async runWithAuthCheck<T>(operation: () => Promise<T>): Promise<T> {
114+
const user = await this.octoKitService.getCurrentAuthedUser();
115+
if (!user) {
116+
throw new Error('User is not signed in');
117+
}
118+
return operation();
119+
}
120+
113121
private async fetchAndUpdateCache(
114122
options: vscode.CustomAgentQueryOptions
115123
): Promise<void> {
@@ -121,10 +129,16 @@ export class OrganizationAndEnterpriseAgentProvider extends Disposable implement
121129

122130
this.isFetching = true;
123131
try {
132+
const user = await this.octoKitService.getCurrentAuthedUser();
133+
if (!user) {
134+
this.logService.trace('[OrganizationAndEnterpriseAgentProvider] User not signed in, skipping fetch');
135+
return;
136+
}
137+
124138
this.logService.trace('[OrganizationAndEnterpriseAgentProvider] Fetching custom agents from all user organizations');
125139

126140
// Get all organizations the user belongs to
127-
const organizations = await this.octoKitService.getUserOrganizations();
141+
const organizations = await this.runWithAuthCheck(() => this.octoKitService.getUserOrganizations());
128142
if (organizations.length === 0) {
129143
this.logService.trace('[OrganizationAndEnterpriseAgentProvider] User does not belong to any organizations');
130144
return;
@@ -148,19 +162,23 @@ export class OrganizationAndEnterpriseAgentProvider extends Disposable implement
148162

149163
// Get the first repository for this organization to use in the API call
150164
// We can't just use .github-private because user may not have access to it
151-
const repos = await this.octoKitService.getOrganizationRepositories(org);
165+
const repos = await this.runWithAuthCheck(() => this.octoKitService.getOrganizationRepositories(org));
152166
if (repos.length === 0) {
153167
this.logService.trace(`[OrganizationAndEnterpriseAgentProvider] No repositories found for ${org}, skipping`);
154168
continue;
155169
}
156170

157171
const repoName = repos[0];
158-
const agents = await this.octoKitService.getCustomAgents(org, repoName, internalOptions);
172+
const agents = await this.runWithAuthCheck(() => this.octoKitService.getCustomAgents(org, repoName, internalOptions));
159173
for (const agent of agents) {
160174
agentsForOrg.set(agent.name, agent);
161175
}
162176
this.logService.trace(`[OrganizationAndEnterpriseAgentProvider] Fetched ${agents.length} agents from ${org} using repo ${repoName}`);
163177
} catch (error) {
178+
if (error instanceof Error && error.message === 'User is not signed in') {
179+
this.logService.trace('[OrganizationAndEnterpriseAgentProvider] User signed out during fetch, aborting');
180+
return;
181+
}
164182
this.logService.error(`[OrganizationAndEnterpriseAgentProvider] Error fetching agents from ${org}: ${error}`);
165183
hadAnyFetchErrors = true;
166184
}
@@ -222,12 +240,12 @@ export class OrganizationAndEnterpriseAgentProvider extends Disposable implement
222240
const filename = this.sanitizeFilename(agent.name) + AgentFileExtension;
223241

224242
// Fetch full agent details including prompt content
225-
const agentDetails = await this.octoKitService.getCustomAgentDetails(
243+
const agentDetails = await this.runWithAuthCheck(() => this.octoKitService.getCustomAgentDetails(
226244
agent.repo_owner,
227245
agent.repo_name,
228246
agent.name,
229247
agent.version
230-
);
248+
));
231249

232250
// Generate agent markdown file content
233251
if (agentDetails) {
@@ -236,6 +254,10 @@ export class OrganizationAndEnterpriseAgentProvider extends Disposable implement
236254
totalAgents++;
237255
}
238256
} catch (error) {
257+
if (error instanceof Error && error.message === 'User is not signed in') {
258+
this.logService.trace('[OrganizationAndEnterpriseAgentProvider] User signed out during fetch, aborting');
259+
return;
260+
}
239261
this.logService.error(`[OrganizationAndEnterpriseAgentProvider] Error fetching details for agent ${agent.name} from ${org}: ${error}`);
240262
hadFetchError = true;
241263
}

src/extension/agents/vscode-node/test/organizationAndEnterpriseAgentProvider.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -873,4 +873,30 @@ Test prompt
873873

874874
assert.equal(content, expectedContent);
875875
});
876+
877+
test('aborts fetch if user signs out during process', async () => {
878+
const provider = createProvider();
879+
880+
// Setup multiple organizations to ensure we have multiple steps
881+
mockOctoKitService.setUserOrganizations(['org1', 'org2']);
882+
mockOctoKitService.getOrganizationRepositories = async (org) => ['repo'];
883+
884+
// Mock getCustomAgents to simulate sign out after first org
885+
let callCount = 0;
886+
const originalGetCustomAgents = mockOctoKitService.getCustomAgents;
887+
mockOctoKitService.getCustomAgents = async (owner, repo, options) => {
888+
callCount++;
889+
if (callCount === 1) {
890+
// Sign out user after first call
891+
mockOctoKitService.getCurrentAuthedUser = async () => undefined as any;
892+
}
893+
return originalGetCustomAgents.call(mockOctoKitService, owner, repo, options);
894+
};
895+
896+
await provider.provideCustomAgents({}, {} as any);
897+
await new Promise(resolve => setTimeout(resolve, 100));
898+
899+
// Should have aborted after first org, so second org shouldn't be processed
900+
assert.equal(callCount, 1);
901+
});
876902
});

0 commit comments

Comments
 (0)