diff --git a/README.md b/README.md index defcbf4..560f179 100644 --- a/README.md +++ b/README.md @@ -168,3 +168,11 @@ The allowed actions are: - `Respond` - If you send a text response back, it will be used to rewrite the email in some way, then interrupt again and wait for you to take an action. - `Ignore` - This will send back an `ignore` response, and the graph will end without taking any actions. - `Mark as resolved` - If you select this, it will resume the graph, but starting at the `__end__` node, causing the graph to end without taking any actions. + +## Writer Agent + +This is a dummy agent used to demonstrate how you can stream generative UI components as an artifact. It should be accessed via the `writer` graph ID. It should be accessed via the `agent` graph ID, which means you'll need to go through the Supervisor agent to access it. The following prompts will trigger the writer agent: + +- `Write me a short story about a ` + +This will render a generative UI component that contains the title and content of your short story. The generative UI component will be rendered in a side panel to the right of the chat and the contents of the story will be streamed to the UI as it is generated. diff --git a/src/agent-uis/utils/use-artifact.tsx b/src/agent-uis/utils/use-artifact.tsx index 8220407..2a1ed86 100644 --- a/src/agent-uis/utils/use-artifact.tsx +++ b/src/agent-uis/utils/use-artifact.tsx @@ -1,23 +1,24 @@ -import { Message } from "@langchain/langgraph-sdk"; -import { useStreamContext, UIMessage } from "@langchain/langgraph-sdk/react-ui"; - -// eslint-disable-next-line react-refresh/only-export-components -const NoopPreview = () => null; - -// eslint-disable-next-line react-refresh/only-export-components -const NoopSetOpen = () => void 0; - -// eslint-disable-next-line react-refresh/only-export-components -const NoopSetContext = () => void 0; - -const NoopContext = {}; - +import { useMemo } from "react"; +import type { Message } from "@langchain/langgraph-sdk"; +import { + useStreamContext, + type UIMessage, +} from "@langchain/langgraph-sdk/react-ui"; + +/** + * Hook that obtains the artifact context provided by the `LoadExternalComponent` + * found in the `meta.artifact` field. + * + * @see https://github.com/langchain-ai/agent-chat-ui/blob/main/src/components/thread/messages/ai.tsx + */ export function useArtifact>() { type Component = (props: { children: React.ReactNode; title?: React.ReactNode; }) => React.ReactNode; + type Context = TContext | undefined; + type Bag = { open: boolean; setOpen: (value: boolean | ((prev: boolean) => boolean)) => void; @@ -28,17 +29,23 @@ export function useArtifact>() { const thread = useStreamContext< { messages: Message[]; ui: UIMessage[] }, - { MetaType: { artifact: { content: Component } & Bag } } + { MetaType: { artifact: [Component, Bag] } } >(); - return [ - thread.meta?.artifact?.content ?? NoopPreview, - { - open: thread.meta?.artifact?.open ?? false, - setOpen: thread.meta?.artifact?.setOpen ?? NoopSetOpen, - - context: thread.meta?.artifact?.context ?? NoopContext, - setContext: thread.meta?.artifact?.setContext ?? NoopSetContext, - }, - ] as [Component, Bag]; + const noop = useMemo( + () => + [ + () => null, + { + open: false, + setOpen: () => void 0, + + context: {} as TContext, + setContext: () => void 0, + }, + ] as [Component, Bag], + [], + ); + + return thread.meta?.artifact ?? noop; }