fix: prevent repeated 404 errors when accessing deleted sessions (#5644)
Signed-off-by: sheikhlimon <sheikhlimon404@gmail.com>
This commit is contained in:
@@ -62,12 +62,58 @@ export default function Pair({
|
|||||||
return prev;
|
return prev;
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.error('Agent initialization failed:', error);
|
||||||
setFatalError(`Agent init failure: ${error instanceof Error ? error.message : '' + error}`);
|
|
||||||
|
// Clear deleted session from URL and retry
|
||||||
|
if (
|
||||||
|
error instanceof Error &&
|
||||||
|
(error.message.includes('Session not found') || error.message.includes('404'))
|
||||||
|
) {
|
||||||
|
console.log('Clearing invalid session ID from URL');
|
||||||
|
setSearchParams((prev) => {
|
||||||
|
prev.delete('resumeSessionId');
|
||||||
|
return prev;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const chat = await loadCurrentChat({
|
||||||
|
setAgentWaitingMessage,
|
||||||
|
});
|
||||||
|
setChat(chat);
|
||||||
|
setSearchParams((prev) => {
|
||||||
|
prev.set('resumeSessionId', chat.sessionId);
|
||||||
|
return prev;
|
||||||
|
});
|
||||||
|
} catch (retryError) {
|
||||||
|
handleInitializationError(retryError);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handleInitializationError(error);
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setLoadingChat(false);
|
setLoadingChat(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleInitializationError = (error: unknown) => {
|
||||||
|
let errorMessage = 'Unknown error occurred';
|
||||||
|
if (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
errorMessage = error.message;
|
||||||
|
} else if (typeof error === 'object' && error !== null) {
|
||||||
|
// Handle case where error is an object with properties
|
||||||
|
try {
|
||||||
|
errorMessage = JSON.stringify(error);
|
||||||
|
} catch {
|
||||||
|
errorMessage = Object.prototype.toString.call(error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errorMessage = String(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setFatalError(`Agent init failure: ${errorMessage}`);
|
||||||
|
};
|
||||||
|
|
||||||
initializeFromState();
|
initializeFromState();
|
||||||
}, [
|
}, [
|
||||||
agentState,
|
agentState,
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export function useAgent(): UseAgentReturn {
|
|||||||
const [agentState, setAgentState] = useState<AgentState>(AgentState.UNINITIALIZED);
|
const [agentState, setAgentState] = useState<AgentState>(AgentState.UNINITIALIZED);
|
||||||
const [sessionId, setSessionId] = useState<string | null>(null);
|
const [sessionId, setSessionId] = useState<string | null>(null);
|
||||||
const initPromiseRef = useRef<Promise<ChatType> | null>(null);
|
const initPromiseRef = useRef<Promise<ChatType> | null>(null);
|
||||||
|
const deletedSessionsRef = useRef<Set<string>>(new Set());
|
||||||
const recipeIdFromConfig = useRef<string | null>(
|
const recipeIdFromConfig = useRef<string | null>(
|
||||||
(window.appConfig.get('recipeId') as string | null | undefined) ?? null
|
(window.appConfig.get('recipeId') as string | null | undefined) ?? null
|
||||||
);
|
);
|
||||||
@@ -64,20 +65,54 @@ export function useAgent(): UseAgentReturn {
|
|||||||
recipeIdFromConfig.current = null;
|
recipeIdFromConfig.current = null;
|
||||||
recipeDeeplinkFromConfig.current = null;
|
recipeDeeplinkFromConfig.current = null;
|
||||||
scheduledJobIdFromConfig.current = null;
|
scheduledJobIdFromConfig.current = null;
|
||||||
|
deletedSessionsRef.current.clear();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const agentIsInitialized = agentState === AgentState.INITIALIZED;
|
const agentIsInitialized = agentState === AgentState.INITIALIZED;
|
||||||
const currentChat = useCallback(
|
const currentChat = useCallback(
|
||||||
async (initContext: InitializationContext): Promise<ChatType> => {
|
async (initContext: InitializationContext): Promise<ChatType> => {
|
||||||
if (agentIsInitialized && sessionId) {
|
// Skip deleted sessions
|
||||||
const agentResponse = await resumeAgent({
|
if (
|
||||||
|
initContext.resumeSessionId &&
|
||||||
|
deletedSessionsRef.current.has(initContext.resumeSessionId)
|
||||||
|
) {
|
||||||
|
initContext.resumeSessionId = undefined;
|
||||||
|
|
||||||
|
// Clear from URL
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
url.searchParams.delete('resumeSessionId');
|
||||||
|
window.history.replaceState({}, '', url.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sessionId && deletedSessionsRef.current.has(sessionId)) {
|
||||||
|
setSessionId(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (agentIsInitialized && sessionId && !deletedSessionsRef.current.has(sessionId)) {
|
||||||
|
let agentResponse;
|
||||||
|
try {
|
||||||
|
agentResponse = await resumeAgent({
|
||||||
body: {
|
body: {
|
||||||
session_id: sessionId,
|
session_id: sessionId,
|
||||||
load_model_and_extensions: false,
|
load_model_and_extensions: false,
|
||||||
},
|
},
|
||||||
throwOnError: true,
|
throwOnError: true,
|
||||||
});
|
});
|
||||||
|
} catch {
|
||||||
|
// Mark session as deleted and clear state
|
||||||
|
deletedSessionsRef.current.add(sessionId);
|
||||||
|
setSessionId(null);
|
||||||
|
|
||||||
|
// Clear from URL
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
if (url.searchParams.get('resumeSessionId')) {
|
||||||
|
url.searchParams.delete('resumeSessionId');
|
||||||
|
window.history.replaceState({}, '', url.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall through to create new session
|
||||||
|
if (agentResponse?.data) {
|
||||||
const agentSession = agentResponse.data;
|
const agentSession = agentResponse.data;
|
||||||
const messages = agentSession.conversation || [];
|
const messages = agentSession.conversation || [];
|
||||||
return {
|
return {
|
||||||
@@ -89,6 +124,7 @@ export function useAgent(): UseAgentReturn {
|
|||||||
recipeParameterValues: agentSession.user_recipe_values || null,
|
recipeParameterValues: agentSession.user_recipe_values || null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (initPromiseRef.current) {
|
if (initPromiseRef.current) {
|
||||||
return initPromiseRef.current;
|
return initPromiseRef.current;
|
||||||
@@ -109,7 +145,9 @@ export function useAgent(): UseAgentReturn {
|
|||||||
throw new NoProviderOrModelError();
|
throw new NoProviderOrModelError();
|
||||||
}
|
}
|
||||||
|
|
||||||
const agentResponse = initContext.resumeSessionId
|
let agentResponse;
|
||||||
|
try {
|
||||||
|
agentResponse = initContext.resumeSessionId
|
||||||
? await resumeAgent({
|
? await resumeAgent({
|
||||||
body: {
|
body: {
|
||||||
session_id: initContext.resumeSessionId,
|
session_id: initContext.resumeSessionId,
|
||||||
@@ -128,6 +166,34 @@ export function useAgent(): UseAgentReturn {
|
|||||||
},
|
},
|
||||||
throwOnError: true,
|
throwOnError: true,
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// If resuming fails, mark session as deleted and create new agent
|
||||||
|
if (initContext.resumeSessionId) {
|
||||||
|
deletedSessionsRef.current.add(initContext.resumeSessionId);
|
||||||
|
|
||||||
|
// Clear from URL
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
url.searchParams.delete('resumeSessionId');
|
||||||
|
window.history.replaceState({}, '', url.toString());
|
||||||
|
|
||||||
|
agentResponse = await startAgent({
|
||||||
|
body: {
|
||||||
|
working_dir: window.appConfig.get('GOOSE_WORKING_DIR') as string,
|
||||||
|
...buildRecipeInput(
|
||||||
|
initContext.recipe,
|
||||||
|
recipeIdFromConfig.current,
|
||||||
|
recipeDeeplinkFromConfig.current
|
||||||
|
),
|
||||||
|
},
|
||||||
|
throwOnError: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear resume flag
|
||||||
|
initContext.resumeSessionId = undefined;
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const agentSession = agentResponse.data;
|
const agentSession = agentResponse.data;
|
||||||
if (!agentSession) {
|
if (!agentSession) {
|
||||||
|
|||||||
Reference in New Issue
Block a user