import React, { createContext, useContext, ReactNode, useState } from "react"; import { useStream } from "@langchain/langgraph-sdk/react"; import { type Message } from "@langchain/langgraph-sdk"; import type { UIMessage, RemoveUIMessage, } from "@langchain/langgraph-sdk/react-ui/types"; import { useQueryParam, StringParam } from "use-query-params"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { LangGraphLogoSVG } from "@/components/icons/langgraph"; import { Label } from "@/components/ui/label"; import { ArrowRight } from "lucide-react"; import { PasswordInput } from "@/components/ui/password-input"; const useTypedStream = useStream< { messages: Message[]; ui: UIMessage[] }, { UpdateType: { messages?: Message[] | Message | string; ui?: (UIMessage | RemoveUIMessage)[] | UIMessage | RemoveUIMessage; }; CustomUpdateType: UIMessage | RemoveUIMessage; } >; type StreamContextType = ReturnType; const StreamContext = createContext(undefined); const StreamSession = ({ children, apiKey, apiUrl, assistantId, }: { children: ReactNode; apiKey: string | null; apiUrl: string; assistantId: string; }) => { const [threadId, setThreadId] = useQueryParam("threadId", StringParam); const streamValue = useTypedStream({ apiUrl, apiKey: apiKey ?? undefined, assistantId, threadId: threadId ?? null, onThreadId: setThreadId, }); return ( {children} ); }; export const StreamProvider: React.FC<{ children: ReactNode }> = ({ children, }) => { const [apiUrl, setApiUrl] = useQueryParam("apiUrl", StringParam); const [apiKey, _setApiKey] = useState(() => { try { const key = window.localStorage.getItem("lg:chat:apiKey"); return key || null; } catch { // pass } return null; }); const setApiKey = (key: string) => { window.localStorage.setItem("lg:chat:apiKey", key); _setApiKey(key); }; const [assistantId, setAssistantId] = useQueryParam( "assistantId", StringParam, ); if (!apiUrl || !assistantId) { return (

LangGraph Chat

Welcome to LangGraph Chat! Before you get started, you need to enter the URL of the deployment and the assistant / graph ID.

{ e.preventDefault(); const form = e.target as HTMLFormElement; const formData = new FormData(form); const apiUrl = formData.get("apiUrl") as string; const assistantId = formData.get("assistantId") as string; const apiKey = formData.get("apiKey") as string; setApiUrl(apiUrl); setApiKey(apiKey); setAssistantId(assistantId); form.reset(); }} className="flex flex-col gap-6 p-6 bg-muted/50" >

This is the URL of your LangGraph deployment. Can be a local, or production deployment.

This is the ID of the graph (can be the graph name), or assistant to fetch threads from, and invoke when actions are taken.

This value is stored in your browser's local storage and is only used to authenticate requests sent to your LangGraph server.

); } return ( {children} ); }; // Create a custom hook to use the context export const useStreamContext = (): StreamContextType => { const context = useContext(StreamContext); if (context === undefined) { throw new Error("useStreamContext must be used within a StreamProvider"); } return context; }; export default StreamContext;