Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
97db7c9
feat: extract shared OAuth utilities from service files
Feb 7, 2026
60a8075
refactor(copilot): use shared createDeferred from oauthUtils
Feb 7, 2026
f091a65
refactor: use shared OAuth utilities in muxGatewayOauthService
Feb 7, 2026
4b1ad3a
refactor: use shared OAuth utilities in muxGovernorOauthService
Feb 7, 2026
2999625
refactor(mcpOauthService): use shared OAuth utilities from oauthUtils
Feb 7, 2026
aabe338
refactor: use shared OAuth utilities in codexOauthService
Feb 7, 2026
60b6e3f
test: add unit tests for shared OAuth utility modules
Feb 7, 2026
d180551
style: format OAuth service files with prettier
Feb 7, 2026
5480bd9
fix: escape failure messages in OAuth callback HTML + add start-time …
Feb 7, 2026
ba8d6ce
πŸ€– fix: make Governor OAuth callback cancellation-aware
Feb 7, 2026
98e5792
πŸ€– fix: defer OAuth loopback success page until exchange completes
Feb 7, 2026
cb4c306
fix: suppress empty-function lint in test timeout stub
Feb 7, 2026
ebb6050
docs: clarify OAuthFlowManager waitFor timeout docs
Feb 7, 2026
991c975
test: add desktop OAuth service coverage for gateway and governor
Feb 7, 2026
0f1009c
πŸ€– tests: fix oauth service test static-check issues
Feb 7, 2026
08722e3
πŸ€– tests: reduce OAuth pending timeout flakiness
Feb 8, 2026
c8030ed
fix: keep completed OAuth flows for TTL
Feb 8, 2026
9201fbd
fix: ignore invalid OAuth state callbacks in loopback server
Feb 8, 2026
f08ff2c
style: format oauthFlowManager tests
Feb 8, 2026
c167ecb
fix: device flow race condition β€” useEffect [api] dep causes spurious…
Feb 9, 2026
914ae25
fix(oauth): cancel stale Copilot flow + harden flow register
Feb 10, 2026
ebf95f1
tests(oauth): cover duplicate register + validateLoopback reject
Feb 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions src/browser/components/Settings/sections/ProvidersSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -836,14 +836,18 @@ export function ProvidersSection() {
setCopilotLoginError(null);
};

// Cancel any in-flight Copilot login if the component unmounts
// Cancel any in-flight Copilot login if the component unmounts.
// Use a ref for api so this only fires on true unmount, not on api identity
// changes (e.g. reconnection), which would spuriously cancel active flows.
const apiRef = useRef(api);
apiRef.current = api;
useEffect(() => {
return () => {
if (copilotFlowIdRef.current && api) {
void api.copilotOauth.cancelDeviceFlow({ flowId: copilotFlowIdRef.current });
if (copilotFlowIdRef.current && apiRef.current) {
void apiRef.current.copilotOauth.cancelDeviceFlow({ flowId: copilotFlowIdRef.current });
}
};
}, [api]);
}, []);

const clearCopilotCredentials = () => {
if (!api) return;
Expand All @@ -868,9 +872,21 @@ export function ProvidersSection() {
return;
}

// Best-effort: cancel any in-progress flow before starting a new one.
if (copilotFlowIdRef.current) {
void api.copilotOauth.cancelDeviceFlow({ flowId: copilotFlowIdRef.current });
copilotFlowIdRef.current = null;
setCopilotFlowId(null);
}

const startResult = await api.copilotOauth.startDeviceFlow();

if (attempt !== copilotLoginAttemptRef.current) return;
if (attempt !== copilotLoginAttemptRef.current) {
if (startResult.success) {
void api.copilotOauth.cancelDeviceFlow({ flowId: startResult.data.flowId });
}
return;
}

if (!startResult.success) {
setCopilotLoginStatus("error");
Expand Down
Loading
Loading