mirror of https://github.com/kortix-ai/suna.git
load thread page no-side-panel skeleton fix
This commit is contained in:
parent
9a5bcd00a7
commit
6bffd6d2c4
|
@ -40,7 +40,7 @@ MODEL_NAME_ALIASES = {
|
||||||
"gpt-4": "openai/gpt-4",
|
"gpt-4": "openai/gpt-4",
|
||||||
"gemini-flash-2.5": "openrouter/google/gemini-2.5-flash-preview",
|
"gemini-flash-2.5": "openrouter/google/gemini-2.5-flash-preview",
|
||||||
"grok-3": "xai/grok-3-fast-latest",
|
"grok-3": "xai/grok-3-fast-latest",
|
||||||
"deepseek": "deepseek/deepseek-chat",
|
"deepseek": "openrouter/deepseek/deepseek-chat",
|
||||||
"grok-3-mini": "xai/grok-3-mini-fast-beta",
|
"grok-3-mini": "xai/grok-3-mini-fast-beta",
|
||||||
"qwen3": "openrouter/qwen/qwen3-235b-a22b",
|
"qwen3": "openrouter/qwen/qwen3-235b-a22b",
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ MODEL_NAME_ALIASES = {
|
||||||
"openai/gpt-4": "openai/gpt-4",
|
"openai/gpt-4": "openai/gpt-4",
|
||||||
"openrouter/google/gemini-2.5-flash-preview": "openrouter/google/gemini-2.5-flash-preview",
|
"openrouter/google/gemini-2.5-flash-preview": "openrouter/google/gemini-2.5-flash-preview",
|
||||||
"xai/grok-3-fast-latest": "xai/grok-3-fast-latest",
|
"xai/grok-3-fast-latest": "xai/grok-3-fast-latest",
|
||||||
"deepseek/deepseek-chat": "deepseek/deepseek-chat",
|
"deepseek/deepseek-chat": "openrouter/deepseek/deepseek-chat",
|
||||||
"xai/grok-3-mini-fast-beta": "xai/grok-3-mini-fast-beta",
|
"xai/grok-3-mini-fast-beta": "xai/grok-3-mini-fast-beta",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1370,7 +1370,7 @@ export default function ThreadPage({
|
||||||
return (
|
return (
|
||||||
<div className="flex h-screen">
|
<div className="flex h-screen">
|
||||||
<div
|
<div
|
||||||
className={`flex flex-col flex-1 overflow-hidden transition-all duration-200 ease-in-out ${isSidePanelOpen ? 'mr-[90%] sm:mr-[450px] md:mr-[500px] lg:mr-[550px] xl:mr-[650px]' : ''}`}
|
className={`flex flex-col flex-1 overflow-hidden transition-all duration-200 ease-in-out`}
|
||||||
>
|
>
|
||||||
{/* Skeleton Header */}
|
{/* Skeleton Header */}
|
||||||
<div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
<div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
||||||
|
@ -1465,16 +1465,7 @@ export default function ThreadPage({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Skeleton Side Panel (closed state) */}
|
{/* Skeleton Side Panel (hidden during loading) */}
|
||||||
<div className={`hidden ${isSidePanelOpen ? 'block' : ''}`}>
|
|
||||||
<div className="h-screen w-[450px] border-l">
|
|
||||||
<div className="p-4">
|
|
||||||
<Skeleton className="h-8 w-32 mb-4" />
|
|
||||||
<Skeleton className="h-20 w-full rounded-md mb-4" />
|
|
||||||
<Skeleton className="h-40 w-full rounded-md" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1483,7 +1474,7 @@ export default function ThreadPage({
|
||||||
return (
|
return (
|
||||||
<div className="flex h-screen">
|
<div className="flex h-screen">
|
||||||
<div
|
<div
|
||||||
className={`flex flex-col flex-1 overflow-hidden transition-all duration-200 ease-in-out ${isSidePanelOpen ? 'mr-[90%] sm:mr-[450px] md:mr-[500px] lg:mr-[550px] xl:mr-[650px]' : ''}`}
|
className={`flex flex-col flex-1 overflow-hidden transition-all duration-200 ease-in-out ${(isSidePanelOpen && initialLoadCompleted.current) ? 'mr-[90%] sm:mr-[450px] md:mr-[500px] lg:mr-[550px] xl:mr-[650px]' : ''}`}
|
||||||
>
|
>
|
||||||
<SiteHeader
|
<SiteHeader
|
||||||
threadId={threadId}
|
threadId={threadId}
|
||||||
|
@ -1512,13 +1503,14 @@ export default function ThreadPage({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ToolCallSidePanel
|
<ToolCallSidePanel
|
||||||
isOpen={isSidePanelOpen}
|
isOpen={isSidePanelOpen && initialLoadCompleted.current}
|
||||||
onClose={() => setIsSidePanelOpen(false)}
|
onClose={() => setIsSidePanelOpen(false)}
|
||||||
toolCalls={[]}
|
toolCalls={[]}
|
||||||
currentIndex={0}
|
currentIndex={0}
|
||||||
onNavigate={handleSidePanelNavigate}
|
onNavigate={handleSidePanelNavigate}
|
||||||
project={project || undefined}
|
project={project || undefined}
|
||||||
agentStatus="error"
|
agentStatus="error"
|
||||||
|
isLoading={!initialLoadCompleted.current || isLoading}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1527,7 +1519,7 @@ export default function ThreadPage({
|
||||||
return (
|
return (
|
||||||
<div className="flex h-screen">
|
<div className="flex h-screen">
|
||||||
<div
|
<div
|
||||||
className={`flex flex-col flex-1 overflow-hidden transition-all duration-200 ease-in-out ${isSidePanelOpen ? 'mr-[90%] sm:mr-[450px] md:mr-[500px] lg:mr-[550px] xl:mr-[650px]' : ''}`}
|
className={`flex flex-col flex-1 overflow-hidden transition-all duration-200 ease-in-out ${(!initialLoadCompleted.current || isSidePanelOpen) ? 'mr-[90%] sm:mr-[450px] md:mr-[500px] lg:mr-[550px] xl:mr-[650px]' : ''}`}
|
||||||
>
|
>
|
||||||
<SiteHeader
|
<SiteHeader
|
||||||
threadId={threadId}
|
threadId={threadId}
|
||||||
|
@ -1935,7 +1927,7 @@ export default function ThreadPage({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ToolCallSidePanel
|
<ToolCallSidePanel
|
||||||
isOpen={isSidePanelOpen}
|
isOpen={isSidePanelOpen && initialLoadCompleted.current}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setIsSidePanelOpen(false);
|
setIsSidePanelOpen(false);
|
||||||
userClosedPanelRef.current = true;
|
userClosedPanelRef.current = true;
|
||||||
|
@ -1949,6 +1941,7 @@ export default function ThreadPage({
|
||||||
project={project || undefined}
|
project={project || undefined}
|
||||||
renderAssistantMessage={toolViewAssistant}
|
renderAssistantMessage={toolViewAssistant}
|
||||||
renderToolResult={toolViewResult}
|
renderToolResult={toolViewResult}
|
||||||
|
isLoading={!initialLoadCompleted.current || isLoading}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{sandboxId && (
|
{sandboxId && (
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { Project } from '@/lib/api';
|
||||||
import { getToolIcon } from '@/components/thread/utils';
|
import { getToolIcon } from '@/components/thread/utils';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Slider } from '@/components/ui/slider';
|
import { Slider } from '@/components/ui/slider';
|
||||||
|
import { Skeleton } from '@/components/ui/skeleton';
|
||||||
import { ApiMessageType } from '@/components/thread/types';
|
import { ApiMessageType } from '@/components/thread/types';
|
||||||
import { CircleDashed, X, ChevronLeft, ChevronRight } from 'lucide-react';
|
import { CircleDashed, X, ChevronLeft, ChevronRight } from 'lucide-react';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
@ -217,6 +218,7 @@ interface ToolCallSidePanelProps {
|
||||||
toolContent?: string,
|
toolContent?: string,
|
||||||
isSuccess?: boolean,
|
isSuccess?: boolean,
|
||||||
) => React.ReactNode;
|
) => React.ReactNode;
|
||||||
|
isLoading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ToolCallSidePanel({
|
export function ToolCallSidePanel({
|
||||||
|
@ -230,6 +232,7 @@ export function ToolCallSidePanel({
|
||||||
project,
|
project,
|
||||||
renderAssistantMessage,
|
renderAssistantMessage,
|
||||||
renderToolResult,
|
renderToolResult,
|
||||||
|
isLoading = false,
|
||||||
}: ToolCallSidePanelProps) {
|
}: ToolCallSidePanelProps) {
|
||||||
// Move hooks outside of conditional
|
// Move hooks outside of conditional
|
||||||
const [dots, setDots] = React.useState('');
|
const [dots, setDots] = React.useState('');
|
||||||
|
@ -308,6 +311,50 @@ export function ToolCallSidePanel({
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null;
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
'fixed inset-y-0 right-0 border-l flex flex-col z-30 h-screen transition-all duration-200 ease-in-out',
|
||||||
|
isMobile
|
||||||
|
? 'w-full'
|
||||||
|
: 'w-[90%] sm:w-[450px] md:w-[500px] lg:w-[550px] xl:w-[650px]',
|
||||||
|
!isOpen && 'translate-x-full',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="flex-1 flex flex-col overflow-hidden bg-background">
|
||||||
|
<div className="flex flex-col h-full">
|
||||||
|
<div className="pt-4 pl-4 pr-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<h2 className="text-lg font-medium text-zinc-900 dark:text-zinc-100">
|
||||||
|
Suna's Computer
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
onClick={onClose}
|
||||||
|
className="h-8 w-8"
|
||||||
|
>
|
||||||
|
<X className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 p-4 overflow-auto">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<Skeleton className="h-8 w-32" />
|
||||||
|
<Skeleton className="h-20 w-full rounded-md" />
|
||||||
|
<Skeleton className="h-40 w-full rounded-md" />
|
||||||
|
<Skeleton className="h-20 w-full rounded-md" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const renderContent = () => {
|
const renderContent = () => {
|
||||||
if (!currentToolCall) {
|
if (!currentToolCall) {
|
||||||
return (
|
return (
|
||||||
|
|
Loading…
Reference in New Issue