Merge branch 'main' of https://github.com/langchain-ai/agent-ui-demo into brace/hookup-accommodations

This commit is contained in:
bracesproul
2025-03-05 12:38:02 -08:00
12 changed files with 78 additions and 60 deletions

View File

@@ -1,4 +1,4 @@
import { StockbrokerState } from "../types"; import { StockbrokerState, StockbrokerUpdate } from "../types";
import { ChatOpenAI } from "@langchain/openai"; import { ChatOpenAI } from "@langchain/openai";
import { typedUi } from "@langchain/langgraph-sdk/react-ui/server"; import { typedUi } from "@langchain/langgraph-sdk/react-ui/server";
import type ComponentMap from "../../uis/index"; import type ComponentMap from "../../uis/index";
@@ -32,7 +32,7 @@ const STOCKBROKER_TOOLS = [
export async function callTools( export async function callTools(
state: StockbrokerState, state: StockbrokerState,
config: LangGraphRunnableConfig, config: LangGraphRunnableConfig,
): Promise<Partial<StockbrokerState>> { ): Promise<StockbrokerUpdate> {
const ui = typedUi<typeof ComponentMap>(config); const ui = typedUi<typeof ComponentMap>(config);
const message = await llm.bindTools(STOCKBROKER_TOOLS).invoke([ const message = await llm.bindTools(STOCKBROKER_TOOLS).invoke([
@@ -65,8 +65,7 @@ export async function callTools(
return { return {
messages: [message], messages: [message],
// TODO: Fix the ui return type. ui: ui.collect as StockbrokerUpdate["ui"],
ui: ui.collect as any[],
timestamp: Date.now(), timestamp: Date.now(),
}; };
} }

View File

@@ -8,3 +8,4 @@ export const StockbrokerAnnotation = Annotation.Root({
}); });
export type StockbrokerState = typeof StockbrokerAnnotation.State; export type StockbrokerState = typeof StockbrokerAnnotation.State;
export type StockbrokerUpdate = typeof StockbrokerAnnotation.Update;

View File

@@ -1,11 +1,11 @@
import { ChatOpenAI } from "@langchain/openai"; import { ChatOpenAI } from "@langchain/openai";
import { TripPlannerState } from "../types"; import { TripPlannerState, TripPlannerUpdate } from "../types";
import { z } from "zod"; import { z } from "zod";
import { formatMessages } from "agent/utils/format-messages"; import { formatMessages } from "agent/utils/format-messages";
export async function classify( export async function classify(
state: TripPlannerState, state: TripPlannerState,
): Promise<Partial<TripPlannerState>> { ): Promise<TripPlannerUpdate> {
if (!state.tripDetails) { if (!state.tripDetails) {
// Can not classify if tripDetails are undefined // Can not classify if tripDetails are undefined
return {}; return {};

View File

@@ -1,5 +1,5 @@
import { ChatOpenAI } from "@langchain/openai"; import { ChatOpenAI } from "@langchain/openai";
import { TripDetails, TripPlannerState } from "../types"; import { TripDetails, TripPlannerState, TripPlannerUpdate } from "../types";
import { z } from "zod"; import { z } from "zod";
import { formatMessages } from "agent/utils/format-messages"; import { formatMessages } from "agent/utils/format-messages";
@@ -43,7 +43,7 @@ function calculateDates(
export async function extraction( export async function extraction(
state: TripPlannerState, state: TripPlannerState,
): Promise<Partial<TripPlannerState>> { ): Promise<TripPlannerUpdate> {
const schema = z.object({ const schema = z.object({
location: z location: z
.string() .string()

View File

@@ -1,4 +1,4 @@
import { TripPlannerState } from "../types"; import { TripPlannerState, TripPlannerUpdate } from "../types";
import { ChatOpenAI } from "@langchain/openai"; import { ChatOpenAI } from "@langchain/openai";
import { typedUi } from "@langchain/langgraph-sdk/react-ui/server"; import { typedUi } from "@langchain/langgraph-sdk/react-ui/server";
import type ComponentMap from "../../uis/index"; import type ComponentMap from "../../uis/index";
@@ -49,7 +49,7 @@ const schema = z.object({
export async function callTools( export async function callTools(
state: TripPlannerState, state: TripPlannerState,
config: LangGraphRunnableConfig, config: LangGraphRunnableConfig,
): Promise<Partial<TripPlannerState>> { ): Promise<TripPlannerUpdate> {
if (!state.tripDetails) { if (!state.tripDetails) {
throw new Error("No trip details found"); throw new Error("No trip details found");
} }
@@ -111,8 +111,7 @@ export async function callTools(
return { return {
messages: [response], messages: [response],
// TODO: Fix the ui return type. ui: ui.collect as TripPlannerUpdate["ui"],
ui: ui.collect as any[],
timestamp: Date.now(), timestamp: Date.now(),
}; };
} }

View File

@@ -16,3 +16,4 @@ export const TripPlannerAnnotation = Annotation.Root({
}); });
export type TripPlannerState = typeof TripPlannerAnnotation.State; export type TripPlannerState = typeof TripPlannerAnnotation.State;
export type TripPlannerUpdate = typeof TripPlannerAnnotation.Update;

View File

@@ -1,9 +1,16 @@
import { MessagesAnnotation, Annotation } from "@langchain/langgraph"; import { MessagesAnnotation, Annotation } from "@langchain/langgraph";
import { uiMessageReducer } from "@langchain/langgraph-sdk/react-ui/types"; import {
RemoveUIMessage,
UIMessage,
uiMessageReducer,
} from "@langchain/langgraph-sdk/react-ui/server";
export const GenerativeUIAnnotation = Annotation.Root({ export const GenerativeUIAnnotation = Annotation.Root({
messages: MessagesAnnotation.spec["messages"], messages: MessagesAnnotation.spec["messages"],
ui: Annotation({ default: () => [], reducer: uiMessageReducer }), ui: Annotation<
UIMessage[],
UIMessage | RemoveUIMessage | (UIMessage | RemoveUIMessage)[]
>({ default: () => [], reducer: uiMessageReducer }),
timestamp: Annotation<number>, timestamp: Annotation<number>,
next: Annotation<"stockbroker" | "tripPlanner" | "generalInput">(), next: Annotation<"stockbroker" | "tripPlanner" | "generalInput">(),
}); });

View File

@@ -1,12 +1,20 @@
import "./index.css"; import "./index.css";
import { useStream } from "@langchain/langgraph-sdk/react"; import {
import type { AIMessage, Message } from "@langchain/langgraph-sdk"; useStreamContext,
type UIMessage,
} from "@langchain/langgraph-sdk/react-ui";
import type { AIMessage, Message, ToolMessage } from "@langchain/langgraph-sdk";
import { useState, useEffect, useCallback } from "react"; import { useState, useEffect, useCallback } from "react";
export default function StockPrice(props: { export default function StockPrice(props: {
instruction: string; instruction: string;
logo: string; logo: string;
}) { }) {
const thread = useStreamContext<
{ messages: Message[]; ui: UIMessage[] },
{ MetaType: { ui: UIMessage | undefined } }
>();
const [quantity, setQuantity] = useState(1); const [quantity, setQuantity] = useState(1);
const [stockData, setStockData] = useState({ const [stockData, setStockData] = useState({
symbol: "AAPL", symbol: "AAPL",
@@ -51,23 +59,16 @@ export default function StockPrice(props: {
const [limitPrice, setLimitPrice] = useState(stockData.price.toFixed(2)); const [limitPrice, setLimitPrice] = useState(stockData.price.toFixed(2));
const [showOrderSuccess, setShowOrderSuccess] = useState(false); const [showOrderSuccess, setShowOrderSuccess] = useState(false);
// useStream should be able to be infered from context const aiTool = thread.messages.findLast(
const thread = useStream<{ messages: Message[] }>({
assistantId: "assistant_123",
apiUrl: "http://localhost:3123",
});
const messagesCopy = thread.messages;
const aiTool = messagesCopy
.slice()
.reverse()
.find(
(message): message is AIMessage => (message): message is AIMessage =>
message.type === "ai" && !!message.tool_calls?.length, message.type === "ai" && !!message.tool_calls?.length,
); );
const toolCallId = aiTool?.tool_calls?.[0]?.id; const toolCallId = aiTool?.tool_calls?.[0]?.id;
const toolResponse = thread.messages.findLast(
(message): message is ToolMessage =>
message.type === "tool" && message.tool_call_id === toolCallId,
);
// Simulated price history generation on component mount // Simulated price history generation on component mount
useEffect(() => { useEffect(() => {
@@ -248,6 +249,7 @@ export default function StockPrice(props: {
const range = max - min || 1; const range = max - min || 1;
const chartPath = generateChartPath(); const chartPath = generateChartPath();
if (toolResponse) return <div>Responded</div>;
return ( return (
<div className="w-full max-w-md bg-white rounded-xl shadow-lg overflow-hidden border border-gray-200"> <div className="w-full max-w-md bg-white rounded-xl shadow-lg overflow-hidden border border-gray-200">
<div <div

View File

@@ -58,9 +58,9 @@
"zod": "^3.24.2" "zod": "^3.24.2"
}, },
"resolutions": { "resolutions": {
"@langchain/langgraph-api": "next", "@langchain/langgraph-api": "0.0.14-experimental.1",
"@langchain/langgraph-cli": "next", "@langchain/langgraph-cli": "0.0.14-experimental.1",
"@langchain/langgraph-sdk": "next" "@langchain/langgraph-sdk": "0.0.47-experimental.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.19.0", "@eslint/js": "^9.19.0",

40
pnpm-lock.yaml generated
View File

@@ -5,9 +5,9 @@ settings:
excludeLinksFromLockfile: false excludeLinksFromLockfile: false
overrides: overrides:
"@langchain/langgraph-api": next "@langchain/langgraph-api": 0.0.14-experimental.1
"@langchain/langgraph-cli": next "@langchain/langgraph-cli": 0.0.14-experimental.1
"@langchain/langgraph-sdk": next "@langchain/langgraph-sdk": 0.0.47-experimental.0
importers: importers:
.: .:
@@ -34,14 +34,14 @@ importers:
specifier: ^0.2.49 specifier: ^0.2.49
version: 0.2.49(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0) version: 0.2.49(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0)
"@langchain/langgraph-api": "@langchain/langgraph-api":
specifier: next specifier: 0.0.14-experimental.1
version: 0.0.14-experimental.0(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(@langchain/langgraph-checkpoint@0.0.15(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2))))(@langchain/langgraph@0.2.49(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0))(openai@4.85.4(zod@3.24.2))(typescript@5.7.3) version: 0.0.14-experimental.1(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(@langchain/langgraph-checkpoint@0.0.15(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2))))(@langchain/langgraph@0.2.49(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0))(openai@4.85.4(zod@3.24.2))(typescript@5.7.3)
"@langchain/langgraph-cli": "@langchain/langgraph-cli":
specifier: next specifier: 0.0.14-experimental.1
version: 0.0.14-experimental.0(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(@langchain/langgraph-checkpoint@0.0.15(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2))))(@langchain/langgraph@0.2.49(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0))(openai@4.85.4(zod@3.24.2))(typescript@5.7.3) version: 0.0.14-experimental.1(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(@langchain/langgraph-checkpoint@0.0.15(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2))))(@langchain/langgraph@0.2.49(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0))(openai@4.85.4(zod@3.24.2))(typescript@5.7.3)
"@langchain/langgraph-sdk": "@langchain/langgraph-sdk":
specifier: next specifier: 0.0.47-experimental.0
version: 0.0.46-experimental.0(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0) version: 0.0.47-experimental.0(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0)
"@langchain/openai": "@langchain/openai":
specifier: ^0.4.4 specifier: ^0.4.4
version: 0.4.4(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2))) version: 0.4.4(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))
@@ -1087,10 +1087,10 @@ packages:
peerDependencies: peerDependencies:
"@langchain/core": ">=0.3.17 <0.4.0" "@langchain/core": ">=0.3.17 <0.4.0"
"@langchain/langgraph-api@0.0.14-experimental.0": "@langchain/langgraph-api@0.0.14-experimental.1":
resolution: resolution:
{ {
integrity: sha512-Cc72BHOXS0DhDvlkF3eW6V9CxvMRm0BI2J+ftpZUDG4s3nJjnp4p5F/fXkCnu9hks7w9IUrp4CGXzK4LUEf2iw==, integrity: sha512-gSQzZZk9tIrxXMQjudQbYHXPeK7l3Y/YbzCtnH6hWHvETQOZApUn0G18O5hWT9iYaAzZfSS8ExG7y6YM0MsFTQ==,
} }
engines: { node: ^18.19.0 || >=20.16.0 } engines: { node: ^18.19.0 || >=20.16.0 }
peerDependencies: peerDependencies:
@@ -1108,18 +1108,18 @@ packages:
peerDependencies: peerDependencies:
"@langchain/core": ">=0.2.31 <0.4.0" "@langchain/core": ">=0.2.31 <0.4.0"
"@langchain/langgraph-cli@0.0.14-experimental.0": "@langchain/langgraph-cli@0.0.14-experimental.1":
resolution: resolution:
{ {
integrity: sha512-31rdexCp4tR5849Qe3lstVai6VDm5+CFniGSQT08dghlITm4G0g35/jak9dFksavwLJ1NxeMTLuNJUfB5MocyA==, integrity: sha512-S8Y7WrBPsNZR7wUyWj3De0sEdTTf+ipJf1lCrJho+moL9TVXUXUE+oFoMb1G/uHvt8Q/FCSE9BfadEg4JUb5MQ==,
} }
engines: { node: ^18.19.0 || >=20.16.0 } engines: { node: ^18.19.0 || >=20.16.0 }
hasBin: true hasBin: true
"@langchain/langgraph-sdk@0.0.46-experimental.0": "@langchain/langgraph-sdk@0.0.47-experimental.0":
resolution: resolution:
{ {
integrity: sha512-ADzrxf/Rx8I2fe2lcXgIsB/3sG0uTLsG8S+HIA749yveWo1SQrlcy9+Smkla16y9PWdQpKeztrhNGI5g0BKxDw==, integrity: sha512-di60Pi2knQbe/sjOB3gNbNQNuTIhj0Yjls0SfEYeWDHirSN9heumPB/oxvwaxLBA8JKhuHg2h5lKUxAIT4b+aA==,
} }
peerDependencies: peerDependencies:
"@langchain/core": ">=0.2.31 <0.4.0" "@langchain/core": ">=0.2.31 <0.4.0"
@@ -5996,7 +5996,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- zod - zod
"@langchain/langgraph-api@0.0.14-experimental.0(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(@langchain/langgraph-checkpoint@0.0.15(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2))))(@langchain/langgraph@0.2.49(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0))(openai@4.85.4(zod@3.24.2))(typescript@5.7.3)": "@langchain/langgraph-api@0.0.14-experimental.1(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(@langchain/langgraph-checkpoint@0.0.15(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2))))(@langchain/langgraph@0.2.49(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0))(openai@4.85.4(zod@3.24.2))(typescript@5.7.3)":
dependencies: dependencies:
"@babel/code-frame": 7.26.2 "@babel/code-frame": 7.26.2
"@hono/node-server": 1.13.8(hono@4.7.2) "@hono/node-server": 1.13.8(hono@4.7.2)
@@ -6032,11 +6032,11 @@ snapshots:
"@langchain/core": 0.3.41(openai@4.85.4(zod@3.24.2)) "@langchain/core": 0.3.41(openai@4.85.4(zod@3.24.2))
uuid: 10.0.0 uuid: 10.0.0
"@langchain/langgraph-cli@0.0.14-experimental.0(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(@langchain/langgraph-checkpoint@0.0.15(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2))))(@langchain/langgraph@0.2.49(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0))(openai@4.85.4(zod@3.24.2))(typescript@5.7.3)": "@langchain/langgraph-cli@0.0.14-experimental.1(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(@langchain/langgraph-checkpoint@0.0.15(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2))))(@langchain/langgraph@0.2.49(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0))(openai@4.85.4(zod@3.24.2))(typescript@5.7.3)":
dependencies: dependencies:
"@babel/code-frame": 7.26.2 "@babel/code-frame": 7.26.2
"@commander-js/extra-typings": 13.1.0(commander@13.1.0) "@commander-js/extra-typings": 13.1.0(commander@13.1.0)
"@langchain/langgraph-api": 0.0.14-experimental.0(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(@langchain/langgraph-checkpoint@0.0.15(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2))))(@langchain/langgraph@0.2.49(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0))(openai@4.85.4(zod@3.24.2))(typescript@5.7.3) "@langchain/langgraph-api": 0.0.14-experimental.1(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(@langchain/langgraph-checkpoint@0.0.15(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2))))(@langchain/langgraph@0.2.49(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0))(openai@4.85.4(zod@3.24.2))(typescript@5.7.3)
chokidar: 4.0.3 chokidar: 4.0.3
commander: 13.1.0 commander: 13.1.0
dedent: 1.5.3 dedent: 1.5.3
@@ -6061,7 +6061,7 @@ snapshots:
- supports-color - supports-color
- typescript - typescript
"@langchain/langgraph-sdk@0.0.46-experimental.0(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0)": "@langchain/langgraph-sdk@0.0.47-experimental.0(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0)":
dependencies: dependencies:
"@types/json-schema": 7.0.15 "@types/json-schema": 7.0.15
p-queue: 6.6.2 p-queue: 6.6.2
@@ -6075,7 +6075,7 @@ snapshots:
dependencies: dependencies:
"@langchain/core": 0.3.41(openai@4.85.4(zod@3.24.2)) "@langchain/core": 0.3.41(openai@4.85.4(zod@3.24.2))
"@langchain/langgraph-checkpoint": 0.0.15(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2))) "@langchain/langgraph-checkpoint": 0.0.15(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))
"@langchain/langgraph-sdk": 0.0.46-experimental.0(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0) "@langchain/langgraph-sdk": 0.0.47-experimental.0(@langchain/core@0.3.41(openai@4.85.4(zod@3.24.2)))(react@19.0.0)
uuid: 10.0.0 uuid: 10.0.0
zod: 3.24.2 zod: 3.24.2
transitivePeerDependencies: transitivePeerDependencies:

View File

@@ -4,7 +4,7 @@ import { getContentString } from "../utils";
import { BranchSwitcher, CommandBar } from "./shared"; import { BranchSwitcher, CommandBar } from "./shared";
import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { MarkdownText } from "../markdown-text"; import { MarkdownText } from "../markdown-text";
import { LoadExternalComponent } from "@langchain/langgraph-sdk/react-ui/client"; import { LoadExternalComponent } from "@langchain/langgraph-sdk/react-ui";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { ToolCalls, ToolResult } from "./tool-calls"; import { ToolCalls, ToolResult } from "./tool-calls";
@@ -36,6 +36,7 @@ function CustomComponent({
assistantId="agent" assistantId="agent"
stream={thread} stream={thread}
message={customComponent} message={customComponent}
meta={{ ui: customComponent }}
/> />
)} )}
</div> </div>

View File

@@ -4,7 +4,7 @@ import { type Message } from "@langchain/langgraph-sdk";
import type { import type {
UIMessage, UIMessage,
RemoveUIMessage, RemoveUIMessage,
} from "@langchain/langgraph-sdk/react-ui/types"; } from "@langchain/langgraph-sdk/react-ui";
import { useQueryParam, StringParam } from "use-query-params"; import { useQueryParam, StringParam } from "use-query-params";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@@ -110,7 +110,9 @@ export const StreamProvider: React.FC<{ children: ReactNode }> = ({
className="flex flex-col gap-6 p-6 bg-muted/50" className="flex flex-col gap-6 p-6 bg-muted/50"
> >
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<Label htmlFor="apiUrl">Deployment URL</Label> <Label htmlFor="apiUrl">
Deployment URL<span className="text-rose-500">*</span>
</Label>
<p className="text-muted-foreground text-sm"> <p className="text-muted-foreground text-sm">
This is the URL of your LangGraph deployment. Can be a local, or This is the URL of your LangGraph deployment. Can be a local, or
production deployment. production deployment.
@@ -120,11 +122,14 @@ export const StreamProvider: React.FC<{ children: ReactNode }> = ({
name="apiUrl" name="apiUrl"
className="bg-background" className="bg-background"
defaultValue={apiUrl ?? "http://localhost:2024"} defaultValue={apiUrl ?? "http://localhost:2024"}
required
/> />
</div> </div>
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<Label htmlFor="assistantId">Assistant / Graph ID</Label> <Label htmlFor="assistantId">
Assistant / Graph ID<span className="text-rose-500">*</span>
</Label>
<p className="text-muted-foreground text-sm"> <p className="text-muted-foreground text-sm">
This is the ID of the graph (can be the graph name), or This is the ID of the graph (can be the graph name), or
assistant to fetch threads from, and invoke when actions are assistant to fetch threads from, and invoke when actions are
@@ -135,14 +140,17 @@ export const StreamProvider: React.FC<{ children: ReactNode }> = ({
name="assistantId" name="assistantId"
className="bg-background" className="bg-background"
defaultValue={assistantId ?? "agent"} defaultValue={assistantId ?? "agent"}
required
/> />
</div> </div>
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<Label htmlFor="apiKey">LangSmith API Key</Label> <Label htmlFor="apiKey">LangSmith API Key</Label>
<p className="text-muted-foreground text-sm"> <p className="text-muted-foreground text-sm">
This value is stored in your browser's local storage and is only This is <strong>NOT</strong> required if using a local LangGraph
used to authenticate requests sent to your LangGraph server. server. This value is stored in your browser's local storage and
is only used to authenticate requests sent to your LangGraph
server.
</p> </p>
<PasswordInput <PasswordInput
id="apiKey" id="apiKey"