mirror of
https://github.com/block/goose.git
synced 2026-07-17 12:56:20 +02:00
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;
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
setFatalError(`Agent init failure: ${error instanceof Error ? error.message : '' + error}`);
|
||||
console.error('Agent initialization failed:', 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 {
|
||||
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();
|
||||
}, [
|
||||
agentState,
|
||||
|
||||
@@ -47,6 +47,7 @@ export function useAgent(): UseAgentReturn {
|
||||
const [agentState, setAgentState] = useState<AgentState>(AgentState.UNINITIALIZED);
|
||||
const [sessionId, setSessionId] = useState<string | null>(null);
|
||||
const initPromiseRef = useRef<Promise<ChatType> | null>(null);
|
||||
const deletedSessionsRef = useRef<Set<string>>(new Set());
|
||||
const recipeIdFromConfig = useRef<string | null>(
|
||||
(window.appConfig.get('recipeId') as string | null | undefined) ?? null
|
||||
);
|
||||
@@ -64,30 +65,65 @@ export function useAgent(): UseAgentReturn {
|
||||
recipeIdFromConfig.current = null;
|
||||
recipeDeeplinkFromConfig.current = null;
|
||||
scheduledJobIdFromConfig.current = null;
|
||||
deletedSessionsRef.current.clear();
|
||||
}, []);
|
||||
|
||||
const agentIsInitialized = agentState === AgentState.INITIALIZED;
|
||||
const currentChat = useCallback(
|
||||
async (initContext: InitializationContext): Promise<ChatType> => {
|
||||
if (agentIsInitialized && sessionId) {
|
||||
const agentResponse = await resumeAgent({
|
||||
body: {
|
||||
session_id: sessionId,
|
||||
load_model_and_extensions: false,
|
||||
},
|
||||
throwOnError: true,
|
||||
});
|
||||
// Skip deleted sessions
|
||||
if (
|
||||
initContext.resumeSessionId &&
|
||||
deletedSessionsRef.current.has(initContext.resumeSessionId)
|
||||
) {
|
||||
initContext.resumeSessionId = undefined;
|
||||
|
||||
const agentSession = agentResponse.data;
|
||||
const messages = agentSession.conversation || [];
|
||||
return {
|
||||
sessionId: agentSession.id,
|
||||
name: agentSession.recipe?.title || agentSession.name,
|
||||
messageHistoryIndex: 0,
|
||||
messages,
|
||||
recipe: agentSession.recipe,
|
||||
recipeParameterValues: agentSession.user_recipe_values || null,
|
||||
};
|
||||
// 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: {
|
||||
session_id: sessionId,
|
||||
load_model_and_extensions: false,
|
||||
},
|
||||
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 messages = agentSession.conversation || [];
|
||||
return {
|
||||
sessionId: agentSession.id,
|
||||
name: agentSession.recipe?.title || agentSession.name,
|
||||
messageHistoryIndex: 0,
|
||||
messages,
|
||||
recipe: agentSession.recipe,
|
||||
recipeParameterValues: agentSession.user_recipe_values || null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (initPromiseRef.current) {
|
||||
@@ -109,15 +145,38 @@ export function useAgent(): UseAgentReturn {
|
||||
throw new NoProviderOrModelError();
|
||||
}
|
||||
|
||||
const agentResponse = initContext.resumeSessionId
|
||||
? await resumeAgent({
|
||||
body: {
|
||||
session_id: initContext.resumeSessionId,
|
||||
load_model_and_extensions: false,
|
||||
},
|
||||
throwOnError: true,
|
||||
})
|
||||
: await startAgent({
|
||||
let agentResponse;
|
||||
try {
|
||||
agentResponse = initContext.resumeSessionId
|
||||
? await resumeAgent({
|
||||
body: {
|
||||
session_id: initContext.resumeSessionId,
|
||||
load_model_and_extensions: false,
|
||||
},
|
||||
throwOnError: true,
|
||||
})
|
||||
: await startAgent({
|
||||
body: {
|
||||
working_dir: window.appConfig.get('GOOSE_WORKING_DIR') as string,
|
||||
...buildRecipeInput(
|
||||
initContext.recipe,
|
||||
recipeIdFromConfig.current,
|
||||
recipeDeeplinkFromConfig.current
|
||||
),
|
||||
},
|
||||
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(
|
||||
@@ -129,6 +188,13 @@ export function useAgent(): UseAgentReturn {
|
||||
throwOnError: true,
|
||||
});
|
||||
|
||||
// Clear resume flag
|
||||
initContext.resumeSessionId = undefined;
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const agentSession = agentResponse.data;
|
||||
if (!agentSession) {
|
||||
throw Error('Failed to get session info');
|
||||
|
||||
Reference in New Issue
Block a user