Fix mission not loading when accessed via URL before authentication

When loading a mission via URL param (?mission=...), the initial API
fetch would fail with 401 before the user authenticated. After login,
nothing triggered a re-fetch of the mission data.

Added auth retry mechanism:
- Add signalAuthSuccess() to dispatch event after successful login
- Add authRetryTrigger state and listener in control-client
- Re-fetch mission and providers when auth succeeds
This commit is contained in:
Thomas Marchand
2026-01-03 08:33:31 +00:00
parent 2c9e18045f
commit e44c0d00a3
3 changed files with 26 additions and 6 deletions

View File

@@ -864,7 +864,18 @@ export default function ControlClient() {
});
}, []);
// Load mission from URL param on mount
// Load mission from URL param on mount (and retry on auth success)
const [authRetryTrigger, setAuthRetryTrigger] = useState(0);
// Listen for auth success to retry loading
useEffect(() => {
const onAuthSuccess = () => {
setAuthRetryTrigger((prev) => prev + 1);
};
window.addEventListener("openagent:auth:success", onAuthSuccess);
return () => window.removeEventListener("openagent:auth:success", onAuthSuccess);
}, []);
useEffect(() => {
const missionId = searchParams.get("mission");
if (missionId) {
@@ -877,7 +888,10 @@ export default function ControlClient() {
})
.catch((err) => {
console.error("Failed to load mission:", err);
toast.error("Failed to load mission");
// Only show error toast if this wasn't due to auth (authRetryTrigger > 0 means we already retried)
if (authRetryTrigger > 0) {
toast.error("Failed to load mission");
}
})
.finally(() => setMissionLoading(false));
} else {
@@ -893,7 +907,7 @@ export default function ControlClient() {
console.error("Failed to get current mission:", err);
});
}
}, [searchParams, router, missionHistoryToItems]);
}, [searchParams, router, missionHistoryToItems, authRetryTrigger]);
// Poll for running parallel missions
useEffect(() => {
@@ -916,7 +930,7 @@ export default function ControlClient() {
return () => clearInterval(interval);
}, []);
// Fetch available providers and models for mission creation
// Fetch available providers and models for mission creation (retry on auth success)
useEffect(() => {
listProviders()
.then((data) => {
@@ -925,7 +939,7 @@ export default function ControlClient() {
.catch((err) => {
console.error("Failed to fetch providers:", err);
});
}, []);
}, [authRetryTrigger]);
// Fetch server configuration (max_iterations) from health endpoint
useEffect(() => {

View File

@@ -2,7 +2,7 @@
import { useEffect, useMemo, useState } from 'react';
import { login, getHealth } from '@/lib/api';
import { clearJwt, getValidJwt, setJwt } from '@/lib/auth';
import { clearJwt, getValidJwt, setJwt, signalAuthSuccess } from '@/lib/auth';
import { Lock } from 'lucide-react';
export function AuthGate({ children }: { children: React.ReactNode }) {
@@ -61,6 +61,7 @@ export function AuthGate({ children }: { children: React.ReactNode }) {
setJwt(res.token, res.exp);
setIsAuthed(true);
setPassword('');
signalAuthSuccess();
} catch {
setError('Invalid password');
} finally {

View File

@@ -50,3 +50,8 @@ export function signalAuthRequired(): void {
if (typeof window === 'undefined') return;
window.dispatchEvent(new CustomEvent('openagent:auth:required'));
}
export function signalAuthSuccess(): void {
if (typeof window === 'undefined') return;
window.dispatchEvent(new CustomEvent('openagent:auth:success'));
}