chore(dev): show custom agent name on thread page

This commit is contained in:
Soumyadas15 2025-05-24 13:03:17 +05:30
parent beeaffb533
commit cb36e534b2
8 changed files with 357 additions and 214 deletions

View File

@ -72,6 +72,11 @@ class AgentResponse(BaseModel):
created_at: str created_at: str
updated_at: str updated_at: str
class ThreadAgentResponse(BaseModel):
agent: Optional[AgentResponse]
source: str # "thread", "default", "none", "missing"
message: str
def initialize( def initialize(
_thread_manager: ThreadManager, _thread_manager: ThreadManager,
_db: DBConnection, _db: DBConnection,
@ -401,6 +406,78 @@ async def get_agent_run(agent_run_id: str, user_id: str = Depends(get_current_us
"error": agent_run_data['error'] "error": agent_run_data['error']
} }
@router.get("/thread/{thread_id}/agent", response_model=ThreadAgentResponse)
async def get_thread_agent(thread_id: str, user_id: str = Depends(get_current_user_id_from_jwt)):
"""Get the agent details for a specific thread."""
logger.info(f"Fetching agent details for thread: {thread_id}")
client = await db.client
try:
# Verify thread access and get thread data including agent_id
await verify_thread_access(client, thread_id, user_id)
thread_result = await client.table('threads').select('agent_id', 'account_id').eq('thread_id', thread_id).execute()
if not thread_result.data:
raise HTTPException(status_code=404, detail="Thread not found")
thread_data = thread_result.data[0]
thread_agent_id = thread_data.get('agent_id')
account_id = thread_data.get('account_id')
# If no agent_id is set in the thread, try to get the default agent
effective_agent_id = thread_agent_id
agent_source = "thread"
if not effective_agent_id:
# No agent set in thread, get default agent for the account
default_agent_result = await client.table('agents').select('agent_id').eq('account_id', account_id).eq('is_default', True).execute()
if default_agent_result.data:
effective_agent_id = default_agent_result.data[0]['agent_id']
agent_source = "default"
else:
# No default agent found
return {
"agent": None,
"source": "none",
"message": "No agent configured for this thread"
}
# Fetch the agent details
agent_result = await client.table('agents').select('*').eq('agent_id', effective_agent_id).eq('account_id', account_id).execute()
if not agent_result.data:
# Agent was deleted or doesn't exist
return {
"agent": None,
"source": "missing",
"message": f"Agent {effective_agent_id} not found or was deleted"
}
agent_data = agent_result.data[0]
return {
"agent": AgentResponse(
agent_id=agent_data['agent_id'],
account_id=agent_data['account_id'],
name=agent_data['name'],
description=agent_data.get('description'),
system_prompt=agent_data['system_prompt'],
configured_mcps=agent_data.get('configured_mcps', []),
agentpress_tools=agent_data.get('agentpress_tools', {}),
is_default=agent_data.get('is_default', False),
created_at=agent_data['created_at'],
updated_at=agent_data['updated_at']
),
"source": agent_source,
"message": f"Using {agent_source} agent: {agent_data['name']}"
}
except HTTPException:
raise
except Exception as e:
logger.error(f"Error fetching agent for thread {thread_id}: {str(e)}")
raise HTTPException(status_code=500, detail=f"Failed to fetch thread agent: {str(e)}")
@router.get("/agent-run/{agent_run_id}/stream") @router.get("/agent-run/{agent_run_id}/stream")
async def stream_agent_run( async def stream_agent_run(
agent_run_id: str, agent_run_id: str,

View File

@ -23,7 +23,6 @@ import {
} from '@/lib/api'; } from '@/lib/api';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { ChatInput } from '@/components/thread/chat-input/chat-input'; import { ChatInput } from '@/components/thread/chat-input/chat-input';
import { AgentSelector } from '@/components/thread/chat-input/agent-selector';
import { FileViewerModal } from '@/components/thread/file-viewer-modal'; import { FileViewerModal } from '@/components/thread/file-viewer-modal';
import { SiteHeader } from '@/components/thread/thread-site-header'; import { SiteHeader } from '@/components/thread/thread-site-header';
import { import {
@ -47,6 +46,7 @@ import {
DialogFooter, DialogFooter,
} from '@/components/ui/dialog'; } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Skeleton } from '@/components/ui/skeleton';
import { import {
UnifiedMessage, UnifiedMessage,
@ -63,6 +63,7 @@ import { useAgentRunsQuery, useStartAgentMutation, useStopAgentMutation } from '
import { useBillingStatusQuery } from '@/hooks/react-query/threads/use-billing-status'; import { useBillingStatusQuery } from '@/hooks/react-query/threads/use-billing-status';
import { useSubscription, isPlan } from '@/hooks/react-query/subscriptions/use-subscriptions'; import { useSubscription, isPlan } from '@/hooks/react-query/subscriptions/use-subscriptions';
import { SubscriptionStatus } from '@/components/thread/chat-input/_use-model-selection'; import { SubscriptionStatus } from '@/components/thread/chat-input/_use-model-selection';
import { useThreadAgent } from '@/hooks/react-query/agents/use-agents';
// Extend the base Message type with the expected database fields // Extend the base Message type with the expected database fields
interface ApiMessageType extends BaseApiMessageType { interface ApiMessageType extends BaseApiMessageType {
@ -136,6 +137,7 @@ export default function ThreadPage({
const messagesLoadedRef = useRef(false); const messagesLoadedRef = useRef(false);
const agentRunsCheckedRef = useRef(false); const agentRunsCheckedRef = useRef(false);
const previousAgentStatus = useRef<typeof agentStatus>('idle'); const previousAgentStatus = useRef<typeof agentStatus>('idle');
const { data: threadAgent, isLoading: threadAgentLoading, error: threadAgentError } = useThreadAgent(threadId);
const [externalNavIndex, setExternalNavIndex] = React.useState<number | undefined>(undefined); const [externalNavIndex, setExternalNavIndex] = React.useState<number | undefined>(undefined);
@ -1223,19 +1225,27 @@ export default function ThreadPage({
"mx-auto", "mx-auto",
isMobile ? "w-full px-4" : "max-w-3xl" isMobile ? "w-full px-4" : "max-w-3xl"
)}> )}>
<ChatInput {threadAgentLoading || threadAgentError ? (
value={newMessage} <div className="space-y-3">
onChange={setNewMessage} <Skeleton className="h-4 w-32" />
onSubmit={handleSubmitMessage} <Skeleton className="h-12 w-full rounded-lg" />
placeholder="Ask Suna anything..." </div>
loading={isSending} ) : (
disabled={isSending || agentStatus === 'running' || agentStatus === 'connecting'} <ChatInput
isAgentRunning={agentStatus === 'running' || agentStatus === 'connecting'} value={newMessage}
onStopAgent={handleStopAgent} onChange={setNewMessage}
autoFocus={!isLoading} onSubmit={handleSubmitMessage}
onFileBrowse={handleOpenFileViewer} placeholder={`Ask ${threadAgent?.agent?.name || 'Suna'} anything...`}
sandboxId={sandboxId || undefined} loading={isSending}
/> disabled={isSending || agentStatus === 'running' || agentStatus === 'connecting'}
isAgentRunning={agentStatus === 'running' || agentStatus === 'connecting'}
onStopAgent={handleStopAgent}
autoFocus={!isLoading}
onFileBrowse={handleOpenFileViewer}
sandboxId={sandboxId || undefined}
agentName={threadAgent?.agent?.name || 'Suna'}
/>
)}
</div> </div>
</div> </div>
</div> </div>
@ -1257,6 +1267,7 @@ export default function ThreadPage({
renderAssistantMessage={toolViewAssistant} renderAssistantMessage={toolViewAssistant}
renderToolResult={toolViewResult} renderToolResult={toolViewResult}
isLoading={!initialLoadCompleted.current || isLoading} isLoading={!initialLoadCompleted.current || isLoading}
agentName={threadAgentLoading ? 'Loading...' : (threadAgent?.agent?.name || 'Suna')}
/> />
{sandboxId && ( {sandboxId && (

View File

@ -129,7 +129,7 @@ export function AgentSelector({
)} )}
</div> </div>
<span className="text-xs text-muted-foreground pl-6 line-clamp-2"> <span className="text-xs text-muted-foreground pl-6 line-clamp-2">
Your personal AI assistant Your personal AI employee
</span> </span>
</DropdownMenuItem> </DropdownMenuItem>
{agents.length > 0 ? ( {agents.length > 0 ? (
@ -227,7 +227,7 @@ export function AgentSelector({
</span> </span>
) : isUsingSuna ? ( ) : isUsingSuna ? (
<span className="text-xs text-muted-foreground line-clamp-1 max-w-[150px]"> <span className="text-xs text-muted-foreground line-clamp-1 max-w-[150px]">
Your personal AI assistant Your personal AI employee
</span> </span>
) : null} ) : null}
</div> </div>
@ -254,7 +254,7 @@ export function AgentSelector({
)} )}
</div> </div>
<span className="text-xs text-muted-foreground pl-6 line-clamp-2"> <span className="text-xs text-muted-foreground pl-6 line-clamp-2">
Your personal AI assistant Your personal AI employee
</span> </span>
</DropdownMenuItem> </DropdownMenuItem>
{agents.length > 0 ? ( {agents.length > 0 ? (

View File

@ -39,6 +39,7 @@ export interface ChatInputProps {
hideAttachments?: boolean; hideAttachments?: boolean;
selectedAgentId?: string; selectedAgentId?: string;
onAgentSelect?: (agentId: string | undefined) => void; onAgentSelect?: (agentId: string | undefined) => void;
agentName?: string;
} }
export interface UploadedFile { export interface UploadedFile {
@ -66,6 +67,7 @@ export const ChatInput = forwardRef<ChatInputHandles, ChatInputProps>(
hideAttachments = false, hideAttachments = false,
selectedAgentId, selectedAgentId,
onAgentSelect, onAgentSelect,
agentName,
}, },
ref, ref,
) => { ) => {
@ -263,7 +265,7 @@ export const ChatInput = forwardRef<ChatInputHandles, ChatInputProps>(
> >
<div className="text-xs text-muted-foreground flex items-center gap-2"> <div className="text-xs text-muted-foreground flex items-center gap-2">
<Loader2 className="h-3 w-3 animate-spin" /> <Loader2 className="h-3 w-3 animate-spin" />
<span>Kortix Suna is working...</span> <span>{agentName ? `${agentName} is working...` : 'Suna is working...'}</span>
</div> </div>
</motion.div> </motion.div>
)} )}

View File

@ -45,6 +45,7 @@ interface ToolCallSidePanelProps {
isSuccess?: boolean, isSuccess?: boolean,
) => React.ReactNode; ) => React.ReactNode;
isLoading?: boolean; isLoading?: boolean;
agentName?: string;
} }
interface ToolCallSnapshot { interface ToolCallSnapshot {
@ -65,6 +66,7 @@ export function ToolCallSidePanel({
project, project,
isLoading = false, isLoading = false,
externalNavigateToIndex, externalNavigateToIndex,
agentName
}: ToolCallSidePanelProps) { }: ToolCallSidePanelProps) {
const [dots, setDots] = React.useState(''); const [dots, setDots] = React.useState('');
const [internalIndex, setInternalIndex] = React.useState(0); const [internalIndex, setInternalIndex] = React.useState(0);
@ -233,7 +235,7 @@ export function ToolCallSidePanel({
<div className="ml-2 flex items-center gap-2"> <div className="ml-2 flex items-center gap-2">
<Computer className="h-4 w-4" /> <Computer className="h-4 w-4" />
<h2 className="text-md font-medium text-zinc-900 dark:text-zinc-100"> <h2 className="text-md font-medium text-zinc-900 dark:text-zinc-100">
Computer View {agentName ? `${agentName}'s Computer` : 'Suna\'s Computer'}
</h2> </h2>
</div> </div>
<Button <Button
@ -269,7 +271,7 @@ export function ToolCallSidePanel({
<div className="ml-2 flex items-center gap-2"> <div className="ml-2 flex items-center gap-2">
<Computer className="h-4 w-4" /> <Computer className="h-4 w-4" />
<h2 className="text-md font-medium text-zinc-900 dark:text-zinc-100"> <h2 className="text-md font-medium text-zinc-900 dark:text-zinc-100">
Computer View {agentName ? `${agentName}'s Computer` : 'Suna\'s Computer'}
</h2> </h2>
</div> </div>
<Button <Button
@ -330,7 +332,7 @@ export function ToolCallSidePanel({
<div className="ml-2 flex items-center gap-2"> <div className="ml-2 flex items-center gap-2">
<Computer className="h-4 w-4" /> <Computer className="h-4 w-4" />
<h2 className="text-md font-medium text-zinc-900 dark:text-zinc-100"> <h2 className="text-md font-medium text-zinc-900 dark:text-zinc-100">
Computer View {agentName ? `${agentName}'s Computer` : 'Suna\'s Computer'}
</h2> </h2>
</div> </div>

View File

@ -1,9 +1,11 @@
import { createQueryKeys } from "@/hooks/use-query"; import { createQueryKeys } from "@/hooks/use-query";
export const agentKeys = createQueryKeys({ export const agentKeys = createQueryKeys({
all: ['agents'] as const, all: ['agents'] as const,
lists: () => [...agentKeys.all, 'list'] as const, lists: () => [...agentKeys.all, 'list'] as const,
list: (filters?: Record<string, any>) => [...agentKeys.lists(), filters] as const, list: (filters?: Record<string, any>) => [...agentKeys.lists(), filters] as const,
details: () => [...agentKeys.all, 'detail'] as const, details: () => [...agentKeys.all, 'detail'] as const,
detail: (id: string) => [...agentKeys.details(), id] as const, detail: (id: string) => [...agentKeys.details(), id] as const,
}); threadAgents: () => [...agentKeys.all, 'thread-agent'] as const,
threadAgent: (threadId: string) => [...agentKeys.threadAgents(), threadId] as const,
});

View File

@ -2,7 +2,7 @@ import { createMutationHook, createQueryHook } from '@/hooks/use-query';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { agentKeys } from './keys'; import { agentKeys } from './keys';
import { Agent, AgentUpdateRequest, createAgent, deleteAgent, getAgent, getAgents, updateAgent } from './utils'; import { Agent, AgentUpdateRequest, createAgent, deleteAgent, getAgent, getAgents, getThreadAgent, updateAgent } from './utils';
export const useAgents = createQueryHook( export const useAgents = createQueryHook(
agentKeys.list(), agentKeys.list(),
@ -91,4 +91,16 @@ export const useOptimisticAgentUpdate = () => {
queryClient.invalidateQueries({ queryKey: agentKeys.detail(agentId) }); queryClient.invalidateQueries({ queryKey: agentKeys.detail(agentId) });
}, },
}; };
};
export const useThreadAgent = (threadId: string) => {
return createQueryHook(
agentKeys.threadAgent(threadId),
() => getThreadAgent(threadId),
{
enabled: !!threadId,
staleTime: 5 * 60 * 1000,
gcTime: 10 * 60 * 1000,
}
)();
}; };

View File

@ -3,197 +3,234 @@ import { createClient } from "@/lib/supabase/client";
const API_URL = process.env.NEXT_PUBLIC_BACKEND_URL || ''; const API_URL = process.env.NEXT_PUBLIC_BACKEND_URL || '';
export type Agent = { export type Agent = {
agent_id: string; agent_id: string;
account_id: string; account_id: string;
name: string;
description?: string;
system_prompt: string;
configured_mcps: Array<{
name: string; name: string;
description?: string; config: Record<string, any>;
system_prompt: string; }>;
configured_mcps: Array<{ agentpress_tools: Record<string, any>;
name: string; is_default: boolean;
config: Record<string, any>; created_at: string;
}>; updated_at: string;
agentpress_tools: Record<string, any>; };
is_default: boolean;
created_at: string; export type ThreadAgentResponse = {
updated_at: string; agent: Agent | null;
}; source: 'thread' | 'default' | 'none' | 'missing';
message: string;
export type AgentCreateRequest = { };
export type AgentCreateRequest = {
name: string;
description?: string;
system_prompt: string;
configured_mcps?: Array<{
name: string; name: string;
description?: string; config: Record<string, any>;
system_prompt: string; }>;
configured_mcps?: Array<{ agentpress_tools?: Record<string, any>;
name: string; is_default?: boolean;
config: Record<string, any>; };
}>;
agentpress_tools?: Record<string, any>; export type AgentUpdateRequest = {
is_default?: boolean; name?: string;
}; description?: string;
system_prompt?: string;
export type AgentUpdateRequest = { configured_mcps?: Array<{
name?: string; name: string;
description?: string; config: Record<string, any>;
system_prompt?: string; }>;
configured_mcps?: Array<{ agentpress_tools?: Record<string, any>;
name: string; is_default?: boolean;
config: Record<string, any>; };
}>;
agentpress_tools?: Record<string, any>; export const getAgents = async (): Promise<Agent[]> => {
is_default?: boolean; try {
}; const supabase = createClient();
const { data: { session } } = await supabase.auth.getSession();
export const getAgents = async (): Promise<Agent[]> => {
try { if (!session) {
const supabase = createClient(); throw new Error('You must be logged in to get agents');
const { data: { session } } = await supabase.auth.getSession();
if (!session) {
throw new Error('You must be logged in to get agents');
}
const response = await fetch(`${API_URL}/agents`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${session.access_token}`,
},
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Unknown error' }));
throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`);
}
const agents = await response.json();
console.log('[API] Fetched agents:', agents.length);
return agents;
} catch (err) {
console.error('Error fetching agents:', err);
throw err;
} }
};
const response = await fetch(`${API_URL}/agents`, {
export const getAgent = async (agentId: string): Promise<Agent> => { method: 'GET',
try { headers: {
const supabase = createClient(); 'Content-Type': 'application/json',
const { data: { session } } = await supabase.auth.getSession(); 'Authorization': `Bearer ${session.access_token}`,
},
if (!session) { });
throw new Error('You must be logged in to get agent details');
} if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Unknown error' }));
const response = await fetch(`${API_URL}/agents/${agentId}`, { throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`);
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${session.access_token}`,
},
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Unknown error' }));
throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`);
}
const agent = await response.json();
console.log('[API] Fetched agent:', agent.agent_id);
return agent;
} catch (err) {
console.error('Error fetching agent:', err);
throw err;
} }
};
const agents = await response.json();
export const createAgent = async (agentData: AgentCreateRequest): Promise<Agent> => { console.log('[API] Fetched agents:', agents.length);
try { return agents;
const supabase = createClient(); } catch (err) {
const { data: { session } } = await supabase.auth.getSession(); console.error('Error fetching agents:', err);
throw err;
if (!session) { }
throw new Error('You must be logged in to create an agent'); };
}
export const getAgent = async (agentId: string): Promise<Agent> => {
const response = await fetch(`${API_URL}/agents`, { try {
method: 'POST', const supabase = createClient();
headers: { const { data: { session } } = await supabase.auth.getSession();
'Content-Type': 'application/json',
'Authorization': `Bearer ${session.access_token}`, if (!session) {
}, throw new Error('You must be logged in to get agent details');
body: JSON.stringify(agentData),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Unknown error' }));
throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`);
}
const agent = await response.json();
console.log('[API] Created agent:', agent.agent_id);
return agent;
} catch (err) {
console.error('Error creating agent:', err);
throw err;
} }
};
const response = await fetch(`${API_URL}/agents/${agentId}`, {
export const updateAgent = async (agentId: string, agentData: AgentUpdateRequest): Promise<Agent> => { method: 'GET',
try { headers: {
const supabase = createClient(); 'Content-Type': 'application/json',
const { data: { session } } = await supabase.auth.getSession(); 'Authorization': `Bearer ${session.access_token}`,
},
if (!session) { });
throw new Error('You must be logged in to update an agent');
} if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Unknown error' }));
const response = await fetch(`${API_URL}/agents/${agentId}`, { throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`);
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${session.access_token}`,
},
body: JSON.stringify(agentData),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Unknown error' }));
throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`);
}
const agent = await response.json();
console.log('[API] Updated agent:', agent.agent_id);
return agent;
} catch (err) {
console.error('Error updating agent:', err);
throw err;
} }
};
const agent = await response.json();
export const deleteAgent = async (agentId: string): Promise<void> => { console.log('[API] Fetched agent:', agent.agent_id);
try { return agent;
const supabase = createClient(); } catch (err) {
const { data: { session } } = await supabase.auth.getSession(); console.error('Error fetching agent:', err);
throw err;
if (!session) { }
throw new Error('You must be logged in to delete an agent'); };
}
export const createAgent = async (agentData: AgentCreateRequest): Promise<Agent> => {
const response = await fetch(`${API_URL}/agents/${agentId}`, { try {
method: 'DELETE', const supabase = createClient();
headers: { const { data: { session } } = await supabase.auth.getSession();
'Content-Type': 'application/json',
'Authorization': `Bearer ${session.access_token}`, if (!session) {
}, throw new Error('You must be logged in to create an agent');
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Unknown error' }));
throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`);
}
console.log('[API] Deleted agent:', agentId);
} catch (err) {
console.error('Error deleting agent:', err);
throw err;
} }
};
const response = await fetch(`${API_URL}/agents`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${session.access_token}`,
},
body: JSON.stringify(agentData),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Unknown error' }));
throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`);
}
const agent = await response.json();
console.log('[API] Created agent:', agent.agent_id);
return agent;
} catch (err) {
console.error('Error creating agent:', err);
throw err;
}
};
export const updateAgent = async (agentId: string, agentData: AgentUpdateRequest): Promise<Agent> => {
try {
const supabase = createClient();
const { data: { session } } = await supabase.auth.getSession();
if (!session) {
throw new Error('You must be logged in to update an agent');
}
const response = await fetch(`${API_URL}/agents/${agentId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${session.access_token}`,
},
body: JSON.stringify(agentData),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Unknown error' }));
throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`);
}
const agent = await response.json();
console.log('[API] Updated agent:', agent.agent_id);
return agent;
} catch (err) {
console.error('Error updating agent:', err);
throw err;
}
};
export const deleteAgent = async (agentId: string): Promise<void> => {
try {
const supabase = createClient();
const { data: { session } } = await supabase.auth.getSession();
if (!session) {
throw new Error('You must be logged in to delete an agent');
}
const response = await fetch(`${API_URL}/agents/${agentId}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${session.access_token}`,
},
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Unknown error' }));
throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`);
}
console.log('[API] Deleted agent:', agentId);
} catch (err) {
console.error('Error deleting agent:', err);
throw err;
}
};
export const getThreadAgent = async (threadId: string): Promise<ThreadAgentResponse> => {
try {
const supabase = createClient();
const { data: { session } } = await supabase.auth.getSession();
if (!session) {
throw new Error('You must be logged in to get thread agent details');
}
const response = await fetch(`${API_URL}/thread/${threadId}/agent`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${session.access_token}`,
},
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Unknown error' }));
throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`);
}
const threadAgent = await response.json();
console.log('[API] Fetched thread agent:', threadAgent.source, threadAgent.agent?.name);
return threadAgent;
} catch (err) {
console.error('Error fetching thread agent:', err);
throw err;
}
};