diff --git a/examples/with-inline-suggestions/components/ui/assistant-ui/AI_ThreadSuggestion.tsx b/examples/with-inline-suggestions/components/ui/assistant-ui/AI_ThreadSuggestion.tsx index cb8afb20b..7100cea8e 100644 --- a/examples/with-inline-suggestions/components/ui/assistant-ui/AI_ThreadSuggestion.tsx +++ b/examples/with-inline-suggestions/components/ui/assistant-ui/AI_ThreadSuggestion.tsx @@ -1,64 +1,89 @@ -import React, { FC, PropsWithChildren, useState, useEffect, useCallback } from "react"; +import React, { + FC, + PropsWithChildren, + useState, + useEffect, + useCallback, + useRef, +} from "react"; import { Button } from "@/components/ui/button"; import { ThreadPrimitive } from "@assistant-ui/react"; import { useLastAssistantMessage } from "./LastMessageHook"; -import { generate } from './actions'; -import { readStreamableValue } from 'ai/rsc'; +import { generate } from "./actions"; +import { readStreamableValue } from "ai/rsc"; const AI_ThreadSuggestion: FC> = ({ children }) => { const lastAssistantMessage = useLastAssistantMessage(); const [output, setOutput] = useState(null); const [output2, setOutput2] = useState(null); - const handleClick = useCallback(async () => { - const lastMessageContent = lastAssistantMessage?.content; - const lastMessageString = JSON.stringify(lastMessageContent); - console.log('LM:', lastMessageString); + const debounceRef = useRef(false); + const generateSuggestions = useCallback(async (content: string) => { + // do not send duplicate requests in React Strict Mode during development + if (process.env.NODE_ENV === "development") { + if (debounceRef.current) return; + debounceRef.current = true; + setTimeout(() => { + debounceRef.current = false; + }, 0); + } const [response1, response2] = await Promise.all([ - generate(`Generate a optimistic very very short one sentence follow up question based on this response: ${lastMessageString}`), - generate(`Generate a very skeptical very very short one sentence follow up question based on this response: ${lastMessageString}`) + generate( + `Generate a optimistic very very short one sentence follow up question based on this response: "${content}"`, + ), + generate( + `Generate a very skeptical very very short one sentence follow up question based on this response: "${content}"`, + ), ]); - let generatedOutput = ''; + let generatedOutput = ""; for await (const delta of readStreamableValue(response1.output)) { generatedOutput += delta; } console.log(generatedOutput); setOutput(generatedOutput); - let generatedOutput2 = ''; + let generatedOutput2 = ""; for await (const delta of readStreamableValue(response2.output)) { generatedOutput2 += delta; } console.log(generatedOutput2); setOutput2(generatedOutput2); - }, [lastAssistantMessage]); + }, []); useEffect(() => { - if (lastAssistantMessage) { - handleClick(); - } - }, [lastAssistantMessage, handleClick]); + const lastMessageContent = lastAssistantMessage?.content; + const lastMessageString = JSON.stringify(lastMessageContent); + generateSuggestions(lastMessageString); + }, [lastAssistantMessage, generateSuggestions]); return (
- + - + @@ -67,4 +92,12 @@ const AI_ThreadSuggestion: FC> = ({ children }) => { ); }; -export default AI_ThreadSuggestion; \ No newline at end of file +const WrappedAI_ThreadSuggestion = () => { + return ( + + + + ); +}; + +export default WrappedAI_ThreadSuggestion; diff --git a/examples/with-inline-suggestions/components/ui/assistant-ui/LastMessageHook.tsx b/examples/with-inline-suggestions/components/ui/assistant-ui/LastMessageHook.tsx index 958f81fbe..771a7fd7a 100644 --- a/examples/with-inline-suggestions/components/ui/assistant-ui/LastMessageHook.tsx +++ b/examples/with-inline-suggestions/components/ui/assistant-ui/LastMessageHook.tsx @@ -1,16 +1,14 @@ +import { ThreadAssistantMessage } from "@assistant-ui/react"; import { useThreadContext } from "@assistant-ui/react"; -import { useMemo } from "react"; export const useLastAssistantMessage = () => { const { useThreadMessages } = useThreadContext(); - const messages = useThreadMessages(); - - return useMemo(() => { + return useThreadMessages((messages) => { for (let i = messages.length - 1; i >= 0; i--) { - if (messages[i].role === "assistant") { - return messages[i]; + if (messages[i]?.role === "assistant") { + return messages[i]! as ThreadAssistantMessage; } } return null; - }, [messages]); -}; \ No newline at end of file + }); +};