mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-28 00:18:25 -05:00
fix: address remaining review feedback
Backend: - Make invalidate_session_cache best-effort with try-except Frontend: - Fix polling bug: use recursive scheduling so polling continues after each refetch - Add toolName fallback in helpers.ts parseToolResponse for operation_* types - Make PendingOperationWidget title dynamic based on toolName instead of hardcoded "Creating Agent"
This commit is contained in:
@@ -299,10 +299,15 @@ async def invalidate_session_cache(session_id: str) -> None:
|
||||
"""Invalidate a chat session from Redis cache.
|
||||
|
||||
Used by background tasks to ensure fresh data is loaded on next access.
|
||||
This is best-effort - Redis failures are logged but don't fail the operation.
|
||||
"""
|
||||
redis_key = _get_session_cache_key(session_id)
|
||||
async_redis = await get_redis_async()
|
||||
await async_redis.delete(redis_key)
|
||||
try:
|
||||
redis_key = _get_session_cache_key(session_id)
|
||||
async_redis = await get_redis_async()
|
||||
await async_redis.delete(redis_key)
|
||||
except Exception as e:
|
||||
# Best-effort: log but don't fail - cache will expire naturally
|
||||
logger.warning(f"Failed to invalidate session cache for {session_id}: {e}")
|
||||
|
||||
|
||||
async def _get_session_from_db(session_id: str) -> ChatSession | None:
|
||||
|
||||
@@ -344,7 +344,7 @@ export function parseToolResponse(
|
||||
if (responseType === "operation_started") {
|
||||
return {
|
||||
type: "operation_started",
|
||||
toolName: parsedResult.tool_name as string,
|
||||
toolName: (parsedResult.tool_name as string) || toolName,
|
||||
operationId: (parsedResult.operation_id as string) || "",
|
||||
message:
|
||||
(parsedResult.message as string) ||
|
||||
@@ -355,7 +355,7 @@ export function parseToolResponse(
|
||||
if (responseType === "operation_pending") {
|
||||
return {
|
||||
type: "operation_pending",
|
||||
toolName: parsedResult.tool_name as string,
|
||||
toolName: (parsedResult.tool_name as string) || toolName,
|
||||
operationId: (parsedResult.operation_id as string) || "",
|
||||
message:
|
||||
(parsedResult.message as string) ||
|
||||
@@ -366,7 +366,7 @@ export function parseToolResponse(
|
||||
if (responseType === "operation_in_progress") {
|
||||
return {
|
||||
type: "operation_in_progress",
|
||||
toolName: parsedResult.tool_name as string,
|
||||
toolName: (parsedResult.tool_name as string) || toolName,
|
||||
toolCallId: (parsedResult.tool_call_id as string) || "",
|
||||
message:
|
||||
(parsedResult.message as string) ||
|
||||
|
||||
@@ -19,6 +19,19 @@ interface Props {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function getOperationTitle(toolName?: string): string {
|
||||
if (!toolName) return "Operation";
|
||||
// Convert tool name to human-readable format
|
||||
// e.g., "create_agent" -> "Creating Agent", "edit_agent" -> "Editing Agent"
|
||||
if (toolName === "create_agent") return "Creating Agent";
|
||||
if (toolName === "edit_agent") return "Editing Agent";
|
||||
// Default: capitalize and format tool name
|
||||
return toolName
|
||||
.split("_")
|
||||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
export function PendingOperationWidget({
|
||||
status,
|
||||
message,
|
||||
@@ -30,6 +43,8 @@ export function PendingOperationWidget({
|
||||
const isCompleted = status === "completed";
|
||||
const isError = status === "error";
|
||||
|
||||
const operationTitle = getOperationTitle(toolName);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
@@ -66,9 +81,9 @@ export function PendingOperationWidget({
|
||||
<Card className="space-y-2 p-4">
|
||||
<div>
|
||||
<Text variant="h4" className="mb-1 text-slate-900">
|
||||
{isPending && "Creating Agent"}
|
||||
{isCompleted && "Operation Complete"}
|
||||
{isError && "Operation Failed"}
|
||||
{isPending && operationTitle}
|
||||
{isCompleted && `${operationTitle} Complete`}
|
||||
{isError && `${operationTitle} Failed`}
|
||||
</Text>
|
||||
<Text variant="small" className="text-slate-600">
|
||||
{message}
|
||||
|
||||
@@ -132,6 +132,9 @@ export function useChatSession({
|
||||
|
||||
// Poll for updates when there are pending operations (long poll - 10s intervals with backoff)
|
||||
const pollAttemptRef = useRef(0);
|
||||
const hasPendingOperationsRef = useRef(hasPendingOperations);
|
||||
hasPendingOperationsRef.current = hasPendingOperations;
|
||||
|
||||
useEffect(
|
||||
function pollForPendingOperations() {
|
||||
if (!sessionId || !hasPendingOperations) {
|
||||
@@ -139,27 +142,43 @@ export function useChatSession({
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
// Calculate delay with exponential backoff: 10s, 15s, 20s, 25s, 30s (max)
|
||||
const baseDelay = 10000;
|
||||
const maxDelay = 30000;
|
||||
const delay = Math.min(
|
||||
baseDelay + pollAttemptRef.current * 5000,
|
||||
maxDelay,
|
||||
);
|
||||
|
||||
const timeoutId = setTimeout(async () => {
|
||||
console.info(
|
||||
`[useChatSession] Polling for pending operation updates (attempt ${pollAttemptRef.current + 1})`,
|
||||
function schedule() {
|
||||
const delay = Math.min(
|
||||
baseDelay + pollAttemptRef.current * 5000,
|
||||
maxDelay,
|
||||
);
|
||||
pollAttemptRef.current += 1;
|
||||
try {
|
||||
await refetch();
|
||||
} catch (err) {
|
||||
console.error("[useChatSession] Poll failed:", err);
|
||||
}
|
||||
}, delay);
|
||||
timeoutId = setTimeout(async () => {
|
||||
if (cancelled) return;
|
||||
console.info(
|
||||
`[useChatSession] Polling for pending operation updates (attempt ${pollAttemptRef.current + 1})`,
|
||||
);
|
||||
pollAttemptRef.current += 1;
|
||||
try {
|
||||
await refetch();
|
||||
} catch (err) {
|
||||
console.error("[useChatSession] Poll failed:", err);
|
||||
} finally {
|
||||
// Continue polling if still pending and not cancelled
|
||||
if (!cancelled && hasPendingOperationsRef.current) {
|
||||
schedule();
|
||||
}
|
||||
}
|
||||
}, delay);
|
||||
}
|
||||
|
||||
return () => clearTimeout(timeoutId);
|
||||
schedule();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
if (timeoutId) clearTimeout(timeoutId);
|
||||
};
|
||||
},
|
||||
[sessionId, hasPendingOperations, refetch],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user