Skip to content

Commit

Permalink
disable if not all are present
Browse files Browse the repository at this point in the history
  • Loading branch information
bracesproul committed Oct 16, 2024
1 parent 7a7c584 commit edeacfb
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 4 deletions.
3 changes: 2 additions & 1 deletion frontend/app/components/Primitives.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ const MyThreadScrollToBottom: FC = () => {

interface MyComposerProps {
messages: BaseMessage[];
submitDisabled: boolean;
}

const MyComposer: FC<MyComposerProps> = (props: MyComposerProps) => {
Expand All @@ -117,7 +118,7 @@ const MyComposer: FC<MyComposerProps> = (props: MyComposerProps) => {
className="placeholder:text-gray-400 text-gray-100 max-h-40 flex-1 resize-none border-none bg-transparent px-2 py-2 text-sm outline-none focus:ring-0 disabled:cursor-not-allowed"
/>
<div className="flex-shrink-0">
<ThreadPrimitive.If running={false}>
<ThreadPrimitive.If running={false} disabled={props.submitDisabled}>
<ComposerPrimitive.Send asChild>
<TooltipIconButton
tooltip="Send"
Expand Down
26 changes: 24 additions & 2 deletions frontend/app/hooks/useGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { v4 as uuidv4 } from "uuid";

import { Client } from "@langchain/langgraph-sdk";
import { getCookie, setCookie } from "../utils/cookies";
import { ThreadActual } from "./useThreads";
import { ThreadActual, useThreads } from "./useThreads";

export const createClient = () => {
const apiUrl = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:3000/api";
Expand Down Expand Up @@ -53,20 +53,41 @@ export interface GraphInput {

export function useGraph(userId: string | undefined) {
const { toast } = useToast();
const { getThreadById } = useThreads(userId);
const [messages, setMessages] = useState<BaseMessage[]>([]);
const [assistantId, setAssistantId] = useState<string>();
const [threadId, setThreadId] = useState<string>();

useEffect(() => {
if (threadId || typeof window === "undefined" || !userId) return;
createThread(userId);
searchOrCreateThread(userId);
}, [userId]);

useEffect(() => {
if (assistantId || typeof window === "undefined") return;
getOrCreateAssistant();
}, []);

const searchOrCreateThread = async (id: string) => {
const threadIdCookie = getCookie("clc_py_thread_id");
if (!threadIdCookie) {
await createThread(id);
return;
}
// Thread ID is in cookies.

const thread = await getThreadById(threadIdCookie);
if (!thread.values) {
// No values = no activity. Can keep.
setThreadId(threadIdCookie);
return;
} else {
// Current thread has activity. Create a new thread.
await createThread(id);
return;
}
};

const createThread = async (id: string) => {
setMessages([]);
const client = createClient();
Expand All @@ -81,6 +102,7 @@ export function useGraph(userId: string | undefined) {
throw new Error("Thread creation failed.");
}
setThreadId(thread.thread_id);
setCookie("clc_py_thread_id", thread.thread_id);
} catch (e) {
console.error("Error creating thread", e);
toast({
Expand Down
6 changes: 6 additions & 0 deletions frontend/app/hooks/useThreads.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,13 @@ export function useThreads(userId: string | undefined) {
}
};

const getThreadById = async (id: string) => {
const client = createClient();
return (await client.threads.get(id)) as Awaited<ThreadActual>;
};

return {
userThreads,
getThreadById,
};
}
22 changes: 21 additions & 1 deletion frontend/app/new/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ import { useGraph } from "../hooks/useGraph";
import { ThreadHistory } from "../components/ThreadHistory";
import { useUser } from "../hooks/useUser";
import { useThreads } from "../hooks/useThreads";
import { useToast } from "../hooks/use-toast";

export default function ContentComposerChatInterface(): React.ReactElement {
const { toast } = useToast();
const { userId } = useUser();
const {
messages,
Expand All @@ -34,7 +36,25 @@ export default function ContentComposerChatInterface(): React.ReactElement {
const { userThreads } = useThreads(userId);
const [isRunning, setIsRunning] = useState(false);

const isSubmitDisabled = !userId || !assistantId || !currentThread;

async function onNew(message: AppendMessage): Promise<void> {
if (isSubmitDisabled) {
let description = "";
if (!userId) {
description = "Unable to find user ID. Please try again later.";
} else if (!assistantId) {
description = "Unable to find assistant ID. Please try again later.";
} else if (!currentThread) {
description =
"Unable to find current thread ID. Please try again later.";
}
toast({
title: "Failed to send message",
description,
});
return;
}
if (message.content[0]?.type !== "text") {
throw new Error("Only text messages are supported");
}
Expand Down Expand Up @@ -83,7 +103,7 @@ export default function ContentComposerChatInterface(): React.ReactElement {
</div>
<div className="w-full h-full overflow-hidden">
<AssistantRuntimeProvider runtime={runtime}>
<MyThread messages={messages} />
<MyThread submitDisabled={isSubmitDisabled} messages={messages} />
</AssistantRuntimeProvider>
</div>
<Toaster />
Expand Down

0 comments on commit edeacfb

Please sign in to comment.