diff --git a/backend/src/agents/lead_agent/agent.py b/backend/src/agents/lead_agent/agent.py
index 5195b0a..fa21138 100644
--- a/backend/src/agents/lead_agent/agent.py
+++ b/backend/src/agents/lead_agent/agent.py
@@ -265,7 +265,7 @@ def make_lead_agent(config: RunnableConfig):
is_bootstrap = config.get("configurable", {}).get("is_bootstrap", False)
agent_name = config.get("configurable", {}).get("agent_name")
- agent_config = load_agent_config(agent_name)
+ agent_config = load_agent_config(agent_name) if not is_bootstrap else None
# Custom agent model or fallback to global/default model resolution
agent_model_name = agent_config.model if agent_config and agent_config.model else _resolve_model_name()
diff --git a/frontend/src/app/workspace/agents/[agent_name]/chats/[thread_id]/page.tsx b/frontend/src/app/workspace/agents/[agent_name]/chats/[thread_id]/page.tsx
index 506e053..6bbb597 100644
--- a/frontend/src/app/workspace/agents/[agent_name]/chats/[thread_id]/page.tsx
+++ b/frontend/src/app/workspace/agents/[agent_name]/chats/[thread_id]/page.tsx
@@ -1,10 +1,11 @@
"use client";
-import { BotIcon } from "lucide-react";
-import { useParams } from "next/navigation";
+import { BotIcon, PlusSquare } from "lucide-react";
+import { useParams, useRouter } from "next/navigation";
import { useCallback } from "react";
import type { PromptInputMessage } from "@/components/ai-elements/prompt-input";
+import { Button } from "@/components/ui/button";
import { AgentWelcome } from "@/components/workspace/agent-welcome";
import { ArtifactTrigger } from "@/components/workspace/artifacts";
import { ChatBox, useThreadChat } from "@/components/workspace/chats";
@@ -13,6 +14,7 @@ import { MessageList } from "@/components/workspace/messages";
import { ThreadContext } from "@/components/workspace/messages/context";
import { ThreadTitle } from "@/components/workspace/thread-title";
import { TodoList } from "@/components/workspace/todo-list";
+import { Tooltip } from "@/components/workspace/tooltip";
import { useAgent } from "@/core/agents";
import { useI18n } from "@/core/i18n/hooks";
import { useNotification } from "@/core/notification/hooks";
@@ -25,10 +27,10 @@ import { cn } from "@/lib/utils";
export default function AgentChatPage() {
const { t } = useI18n();
const [settings, setSettings] = useLocalSettings();
+ const router = useRouter();
- const { agent_name, thread_id: threadIdFromPath } = useParams<{
+ const { agent_name } = useParams<{
agent_name: string;
- thread_id: string;
}>();
const { agent } = useAgent(agent_name);
@@ -37,7 +39,7 @@ export default function AgentChatPage() {
const { showNotification } = useNotification();
const [thread, sendMessage] = useThreadStream({
- threadId: threadIdFromPath !== "new" ? threadIdFromPath : undefined,
+ threadId: isNewThread ? undefined : threadId,
context: { ...settings.context, agent_name: agent_name },
onStart: () => {
setIsNewThread(false);
@@ -99,7 +101,18 @@ export default function AgentChatPage() {
-
+
+
+
+
diff --git a/frontend/src/app/workspace/agents/new/page.tsx b/frontend/src/app/workspace/agents/new/page.tsx
index 0273e98..9424a5f 100644
--- a/frontend/src/app/workspace/agents/new/page.tsx
+++ b/frontend/src/app/workspace/agents/new/page.tsx
@@ -43,6 +43,7 @@ export default function NewAgentPage() {
const threadId = useMemo(() => uuid(), []);
const [thread, sendMessage] = useThreadStream({
+ threadId: step === "chat" ? threadId : undefined,
context: {
mode: "flash",
is_bootstrap: true,
diff --git a/frontend/src/components/workspace/artifacts/artifact-trigger.tsx b/frontend/src/components/workspace/artifacts/artifact-trigger.tsx
index a6aa64a..df1fe68 100644
--- a/frontend/src/components/workspace/artifacts/artifact-trigger.tsx
+++ b/frontend/src/components/workspace/artifacts/artifact-trigger.tsx
@@ -10,7 +10,7 @@ export const ArtifactTrigger = () => {
const { t } = useI18n();
const { artifacts, setOpen: setArtifactsOpen } = useArtifacts();
- if (artifacts?.length === 0) {
+ if (!artifacts || artifacts.length === 0) {
return null;
}
return (
diff --git a/frontend/src/components/workspace/chats/use-thread-chat.ts b/frontend/src/components/workspace/chats/use-thread-chat.ts
index 1a4692d..b316448 100644
--- a/frontend/src/components/workspace/chats/use-thread-chat.ts
+++ b/frontend/src/components/workspace/chats/use-thread-chat.ts
@@ -1,21 +1,29 @@
"use client";
-import { useParams, useSearchParams } from "next/navigation";
-import { useMemo, useState } from "react";
+import { useParams, usePathname, useSearchParams } from "next/navigation";
+import { useEffect, useState } from "react";
import { uuid } from "@/core/utils/uuid";
export function useThreadChat() {
const { thread_id: threadIdFromPath } = useParams<{ thread_id: string }>();
+ const pathname = usePathname();
+
const searchParams = useSearchParams();
- const threadId = useMemo(
- () => (threadIdFromPath === "new" ? uuid() : threadIdFromPath),
- [threadIdFromPath],
- );
+ const [threadId, setThreadId] = useState(() => {
+ return threadIdFromPath === "new" ? uuid() : threadIdFromPath;
+ });
const [isNewThread, setIsNewThread] = useState(
() => threadIdFromPath === "new",
);
+
+ useEffect(() => {
+ if (pathname.endsWith("/new")) {
+ setIsNewThread(true);
+ setThreadId(uuid());
+ }
+ }, [pathname]);
const isMock = searchParams.get("mock") === "true";
return { threadId, isNewThread, setIsNewThread, isMock };
}
diff --git a/frontend/src/core/threads/hooks.ts b/frontend/src/core/threads/hooks.ts
index ec70940..b327aa0 100644
--- a/frontend/src/core/threads/hooks.ts
+++ b/frontend/src/core/threads/hooks.ts
@@ -1,8 +1,8 @@
import type { AIMessage } from "@langchain/langgraph-sdk";
import type { ThreadsClient } from "@langchain/langgraph-sdk/client";
-import { useStream, type UseStream } from "@langchain/langgraph-sdk/react";
+import { useStream } from "@langchain/langgraph-sdk/react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
-import { useCallback, useState } from "react";
+import { useCallback, useEffect, useState } from "react";
import { toast } from "sonner";
import type { PromptInputMessage } from "@/components/ai-elements/prompt-input";
@@ -37,6 +37,13 @@ export function useThreadStream({
onToolEnd,
}: ThreadStreamOptions) {
const [_threadId, setThreadId] = useState
(threadId ?? null);
+
+ useEffect(() => {
+ if (_threadId && _threadId !== threadId) {
+ setThreadId(threadId ?? null);
+ }
+ }, [threadId, _threadId]);
+
const queryClient = useQueryClient();
const updateSubtask = useUpdateSubtask();
const thread = useStream({
@@ -74,27 +81,7 @@ export function useThreadStream({
},
onFinish(state) {
onFinish?.(state.values);
- // void queryClient.invalidateQueries({ queryKey: ["threads", "search"] });
- queryClient.setQueriesData(
- {
- queryKey: ["threads", "search"],
- exact: false,
- },
- (oldData: Array) => {
- return oldData.map((t) => {
- if (t.thread_id === threadId) {
- return {
- ...t,
- values: {
- ...t.values,
- title: state.values.title,
- },
- };
- }
- return t;
- });
- },
- );
+ void queryClient.invalidateQueries({ queryKey: ["threads", "search"] });
},
});