mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
fix(otto): prevent breaking when failing to make api call (#9613)
These are some tweaks for Otto to try prevent the frontend from breaking when/if it fails to make the otto api call. ### Changes 🏗️ Removed unused reference to ``OTTO_API_URL`` in [backend/server/v2/otto/routes.py](https://github.com/Significant-Gravitas/AutoGPT/compare/dev...otto-fixes?expand=1#diff-6545b2ed01d619cc095b8d0ca6d5baa86d1448dc970cff508669ec3430675d28) Removed un-needed ``revalidatePath("/build");`` from [frontend/src/app/build/actions.ts](https://github.com/Significant-Gravitas/AutoGPT/compare/dev...otto-fixes?expand=1#diff-6861f6b90ce91138b3821c0a82abfffbc09f425c26b7335fac60f54894e353e9) Added a 60 second timeout to the api call in [backend/server/v2/otto/service.py](https://github.com/Significant-Gravitas/AutoGPT/compare/dev...otto-fixes?expand=1#diff-63c9a1a5337cd5e4ddec7544a258916d4998a6cb5c4181f621d7e24f654bd5c8) Added a better error handler in [frontend/src/components/OttoChatWidget.tsx](https://github.com/Significant-Gravitas/AutoGPT/compare/dev...otto-fixes?expand=1#diff-7351568d5c588b77f35d80994ca6800a7faa1b3b0ca229970cfa491eab4b4b33) Made it so errors return a structured error response for better handling in [frontend/src/app/build/actions.ts](https://github.com/Significant-Gravitas/AutoGPT/compare/dev...otto-fixes?expand=1#diff-6861f6b90ce91138b3821c0a82abfffbc09f425c26b7335fac60f54894e353e9) ### Checklist 📋 #### For code changes: - [x] I have clearly listed my changes in the PR description - [x] I have made a test plan - [x] I have tested my changes according to the test plan: <!-- Put your test plan here: --> - [x] do not set the ENV var for ``otto_api_url`` - [x] Set the ENV var for ``NEXT_PUBLIC_BEHAVE_AS`` to ``CLOUD`` to have the chat ui show in the build page - [x] Send otto a message from the build page frontend, it should fail and not break the frontend - [x] Send otto a message that contains graph data to see if the sending graph data works, this should also fail and not break the frontend - [x] now we set the ENV for ``otto_api_url`` - [x] Send otto a message from the build page frontend, it should work - [x] Send otto a message that contains graph data to see if the sending graph data works, it should work
This commit is contained in:
@@ -4,15 +4,11 @@ from autogpt_libs.auth.middleware import auth_middleware
|
||||
from fastapi import APIRouter, Depends
|
||||
|
||||
from backend.server.utils import get_user_id
|
||||
from backend.util.settings import Settings
|
||||
|
||||
from .models import ApiResponse, ChatRequest
|
||||
from .service import OttoService
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
settings = Settings()
|
||||
|
||||
OTTO_API_URL = settings.config.otto_api_url
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
@@ -67,6 +68,13 @@ class OttoService:
|
||||
"""
|
||||
Send request to Otto API and handle the response.
|
||||
"""
|
||||
# Check if Otto API URL is configured
|
||||
if not OTTO_API_URL:
|
||||
logger.error("Otto API URL is not configured")
|
||||
raise HTTPException(
|
||||
status_code=503, detail="Otto service is not configured"
|
||||
)
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
headers = {
|
||||
@@ -94,7 +102,10 @@ class OttoService:
|
||||
logger.debug(f"Request payload: {payload}")
|
||||
|
||||
async with session.post(
|
||||
OTTO_API_URL, json=payload, headers=headers
|
||||
OTTO_API_URL,
|
||||
json=payload,
|
||||
headers=headers,
|
||||
timeout=aiohttp.ClientTimeout(total=60),
|
||||
) as response:
|
||||
if response.status != 200:
|
||||
error_text = await response.text()
|
||||
@@ -115,6 +126,11 @@ class OttoService:
|
||||
raise HTTPException(
|
||||
status_code=503, detail="Failed to connect to Otto service"
|
||||
)
|
||||
except asyncio.TimeoutError:
|
||||
logger.error("Timeout error connecting to Otto API after 60 seconds")
|
||||
raise HTTPException(
|
||||
status_code=504, detail="Request to Otto service timed out"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error in Otto API proxy: {str(e)}")
|
||||
raise HTTPException(
|
||||
|
||||
@@ -24,10 +24,14 @@ export async function askOtto(
|
||||
|
||||
try {
|
||||
const response = await api.askOtto(ottoQuery);
|
||||
revalidatePath("/build");
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error("Error in askOtto server action:", error);
|
||||
throw error;
|
||||
return {
|
||||
answer: error instanceof Error ? error.message : "Unknown error occurred",
|
||||
documents: [],
|
||||
success: false,
|
||||
error: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,29 +56,30 @@ const OttoChatWidget = () => {
|
||||
// Add user message to chat
|
||||
setMessages((prev) => [...prev, { type: "user", content: userMessage }]);
|
||||
|
||||
// Add temporary processing message
|
||||
setMessages((prev) => [
|
||||
...prev,
|
||||
{ type: "assistant", content: "Processing your question..." },
|
||||
]);
|
||||
|
||||
const conversationHistory = messages.reduce<
|
||||
{ query: string; response: string }[]
|
||||
>((acc, msg, i, arr) => {
|
||||
if (
|
||||
msg.type === "user" &&
|
||||
i + 1 < arr.length &&
|
||||
arr[i + 1].type === "assistant" &&
|
||||
arr[i + 1].content !== "Processing your question..."
|
||||
) {
|
||||
acc.push({
|
||||
query: msg.content,
|
||||
response: arr[i + 1].content,
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
try {
|
||||
// Add temporary processing message
|
||||
setMessages((prev) => [
|
||||
...prev,
|
||||
{ type: "assistant", content: "Processing your question..." },
|
||||
]);
|
||||
|
||||
const conversationHistory = messages.reduce<
|
||||
{ query: string; response: string }[]
|
||||
>((acc, msg, i, arr) => {
|
||||
if (
|
||||
msg.type === "user" &&
|
||||
i + 1 < arr.length &&
|
||||
arr[i + 1].type === "assistant"
|
||||
) {
|
||||
acc.push({
|
||||
query: msg.content,
|
||||
response: arr[i + 1].content,
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
const data = await askOtto(
|
||||
userMessage,
|
||||
conversationHistory,
|
||||
@@ -86,34 +87,43 @@ const OttoChatWidget = () => {
|
||||
flowID || undefined,
|
||||
);
|
||||
|
||||
// Remove processing message and add actual response
|
||||
setMessages((prev) => [
|
||||
...prev.slice(0, -1),
|
||||
{ type: "assistant", content: data.answer },
|
||||
]);
|
||||
} catch (error) {
|
||||
console.error("Error calling API:", error);
|
||||
// Remove processing message and add error message
|
||||
const errorMessage =
|
||||
error instanceof Error && error.message === "Authentication required"
|
||||
? "Please sign in to use the chat feature."
|
||||
: "Sorry, there was an error processing your message. Please try again.";
|
||||
// Check if the response contains an error
|
||||
if ("error" in data && data.error === true) {
|
||||
// Handle different error types
|
||||
let errorMessage =
|
||||
"Sorry, there was an error processing your message. Please try again.";
|
||||
|
||||
setMessages((prev) => [
|
||||
...prev.slice(0, -1),
|
||||
{ type: "assistant", content: errorMessage },
|
||||
]);
|
||||
if (data.answer === "Authentication required") {
|
||||
errorMessage = "Please sign in to use the chat feature.";
|
||||
} else if (data.answer === "Failed to connect to Otto service") {
|
||||
errorMessage =
|
||||
"Otto service is currently unavailable. Please try again later.";
|
||||
} else if (data.answer.includes("timed out")) {
|
||||
errorMessage = "Request timed out. Please try again later.";
|
||||
}
|
||||
|
||||
if (
|
||||
error instanceof Error &&
|
||||
error.message === "Authentication required"
|
||||
) {
|
||||
toast({
|
||||
title: "Authentication Error",
|
||||
description: "Please sign in to use the chat feature.",
|
||||
variant: "destructive",
|
||||
});
|
||||
// Remove processing message and add error message
|
||||
setMessages((prev) => [
|
||||
...prev.slice(0, -1),
|
||||
{ type: "assistant", content: errorMessage },
|
||||
]);
|
||||
} else {
|
||||
// Remove processing message and add actual response
|
||||
setMessages((prev) => [
|
||||
...prev.slice(0, -1),
|
||||
{ type: "assistant", content: data.answer },
|
||||
]);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Unexpected error in chat widget:", error);
|
||||
setMessages((prev) => [
|
||||
...prev.slice(0, -1),
|
||||
{
|
||||
type: "assistant",
|
||||
content:
|
||||
"An unexpected error occurred. Please refresh the page and try again.",
|
||||
},
|
||||
]);
|
||||
} finally {
|
||||
setIsProcessing(false);
|
||||
setIncludeGraphData(false);
|
||||
|
||||
@@ -760,6 +760,7 @@ export interface OttoResponse {
|
||||
answer: string;
|
||||
documents: OttoDocument[];
|
||||
success: boolean;
|
||||
error: boolean;
|
||||
}
|
||||
|
||||
export interface OttoQuery {
|
||||
|
||||
Reference in New Issue
Block a user