mirror of
https://github.com/temporal-community/temporal-ai-agent.git
synced 2026-03-16 06:28:08 +01:00
mucho UI fixes
This commit is contained in:
@@ -19,46 +19,50 @@ export default function ChatWindow({ conversation, loading, onConfirm }) {
|
||||
}
|
||||
|
||||
const filtered = conversation.filter((msg) => {
|
||||
|
||||
const { actor, response } = msg;
|
||||
|
||||
|
||||
if (actor === "user") {
|
||||
return true;
|
||||
}
|
||||
if (actor === "agent") {
|
||||
const parsed = typeof response === "string" ? safeParse(response) : response;
|
||||
// Keep if next is "question", "confirm", or "user_confirmed_tool_run".
|
||||
// Only skip if next is "done" (or something else).
|
||||
// return !["done"].includes(parsed.next);
|
||||
return true;
|
||||
return true; // Adjust this logic based on your "next" field.
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="flex-grow overflow-y-auto space-y-4">
|
||||
{filtered.map((msg, idx) => {
|
||||
|
||||
const { actor, response } = msg;
|
||||
|
||||
if (actor === "user") {
|
||||
return (
|
||||
<MessageBubble key={idx} message={{ response }} isUser />
|
||||
);
|
||||
} else if (actor === "agent") {
|
||||
const data =
|
||||
typeof response === "string" ? safeParse(response) : response;
|
||||
return <LLMResponse key={idx} data={data} onConfirm={onConfirm} />;
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
|
||||
{/* If loading = true, show the spinner at the bottom */}
|
||||
{loading && (
|
||||
<div className="flex justify-center">
|
||||
<LoadingIndicator />
|
||||
</div>
|
||||
)}
|
||||
<div className="flex-grow flex flex-col">
|
||||
{/* Main message container */}
|
||||
<div className="flex-grow flex flex-col justify-end overflow-y-auto space-y-3">
|
||||
{filtered.map((msg, idx) => {
|
||||
const { actor, response } = msg;
|
||||
|
||||
if (actor === "user") {
|
||||
return <MessageBubble key={idx} message={{ response }} isUser />;
|
||||
} else if (actor === "agent") {
|
||||
const data =
|
||||
typeof response === "string" ? safeParse(response) : response;
|
||||
const isLastMessage = idx === filtered.length - 1;
|
||||
return (
|
||||
<LLMResponse
|
||||
key={idx}
|
||||
data={data}
|
||||
onConfirm={onConfirm}
|
||||
isLastMessage={isLastMessage}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null; // Fallback for unsupported actors.
|
||||
})}
|
||||
{/* Loading indicator */}
|
||||
{loading && (
|
||||
<div className="pt-2 flex justify-center">
|
||||
<LoadingIndicator />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function ConfirmInline({ data, confirmed, onConfirm }) {
|
||||
{args && (
|
||||
<div className="mt-1">
|
||||
<strong>Args:</strong>
|
||||
<pre className="bg-gray-100 dark:bg-gray-700 p-1 rounded text-xs whitespace-pre-wrap">
|
||||
<pre className="bg-gray-100 dark:bg-gray-700 p-1 rounded text-sm whitespace-pre-wrap">
|
||||
{JSON.stringify(args, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
@@ -31,14 +31,14 @@ export default function ConfirmInline({ data, confirmed, onConfirm }) {
|
||||
// Not confirmed yet → show confirmation UI
|
||||
return (
|
||||
<div className="mt-2 p-2 border border-gray-400 dark:border-gray-600 rounded bg-gray-50 dark:bg-gray-800">
|
||||
<div className="text-sm text-gray-600 dark:text-gray-300">
|
||||
<div className="text-gray-600 dark:text-gray-300">
|
||||
<div>
|
||||
<strong>Tool:</strong> {tool ?? "Unknown"}
|
||||
</div>
|
||||
{args && (
|
||||
<div className="mt-1">
|
||||
<strong>Args:</strong>
|
||||
<pre className="bg-gray-100 dark:bg-gray-700 p-1 rounded text-xs whitespace-pre-wrap">
|
||||
<pre className="bg-gray-100 dark:bg-gray-700 p-1 rounded text-sm whitespace-pre-wrap">
|
||||
{JSON.stringify(args, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@@ -2,17 +2,16 @@ import React, { useState } from "react";
|
||||
import MessageBubble from "./MessageBubble";
|
||||
import ConfirmInline from "./ConfirmInline";
|
||||
|
||||
export default function LLMResponse({ data, onConfirm }) {
|
||||
export default function LLMResponse({ data, onConfirm, isLastMessage }) {
|
||||
const [isConfirmed, setIsConfirmed] = useState(false);
|
||||
|
||||
const handleConfirm = async () => {
|
||||
if (onConfirm) {
|
||||
await onConfirm();
|
||||
}
|
||||
setIsConfirmed(true); // Update state after confirmation
|
||||
if (onConfirm) await onConfirm();
|
||||
setIsConfirmed(true);
|
||||
};
|
||||
|
||||
const requiresConfirm = data.next === "confirm";
|
||||
// Only requires confirm if data.next === "confirm" AND it's the last message
|
||||
const requiresConfirm = data.next === "confirm" && isLastMessage;
|
||||
|
||||
if (typeof data.response === "object") {
|
||||
data.response = data.response.response;
|
||||
|
||||
@@ -16,11 +16,14 @@ export default function MessageBubble({ message, fallback = "", isUser = false }
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`max-w-xs md:max-w-sm px-4 py-2 mb-1 rounded-lg ${
|
||||
isUser ? "ml-auto" : "mr-auto"
|
||||
} ${bubbleStyle}`}
|
||||
style={{ whiteSpace: "pre-wrap" }}
|
||||
>
|
||||
className={`inline-block px-4 py-2 mb-1 rounded-lg ${
|
||||
isUser ? "ml-auto bg-blue-100" : "mr-auto bg-gray-200"
|
||||
} break-words`}
|
||||
style={{
|
||||
whiteSpace: "pre-wrap",
|
||||
maxWidth: "75%", // or '80%'
|
||||
}}
|
||||
>
|
||||
{displayText}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,8 +2,10 @@ import React from "react";
|
||||
|
||||
export default function NavBar({ title }) {
|
||||
return (
|
||||
<div className="bg-gray-200 dark:bg-gray-700 p-4 shadow-sm">
|
||||
<h1 className="text-xl font-bold">{title}</h1>
|
||||
</div>
|
||||
<header className="fixed top-0 left-0 w-full p-4 bg-white/70 dark:bg-gray-800/70
|
||||
backdrop-blur-md shadow-md z-10 flex justify-center">
|
||||
<h1 className="text-xl font-bold font-poppins">{title}</h1>
|
||||
{/* ...any additional nav items... */}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user