import { validate } from "uuid"; import { getApiKey } from "@/lib/api-key"; import { Client, Thread } from "@langchain/langgraph-sdk"; import { useQueryParam, StringParam } from "use-query-params"; import { createContext, useContext, ReactNode, useCallback, useState, Dispatch, SetStateAction, } from "react"; interface ThreadContextType { getThreads: () => Promise; threads: Thread[]; setThreads: Dispatch>; threadsLoading: boolean; setThreadsLoading: Dispatch>; } const ThreadContext = createContext(undefined); function createClient(apiUrl: string, apiKey: string | undefined) { return new Client({ apiKey, apiUrl, }); } function getThreadSearchMetadata( assistantId: string, ): { graph_id: string } | { assistant_id: string } { if (validate(assistantId)) { return { assistant_id: assistantId }; } else { return { graph_id: assistantId }; } } export function ThreadProvider({ children }: { children: ReactNode }) { const [apiUrl] = useQueryParam("apiUrl", StringParam); const [assistantId] = useQueryParam("assistantId", StringParam); const [threads, setThreads] = useState([]); const [threadsLoading, setThreadsLoading] = useState(false); const getThreads = useCallback(async (): Promise => { if (!apiUrl || !assistantId) return []; const client = createClient(apiUrl, getApiKey() ?? undefined); const threads = await client.threads.search({ metadata: { ...getThreadSearchMetadata(assistantId), }, limit: 100, }); return threads; }, [apiUrl, assistantId]); const value = { getThreads, threads, setThreads, threadsLoading, setThreadsLoading, }; return ( {children} ); } export function useThreads() { const context = useContext(ThreadContext); if (context === undefined) { throw new Error("useThreads must be used within a ThreadProvider"); } return context; }