mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 10:23:14 +00:00
Feat: Polling /chat/threads (#337)
* Thread polling on /chat/page (recent) * polling chat/threads using SWR polling hook * reinstall swr in web/ package.json --------- Co-authored-by: Brace Sproul <braceasproul@gmail.com>
This commit is contained in:
parent
4793ee3d3a
commit
6f7c5e1111
5 changed files with 92 additions and 6 deletions
|
|
@ -62,6 +62,7 @@
|
|||
"remark-gfm": "^4.0.1",
|
||||
"remark-math": "^6.0.0",
|
||||
"sonner": "^2.0.1",
|
||||
"swr": "^2.3.4",
|
||||
"tailwind-merge": "^3.0.2",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"use-stick-to-bottom": "^1.0.46",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { DefaultView } from "@/components/v2/default-view";
|
||||
import { ThreadDisplayInfo, threadToDisplayInfo } from "@/components/v2/types";
|
||||
import { useThreads } from "@/hooks/useThreads";
|
||||
import { useThreadsSWR } from "@/hooks/useThreadsSWR";
|
||||
import { GitHubAppProvider } from "@/providers/GitHubApp";
|
||||
import { GraphState } from "@open-swe/shared/open-swe/types";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
|
|
@ -10,7 +10,13 @@ import { Suspense } from "react";
|
|||
import { MANAGER_GRAPH_ID } from "@open-swe/shared/constants";
|
||||
|
||||
export default function ChatPage() {
|
||||
const { threads, threadsLoading } = useThreads<GraphState>(MANAGER_GRAPH_ID);
|
||||
const { threads, isLoading: threadsLoading } = useThreadsSWR<GraphState>({
|
||||
assistantId: MANAGER_GRAPH_ID,
|
||||
refreshInterval: 15000, // Poll every 15 seconds
|
||||
});
|
||||
if (!threads) {
|
||||
return <div>No threads</div>;
|
||||
}
|
||||
|
||||
// Convert Thread objects to ThreadDisplayInfo for UI
|
||||
const displayThreads: ThreadDisplayInfo[] = threads.map(threadToDisplayInfo);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { Input } from "@/components/ui/input";
|
|||
import { ArrowLeft, Search, Filter } from "lucide-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { ThreadDisplayInfo, threadToDisplayInfo } from "@/components/v2/types";
|
||||
import { useThreads } from "@/hooks/useThreads";
|
||||
import { useThreadsSWR } from "@/hooks/useThreadsSWR";
|
||||
import { GraphState } from "@open-swe/shared/open-swe/types";
|
||||
import { ThreadCard, ThreadCardLoading } from "@/components/v2/thread-card";
|
||||
import { ThemeToggle } from "@/components/theme-toggle";
|
||||
|
|
@ -18,7 +18,10 @@ type FilterStatus = "all" | "running" | "completed" | "failed" | "pending";
|
|||
|
||||
export default function AllThreadsPage() {
|
||||
const router = useRouter();
|
||||
const { threads, threadsLoading } = useThreads<GraphState>(MANAGER_GRAPH_ID);
|
||||
const { threads, isLoading: threadsLoading } = useThreadsSWR<GraphState>({
|
||||
assistantId: MANAGER_GRAPH_ID,
|
||||
refreshInterval: 15000, // Poll every 15 seconds
|
||||
});
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [statusFilter, setStatusFilter] = useState<FilterStatus>("all");
|
||||
|
||||
|
|
|
|||
63
apps/web/src/hooks/useThreadsSWR.ts
Normal file
63
apps/web/src/hooks/useThreadsSWR.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import { createClient } from "@/providers/client";
|
||||
import { Thread } from "@langchain/langgraph-sdk";
|
||||
import useSWR from "swr";
|
||||
|
||||
export interface UseThreadsSWROptions {
|
||||
assistantId?: string;
|
||||
refreshInterval?: number;
|
||||
revalidateOnFocus?: boolean;
|
||||
revalidateOnReconnect?: boolean;
|
||||
}
|
||||
|
||||
export function useThreadsSWR<State extends Record<string, any>>(
|
||||
options: UseThreadsSWROptions = {},
|
||||
) {
|
||||
const {
|
||||
assistantId,
|
||||
refreshInterval = 0, // Default to no polling, can be overridden
|
||||
revalidateOnFocus = true,
|
||||
revalidateOnReconnect = true,
|
||||
} = options;
|
||||
|
||||
const apiUrl: string | undefined = process.env.NEXT_PUBLIC_API_URL ?? "";
|
||||
|
||||
// Create a unique key for SWR caching based on assistantId
|
||||
const swrKey = assistantId ? ["threads", assistantId] : ["threads", "all"];
|
||||
|
||||
const fetcher = async (): Promise<Thread<State>[]> => {
|
||||
if (!apiUrl) {
|
||||
throw new Error("API URL is not configured");
|
||||
}
|
||||
|
||||
const client = createClient(apiUrl);
|
||||
const searchArgs = assistantId
|
||||
? {
|
||||
metadata: {
|
||||
graph_id: assistantId,
|
||||
},
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return await client.threads.search<State>(searchArgs);
|
||||
};
|
||||
|
||||
const { data, error, isLoading, mutate, isValidating } = useSWR(
|
||||
swrKey,
|
||||
fetcher,
|
||||
{
|
||||
refreshInterval,
|
||||
revalidateOnFocus,
|
||||
revalidateOnReconnect,
|
||||
errorRetryCount: 3,
|
||||
errorRetryInterval: 5000,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
threads: data ?? [],
|
||||
error,
|
||||
isLoading,
|
||||
isValidating,
|
||||
mutate, // For manual revalidation
|
||||
};
|
||||
}
|
||||
17
yarn.lock
17
yarn.lock
|
|
@ -2539,6 +2539,7 @@ __metadata:
|
|||
remark-math: ^6.0.0
|
||||
shadcn: ^2.6.1
|
||||
sonner: ^2.0.1
|
||||
swr: ^2.3.4
|
||||
tailwind-merge: ^3.0.2
|
||||
tailwind-scrollbar: ^4.0.1
|
||||
tailwindcss: ^4.0.13
|
||||
|
|
@ -6097,7 +6098,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"dequal@npm:^2.0.0":
|
||||
"dequal@npm:^2.0.0, dequal@npm:^2.0.3":
|
||||
version: 2.0.3
|
||||
resolution: "dequal@npm:2.0.3"
|
||||
checksum: 8679b850e1a3d0ebbc46ee780d5df7b478c23f335887464023a631d1b9af051ad4a6595a44220f9ff8ff95a8ddccf019b5ad778a976fd7bbf77383d36f412f90
|
||||
|
|
@ -13437,6 +13438,18 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"swr@npm:^2.3.4":
|
||||
version: 2.3.4
|
||||
resolution: "swr@npm:2.3.4"
|
||||
dependencies:
|
||||
dequal: ^2.0.3
|
||||
use-sync-external-store: ^1.4.0
|
||||
peerDependencies:
|
||||
react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
checksum: 18172b2215d8fa883b4845a094637e5aafb847b3ab96fb950866f0e50a9ada59450c8bcf9dc930e30e6fa40b986dbee45684c96337685b6d6f4d68006bd26b2a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tailwind-merge@npm:^3.0.2":
|
||||
version: 3.3.0
|
||||
resolution: "tailwind-merge@npm:3.3.0"
|
||||
|
|
@ -14246,7 +14259,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"use-sync-external-store@npm:^1.5.0":
|
||||
"use-sync-external-store@npm:^1.4.0, use-sync-external-store@npm:^1.5.0":
|
||||
version: 1.5.0
|
||||
resolution: "use-sync-external-store@npm:1.5.0"
|
||||
peerDependencies:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue