From e838393d83fb35975863d6ea88ba892defc20e5f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Dec 2025 12:00:27 +0000 Subject: [PATCH 1/4] Initial plan From 07e7ce42c17f090774c803fb3b640a09e8b90ce5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Dec 2025 12:05:42 +0000 Subject: [PATCH 2/4] Initial plan for adding Reauthenticate button to SAML error Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com> --- src/@types/vscode.proposed.chatParticipantAdditions.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/@types/vscode.proposed.chatParticipantAdditions.d.ts b/src/@types/vscode.proposed.chatParticipantAdditions.d.ts index 71520fa1ec..aa7001a3d2 100644 --- a/src/@types/vscode.proposed.chatParticipantAdditions.d.ts +++ b/src/@types/vscode.proposed.chatParticipantAdditions.d.ts @@ -105,6 +105,7 @@ declare module 'vscode' { isComplete?: boolean; toolSpecificData?: ChatTerminalToolInvocationData; fromSubAgent?: boolean; + presentation?: 'hidden' | 'hiddenAfterComplete' | undefined; constructor(toolName: string, toolCallId: string, isError?: boolean); } From 44d8dca3ba8fdf38601c48a6ef9218ab8fa764f3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Dec 2025 12:09:39 +0000 Subject: [PATCH 3/4] Add Reauthenticate button to SAML error messages Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com> --- src/github/folderRepositoryManager.ts | 28 +++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/github/folderRepositoryManager.ts b/src/github/folderRepositoryManager.ts index 9dd9002c84..c4a03f9270 100644 --- a/src/github/folderRepositoryManager.ts +++ b/src/github/folderRepositoryManager.ts @@ -534,12 +534,36 @@ export class FolderRepositoryManager extends Disposable { const stillMissing = result.canceled ? missingSaml : samlTest.map((result, index) => !result ? missingSaml[index] : undefined).filter((repo): repo is GitHubRepository => !!repo); // Make a test call to see if the user has SAML enabled. if (stillMissing.length > 0) { + const reauthenticate = vscode.l10n.t('Reauthenticate'); if (stillMissing.length === repositories.length) { - await vscode.window.showErrorMessage(vscode.l10n.t('SAML access was not provided. GitHub Pull Requests will not work.'), { modal: true }); + const choice = await vscode.window.showErrorMessage(vscode.l10n.t('SAML access was not provided. GitHub Pull Requests will not work.'), { modal: true }, reauthenticate); + if (choice === reauthenticate) { + const retryResult = await this._credentialStore.showSamlMessageAndAuth(stillMissing.map(repo => repo.remote.owner)); + if (!retryResult.canceled) { + const retryTest = await Promise.all(stillMissing.map(repo => repo.resolveRemote())); + const stillMissingAfterRetry = retryTest.map((result, index) => !result ? stillMissing[index] : undefined).filter((repo): repo is GitHubRepository => !!repo); + if (stillMissingAfterRetry.length === 0) { + // Success! Continue with initialization + return false; + } + } + } this.dispose(); return true; } - await vscode.window.showErrorMessage(vscode.l10n.t('SAML access was not provided. Some GitHub repositories will not be available.'), { modal: true }); + const choice = await vscode.window.showErrorMessage(vscode.l10n.t('SAML access was not provided. Some GitHub repositories will not be available.'), { modal: true }, reauthenticate); + if (choice === reauthenticate) { + const retryResult = await this._credentialStore.showSamlMessageAndAuth(stillMissing.map(repo => repo.remote.owner)); + if (!retryResult.canceled) { + const retryTest = await Promise.all(stillMissing.map(repo => repo.resolveRemote())); + const stillMissingAfterRetry = retryTest.map((result, index) => !result ? stillMissing[index] : undefined).filter((repo): repo is GitHubRepository => !!repo); + if (stillMissingAfterRetry.length < stillMissing.length) { + // Some repos now have access, update stillMissing + cleanUpMissingSaml(stillMissingAfterRetry); + return false; + } + } + } cleanUpMissingSaml(stillMissing); } } From 789f8a35105f8619f2e16aca105d4768527b5e45 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Dec 2025 12:14:18 +0000 Subject: [PATCH 4/4] Refactor: Extract SAML retry logic into helper function Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com> --- src/github/folderRepositoryManager.ts | 36 ++++++++++++++------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/github/folderRepositoryManager.ts b/src/github/folderRepositoryManager.ts index c4a03f9270..cfdfe03533 100644 --- a/src/github/folderRepositoryManager.ts +++ b/src/github/folderRepositoryManager.ts @@ -520,6 +520,15 @@ export class FolderRepositoryManager extends Disposable { } }; + const retrySamlAuth = async (repos: GitHubRepository[]): Promise => { + const retryResult = await this._credentialStore.showSamlMessageAndAuth(repos.map(repo => repo.remote.owner)); + if (retryResult.canceled) { + return repos; + } + const retryTest = await Promise.all(repos.map(repo => repo.resolveRemote())); + return retryTest.map((result, index) => !result ? repos[index] : undefined).filter((repo): repo is GitHubRepository => !!repo); + }; + return Promise.all(resolveRemotePromises).then(async (remoteResults: boolean[]) => { const missingSaml: GitHubRepository[] = []; for (let i = 0; i < remoteResults.length; i++) { @@ -538,14 +547,11 @@ export class FolderRepositoryManager extends Disposable { if (stillMissing.length === repositories.length) { const choice = await vscode.window.showErrorMessage(vscode.l10n.t('SAML access was not provided. GitHub Pull Requests will not work.'), { modal: true }, reauthenticate); if (choice === reauthenticate) { - const retryResult = await this._credentialStore.showSamlMessageAndAuth(stillMissing.map(repo => repo.remote.owner)); - if (!retryResult.canceled) { - const retryTest = await Promise.all(stillMissing.map(repo => repo.resolveRemote())); - const stillMissingAfterRetry = retryTest.map((result, index) => !result ? stillMissing[index] : undefined).filter((repo): repo is GitHubRepository => !!repo); - if (stillMissingAfterRetry.length === 0) { - // Success! Continue with initialization - return false; - } + const stillMissingAfterRetry = await retrySamlAuth(stillMissing); + // Only proceed if all repositories now have SAML access + if (stillMissingAfterRetry.length === 0) { + // Success! Continue with initialization + return false; } } this.dispose(); @@ -553,15 +559,11 @@ export class FolderRepositoryManager extends Disposable { } const choice = await vscode.window.showErrorMessage(vscode.l10n.t('SAML access was not provided. Some GitHub repositories will not be available.'), { modal: true }, reauthenticate); if (choice === reauthenticate) { - const retryResult = await this._credentialStore.showSamlMessageAndAuth(stillMissing.map(repo => repo.remote.owner)); - if (!retryResult.canceled) { - const retryTest = await Promise.all(stillMissing.map(repo => repo.resolveRemote())); - const stillMissingAfterRetry = retryTest.map((result, index) => !result ? stillMissing[index] : undefined).filter((repo): repo is GitHubRepository => !!repo); - if (stillMissingAfterRetry.length < stillMissing.length) { - // Some repos now have access, update stillMissing - cleanUpMissingSaml(stillMissingAfterRetry); - return false; - } + const stillMissingAfterRetry = await retrySamlAuth(stillMissing); + // Accept partial success - if some repositories now have access, continue + if (stillMissingAfterRetry.length < stillMissing.length) { + cleanUpMissingSaml(stillMissingAfterRetry); + return false; } } cleanUpMissingSaml(stillMissing);