+
navigator(`/assistant/${id}`)}
+ deleteConfig={props.deleteConfig}
/>
diff --git a/frontend/src/components/OrphanChat.tsx b/frontend/src/components/OrphanChat.tsx
new file mode 100644
index 00000000..1369e90e
--- /dev/null
+++ b/frontend/src/components/OrphanChat.tsx
@@ -0,0 +1,110 @@
+import { useEffect, useState } from "react";
+import { Config } from "../hooks/useConfigList";
+import { Chat } from "../types";
+import { getAssistants } from "../api/assistants";
+import { useThreadAndAssistant } from "../hooks/useThreadAndAssistant";
+
+export function OrphanChat(props: {
+ chat: Chat;
+ updateChat: (
+ name: string,
+ thread_id: string,
+ assistant_id: string | null,
+ ) => Promise
;
+}) {
+ const [newConfigId, setNewConfigId] = useState(null as string | null);
+ const [configs, setConfigs] = useState([]);
+ const { invalidateChat } = useThreadAndAssistant();
+
+ const update = async () => {
+ if (!newConfigId) {
+ alert("Please select a bot.");
+ return;
+ }
+ const updatedChat = await props.updateChat(
+ props.chat.thread_id,
+ props.chat.name,
+ newConfigId,
+ );
+ invalidateChat(updatedChat.thread_id);
+ };
+
+ const botTypeToName = (botType: string) => {
+ switch (botType) {
+ case "chatbot":
+ return "Chatbot";
+ case "chat_retrieval":
+ return "RAG";
+ case "agent":
+ return "Assistant";
+ default:
+ return botType;
+ }
+ };
+
+ useEffect(() => {
+ async function fetchConfigs() {
+ const configs = await getAssistants();
+ const suitableConfigs = configs
+ ? configs.filter(
+ (config) =>
+ config.config.configurable?.type ===
+ props.chat.metadata?.assistant_type,
+ )
+ : [];
+ setConfigs(suitableConfigs);
+ }
+
+ fetchConfigs();
+ }, [props.chat.metadata?.assistant_type]);
+
+ return (
+
+ {configs.length ? (
+
+ ) : (
+
+
+ This chat has no bot attached. To continue chatting, you need to
+ attach a bot. However, there are no suitable bots available for this
+ chat. Please create a new bot with type{" "}
+ {botTypeToName(props.chat.metadata?.assistant_type as string)} and
+ try again.
+
+
+ )}
+
+ );
+}
diff --git a/frontend/src/hooks/useChatList.ts b/frontend/src/hooks/useChatList.ts
index b5a51bb6..5778b5e4 100644
--- a/frontend/src/hooks/useChatList.ts
+++ b/frontend/src/hooks/useChatList.ts
@@ -4,10 +4,11 @@ import { Chat } from "../types";
export interface ChatListProps {
chats: Chat[] | null;
- createChat: (
+ createChat: (name: string, assistant_id: string) => Promise;
+ updateChat: (
name: string,
- assistant_id: string,
- thread_id?: string,
+ thread_id: string,
+ assistant_id: string | null,
) => Promise;
deleteChat: (thread_id: string) => Promise;
}
@@ -57,6 +58,23 @@ export function useChatList(): ChatListProps {
return saved;
}, []);
+ const updateChat = useCallback(
+ async (thread_id: string, name: string, assistant_id: string | null) => {
+ const response = await fetch(`/threads/${thread_id}`, {
+ method: "PUT",
+ body: JSON.stringify({ assistant_id, name }),
+ headers: {
+ "Content-Type": "application/json",
+ Accept: "application/json",
+ },
+ });
+ const saved = await response.json();
+ setChats(saved);
+ return saved;
+ },
+ [],
+ );
+
const deleteChat = useCallback(
async (thread_id: string) => {
await fetch(`/threads/${thread_id}`, {
@@ -73,6 +91,7 @@ export function useChatList(): ChatListProps {
return {
chats,
createChat,
+ updateChat,
deleteChat,
};
}
diff --git a/frontend/src/hooks/useConfigList.ts b/frontend/src/hooks/useConfigList.ts
index bd50ddf9..91014f05 100644
--- a/frontend/src/hooks/useConfigList.ts
+++ b/frontend/src/hooks/useConfigList.ts
@@ -1,5 +1,6 @@
import { useCallback, useEffect, useReducer } from "react";
import orderBy from "lodash/orderBy";
+import { getAssistants } from "../api/assistants";
export interface Config {
assistant_id: string;
@@ -29,6 +30,7 @@ export interface ConfigListProps {
isPublic: boolean,
assistantId?: string,
) => Promise;
+ deleteConfig: (assistantId: string) => Promise;
}
function configsReducer(
@@ -51,14 +53,10 @@ export function useConfigList(): ConfigListProps {
useEffect(() => {
async function fetchConfigs() {
- const myConfigs = await fetch("/assistants/", {
- headers: {
- Accept: "application/json",
- },
- })
- .then((r) => r.json())
- .then((li) => li.map((c: Config) => ({ ...c, mine: true })));
- setConfigs(myConfigs);
+ const assistants = await getAssistants();
+ setConfigs(
+ assistants ? assistants.map((c) => ({ ...c, mine: true })) : [],
+ );
}
fetchConfigs();
@@ -105,8 +103,22 @@ export function useConfigList(): ConfigListProps {
[],
);
+ const deleteConfig = useCallback(
+ async (assistantId: string): Promise => {
+ await fetch(`/assistants/${assistantId}`, {
+ method: "DELETE",
+ headers: {
+ Accept: "application/json",
+ },
+ });
+ setConfigs((configs || []).filter((c) => c.assistant_id !== assistantId));
+ },
+ [configs],
+ );
+
return {
configs,
saveConfig,
+ deleteConfig,
};
}
diff --git a/frontend/src/hooks/useThreadAndAssistant.ts b/frontend/src/hooks/useThreadAndAssistant.ts
index 4b48fd9e..7b17c868 100644
--- a/frontend/src/hooks/useThreadAndAssistant.ts
+++ b/frontend/src/hooks/useThreadAndAssistant.ts
@@ -1,4 +1,4 @@
-import { useQuery } from "react-query";
+import { useQuery, useQueryClient } from "react-query";
import { useParams } from "react-router-dom";
import { getAssistant } from "../api/assistants";
import { getThread } from "../api/threads";
@@ -6,6 +6,7 @@ import { getThread } from "../api/threads";
export function useThreadAndAssistant() {
// Extract route parameters
const { chatId, assistantId } = useParams();
+ const queryClient = useQueryClient();
// React Query to fetch chat details if chatId is present
const { data: currentChat, isLoading: isLoadingChat } = useQuery(
@@ -28,10 +29,15 @@ export function useThreadAndAssistant() {
},
);
+ const invalidateChat = (chatId: string) => {
+ queryClient.invalidateQueries(["thread", chatId]);
+ };
+
// Return both loading states, the chat data, and the assistant configuration
return {
currentChat,
assistantConfig,
isLoading: isLoadingChat || isLoadingAssistant,
+ invalidateChat,
};
}
diff --git a/frontend/src/types.ts b/frontend/src/types.ts
index af698847..f95e0444 100644
--- a/frontend/src/types.ts
+++ b/frontend/src/types.ts
@@ -24,4 +24,5 @@ export interface Chat {
thread_id: string;
name: string;
updated_at: string;
+ metadata: Record | null;
}