mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-02-02 02:45:18 -05:00
arranging messages code
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
import {
|
||||
Conversation,
|
||||
ConversationContent,
|
||||
ConversationEmptyState,
|
||||
ConversationScrollButton,
|
||||
} from "@/components/ai-elements/conversation";
|
||||
import {
|
||||
Message,
|
||||
MessageContent,
|
||||
MessageResponse,
|
||||
} from "@/components/ai-elements/message";
|
||||
import { MessageSquareIcon } from "lucide-react";
|
||||
import { UIMessage, UIDataTypes, UITools } from "ai";
|
||||
|
||||
|
||||
interface ChatMessagesContainerProps {
|
||||
messages: UIMessage<unknown, UIDataTypes, UITools>[];
|
||||
status: string;
|
||||
error: Error | undefined;
|
||||
handleSubmit: (e: React.FormEvent) => void;
|
||||
input: string;
|
||||
setInput: (input: string) => void;
|
||||
}
|
||||
|
||||
export const ChatMessagesContainer = ({messages, status, error, handleSubmit, input, setInput}: ChatMessagesContainerProps) => {
|
||||
return (
|
||||
<div className="flex h-full flex-1 flex-col">
|
||||
<Conversation className="flex-1">
|
||||
<ConversationContent>
|
||||
{messages.length === 0 ? (
|
||||
<ConversationEmptyState
|
||||
icon={<MessageSquareIcon className="size-12" />}
|
||||
title="Start a conversation"
|
||||
description="Type a message below to begin chatting"
|
||||
/>
|
||||
) : (
|
||||
messages.map((message) => (
|
||||
<Message from={message.role} key={message.id}>
|
||||
<MessageContent>
|
||||
{message.parts.map((part, i) => {
|
||||
switch (part.type) {
|
||||
case "text":
|
||||
return (
|
||||
<MessageResponse key={`${message.id}-${i}`}>
|
||||
{part.text}
|
||||
</MessageResponse>
|
||||
);
|
||||
case "tool-find_block":
|
||||
return (
|
||||
<div
|
||||
key={`${message.id}-${i}`}
|
||||
className="w-fit rounded-xl border border-zinc-200 bg-zinc-100 p-2 text-xs text-zinc-700"
|
||||
>
|
||||
{part.state === "input-streaming" && (
|
||||
<p>Finding blocks for you</p>
|
||||
)}
|
||||
{part.state === "input-available" && (
|
||||
<p>
|
||||
Searching blocks for{" "}
|
||||
{(part.input as { query: string }).query}
|
||||
</p>
|
||||
)}
|
||||
{part.state === "output-available" && (
|
||||
<p>
|
||||
Found{" "}
|
||||
{
|
||||
(
|
||||
JSON.parse(part.output as string) as {
|
||||
count: number;
|
||||
}
|
||||
).count
|
||||
}{" "}
|
||||
blocks
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
</MessageContent>
|
||||
</Message>
|
||||
))
|
||||
)}
|
||||
{status === "submitted" && (
|
||||
<Message from="assistant">
|
||||
<MessageContent>
|
||||
<p className="text-zinc-500">Thinking...</p>
|
||||
</MessageContent>
|
||||
</Message>
|
||||
)}
|
||||
{error && (
|
||||
<div className="rounded-lg bg-red-50 p-3 text-red-600">
|
||||
Error: {error.message}
|
||||
</div>
|
||||
)}
|
||||
</ConversationContent>
|
||||
<ConversationScrollButton />
|
||||
</Conversation>
|
||||
|
||||
<form onSubmit={handleSubmit} className="border-t p-4">
|
||||
<div className="mx-auto flex max-w-2xl gap-2">
|
||||
<input
|
||||
value={input}
|
||||
onChange={(e) => setInput(e.target.value)}
|
||||
disabled={status !== "ready"}
|
||||
placeholder="Say something..."
|
||||
className="flex-1 rounded-md border border-zinc-300 px-4 py-2 focus:border-zinc-500 focus:outline-none"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={status !== "ready" || !input.trim()}
|
||||
className="rounded-md bg-zinc-900 px-4 py-2 text-white transition-colors hover:bg-zinc-800 disabled:opacity-50"
|
||||
>
|
||||
Send
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
import { ChatSidebar } from "../ChatSidebar/ChatSidebar";
|
||||
|
||||
interface EmptySessionProps {
|
||||
isCreating: boolean;
|
||||
handleSubmit: (e: React.FormEvent) => void;
|
||||
input: string;
|
||||
setInput: (input: string) => void;
|
||||
}
|
||||
|
||||
export const EmptySession = ({ isCreating, handleSubmit, input, setInput }: EmptySessionProps) => {
|
||||
return (
|
||||
<div className="flex h-full flex-1 flex-col items-center justify-center bg-zinc-100 p-4">
|
||||
<h2 className="mb-4 text-xl font-semibold text-zinc-700">
|
||||
Start a new conversation
|
||||
</h2>
|
||||
<form onSubmit={handleSubmit} className="w-full max-w-md">
|
||||
<input
|
||||
value={input}
|
||||
onChange={(e) => setInput(e.target.value)}
|
||||
disabled={isCreating}
|
||||
placeholder="Type your message to start..."
|
||||
className="w-full rounded-md border border-zinc-300 px-4 py-2"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isCreating || !input.trim()}
|
||||
className="mt-2 w-full rounded-md bg-blue-600 px-4 py-2 text-white transition-colors hover:bg-blue-700 disabled:opacity-50"
|
||||
>
|
||||
{isCreating ? "Starting..." : "Start Chat"}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -5,21 +5,13 @@ import { DefaultChatTransport } from "ai";
|
||||
import { useState, useMemo } from "react";
|
||||
import { parseAsString, useQueryState } from "nuqs";
|
||||
import { MessageSquare } from "lucide-react";
|
||||
import { ChatSidebar } from "./tools/components/ChatSidebar/ChatSidebar";
|
||||
import {
|
||||
Conversation,
|
||||
ConversationContent,
|
||||
ConversationEmptyState,
|
||||
ConversationScrollButton,
|
||||
} from "@/components/ai-elements/conversation";
|
||||
import {
|
||||
Message,
|
||||
MessageContent,
|
||||
MessageResponse,
|
||||
} from "@/components/ai-elements/message";
|
||||
import { ChatSidebar } from "./components/ChatSidebar/ChatSidebar";
|
||||
import { EmptySession } from "./components/EmptySession/EmptySession";
|
||||
import { ChatMessagesContainer } from "./components/ChatMessagesContainer/ChatMessagesContainer";
|
||||
import { postV2CreateSession } from "@/app/api/__generated__/endpoints/chat/chat";
|
||||
|
||||
export default function Page() {
|
||||
const [sessionId] = useQueryState("sessionId", parseAsString);
|
||||
const [sessionId, setSessionId] = useQueryState("sessionId", parseAsString);
|
||||
const [isCreating, setIsCreating] = useState(false);
|
||||
const [input, setInput] = useState("");
|
||||
|
||||
@@ -46,143 +38,37 @@ export default function Page() {
|
||||
transport: transport ?? undefined,
|
||||
});
|
||||
|
||||
function handleSubmit(e: React.FormEvent) {
|
||||
async function handleSubmit(e: React.FormEvent) {
|
||||
e.preventDefault();
|
||||
if(!sessionId) {
|
||||
const newSessionId = await postV2CreateSession({
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
if (newSessionId.status === 200 && newSessionId.data?.id) {
|
||||
setSessionId(newSessionId.data.id);
|
||||
}
|
||||
console.log("newSessionId", newSessionId);
|
||||
}
|
||||
if (input.trim()) {
|
||||
sendMessage({ text: input });
|
||||
setInput("");
|
||||
}
|
||||
}
|
||||
|
||||
// Show landing page when no session exists
|
||||
if (!sessionId) {
|
||||
return (
|
||||
<div className="flex h-full">
|
||||
<ChatSidebar isCreating={isCreating} setIsCreating={setIsCreating} />
|
||||
|
||||
<div className="flex h-full flex-1 flex-col items-center justify-center bg-zinc-100 p-4">
|
||||
<h2 className="mb-4 text-xl font-semibold text-zinc-700">
|
||||
Start a new conversation
|
||||
</h2>
|
||||
<form onSubmit={handleSubmit} className="w-full max-w-md">
|
||||
<input
|
||||
value={input}
|
||||
onChange={(e) => setInput(e.target.value)}
|
||||
disabled={isCreating}
|
||||
placeholder="Type your message to start..."
|
||||
className="w-full rounded-md border border-zinc-300 px-4 py-2"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isCreating || !input.trim()}
|
||||
className="mt-2 w-full rounded-md bg-blue-600 px-4 py-2 text-white transition-colors hover:bg-blue-700 disabled:opacity-50"
|
||||
>
|
||||
{isCreating ? "Starting..." : "Start Chat"}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full">
|
||||
<ChatSidebar isCreating={isCreating} setIsCreating={setIsCreating} />
|
||||
|
||||
<div className="flex h-full flex-1 flex-col">
|
||||
<Conversation className="flex-1">
|
||||
<ConversationContent>
|
||||
{messages.length === 0 ? (
|
||||
<ConversationEmptyState
|
||||
icon={<MessageSquare className="size-12" />}
|
||||
title="Start a conversation"
|
||||
description="Type a message below to begin chatting"
|
||||
/>
|
||||
) : (
|
||||
messages.map((message) => (
|
||||
<Message from={message.role} key={message.id}>
|
||||
<MessageContent>
|
||||
{message.parts.map((part, i) => {
|
||||
switch (part.type) {
|
||||
case "text":
|
||||
return (
|
||||
<MessageResponse key={`${message.id}-${i}`}>
|
||||
{part.text}
|
||||
</MessageResponse>
|
||||
);
|
||||
case "tool-find_block":
|
||||
return (
|
||||
<div
|
||||
key={`${message.id}-${i}`}
|
||||
className="w-fit rounded-xl border border-zinc-200 bg-zinc-100 p-2 text-xs text-zinc-700"
|
||||
>
|
||||
{part.state === "input-streaming" && (
|
||||
<p>Finding blocks for you</p>
|
||||
)}
|
||||
{part.state === "input-available" && (
|
||||
<p>
|
||||
Searching blocks for{" "}
|
||||
{(part.input as { query: string }).query}
|
||||
</p>
|
||||
)}
|
||||
{part.state === "output-available" && (
|
||||
<p>
|
||||
Found{" "}
|
||||
{
|
||||
(
|
||||
JSON.parse(part.output as string) as {
|
||||
count: number;
|
||||
}
|
||||
).count
|
||||
}{" "}
|
||||
blocks
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
</MessageContent>
|
||||
</Message>
|
||||
))
|
||||
)}
|
||||
{status === "submitted" && (
|
||||
<Message from="assistant">
|
||||
<MessageContent>
|
||||
<p className="text-zinc-500">Thinking...</p>
|
||||
</MessageContent>
|
||||
</Message>
|
||||
)}
|
||||
{error && (
|
||||
<div className="rounded-lg bg-red-50 p-3 text-red-600">
|
||||
Error: {error.message}
|
||||
</div>
|
||||
)}
|
||||
</ConversationContent>
|
||||
<ConversationScrollButton />
|
||||
</Conversation>
|
||||
{
|
||||
sessionId ? (
|
||||
<ChatMessagesContainer messages={messages} status={status} error={error} handleSubmit={handleSubmit} input={input} setInput={setInput} />
|
||||
) : (
|
||||
<EmptySession isCreating={isCreating} handleSubmit={handleSubmit} input={input} setInput={setInput} />
|
||||
)
|
||||
}
|
||||
|
||||
<form onSubmit={handleSubmit} className="border-t p-4">
|
||||
<div className="mx-auto flex max-w-2xl gap-2">
|
||||
<input
|
||||
value={input}
|
||||
onChange={(e) => setInput(e.target.value)}
|
||||
disabled={status !== "ready"}
|
||||
placeholder="Say something..."
|
||||
className="flex-1 rounded-md border border-zinc-300 px-4 py-2 focus:border-zinc-500 focus:outline-none"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={status !== "ready" || !input.trim()}
|
||||
className="rounded-md bg-zinc-900 px-4 py-2 text-white transition-colors hover:bg-zinc-800 disabled:opacity-50"
|
||||
>
|
||||
Send
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user