diff --git a/apps/mail/components/create/ai-chat.tsx b/apps/mail/components/create/ai-chat.tsx
index e9c4051040..ea0fe02b03 100644
--- a/apps/mail/components/create/ai-chat.tsx
+++ b/apps/mail/components/create/ai-chat.tsx
@@ -1,4 +1,3 @@
-import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
import { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar';
import { useAIFullScreen, useAISidebar } from '../ui/ai-sidebar';
import { VoiceProvider } from '@/providers/voice-provider';
@@ -14,25 +13,26 @@ import { VoiceButton } from '../voice-button';
import { EditorContent } from '@tiptap/react';
import { CurvedArrow } from '../icons/icons';
import { Tools } from '../../types/tools';
-import { InfoIcon } from 'lucide-react';
import { Button } from '../ui/button';
import { format } from 'date-fns-tz';
import { useQueryState } from 'nuqs';
-const renderThread = (thread: { id: string; title: string; snippet: string }) => {
+const ThreadPreview = ({ threadId }: { threadId: string }) => {
const [, setThreadId] = useQueryState('threadId');
- const { data: getThread } = useThread(thread.id);
+ const { data: getThread } = useThread(threadId);
const [, setIsFullScreen] = useQueryState('isFullScreen');
const handleClick = () => {
- setThreadId(thread.id);
+ setThreadId(threadId);
setIsFullScreen(null);
};
- return getThread?.latest ? (
+ if (!getThread?.latest) return null;
+
+ return (
@@ -65,15 +65,7 @@ const renderThread = (thread: { id: string; title: string; snippet: string }) =>
- ) : null;
-};
-
-const RenderThreads = ({
- threads,
-}: {
- threads: { id: string; title: string; snippet: string }[];
-}) => {
- return {threads.map(renderThread)}
;
+ );
};
const ExampleQueries = ({ onQueryClick }: { onQueryClick: (query: string) => void }) => {
@@ -148,82 +140,55 @@ export interface AIChatProps {
onModelChange?: (model: string) => void;
}
-declare global {
- var DEBUG: boolean;
-}
-
-const ToolResponse = ({ toolName, result, args }: { toolName: string; result: any; args: any }) => {
- const renderContent = () => {
- switch (toolName) {
- case Tools.ListThreads:
- case Tools.AskZeroMailbox:
- return result?.threads ? : null;
-
- case Tools.GetThread:
- return result?.thread ? (
-
-
-
-
- {result.thread.sender?.name?.[0]?.toUpperCase()}
-
-
-
{result.thread.sender?.name}
-
{result.thread.subject}
-
-
-
- {result.thread.body}
-
-
- ) : null;
-
- case Tools.GetUserLabels:
- return result?.labels ? (
-
- {result.labels.map((label: any) => (
-
- ))}
-
- ) : null;
-
- case Tools.ComposeEmail:
- return result?.newBody ? (
-
- ) : null;
-
- default:
- return null;
- }
- };
+// Subcomponents for ToolResponse
+const GetThreadToolResponse = ({ result, args }: { result: any; args: any }) => {
+ // Extract threadId from result or args
+ let threadId: string | null = null;
+ if (typeof result === 'string') {
+ const match = result.match(//);
+ if (match?.[1]) threadId = match[1];
+ }
+ if (!threadId && args?.id && typeof args.id === 'string') threadId = args.id;
+ if (!threadId) return null;
+ return ;
+};
- const content = renderContent();
- if (!content) return null;
+const GetUserLabelsToolResponse = ({ result }: { result: any }) => {
+ if (!result?.labels) return null;
+ return (
+
+ {result.labels.map((label: any) => (
+
+ ))}
+
+ );
+};
+const ComposeEmailToolResponse = ({ result }: { result: any }) => {
+ if (!result?.newBody) return null;
return (
-
- {globalThis.DEBUG ? (
-
-
-
-
-
-
-
Tool Arguments:
-
{JSON.stringify(args, null, 2)}
-
-
-
- ) : null}
- {content}
+
);
};
+// Main ToolResponse switcher
+const ToolResponse = ({ toolName, result, args }: { toolName: string; result: any; args: any }) => {
+ switch (toolName) {
+ case Tools.GetThread:
+ return
;
+ case Tools.GetUserLabels:
+ return
;
+ case Tools.ComposeEmail:
+ return
;
+ default:
+ return null;
+ }
+};
+
export function AIChat({
messages,
setInput,
@@ -320,28 +285,22 @@ export function AIChat({
messages.map((message, index) => {
const textParts = message.parts.filter((part) => part.type === 'text');
const toolParts = message.parts.filter((part) => part.type === 'tool-invocation');
- const streamingTools = new Set([Tools.WebSearch]);
- const doesIncludeStreamingTool = toolParts.some(
- (part) =>
- streamingTools.has(part.toolInvocation?.toolName as Tools) &&
- part.toolInvocation?.result,
- );
+
return (
-
- {toolParts.map((part) =>
- part.toolInvocation &&
- part.toolInvocation.result &&
- !streamingTools.has(part.toolInvocation.toolName as Tools) ? (
-
- ) : null,
+
+ {toolParts.map(
+ (part, index) =>
+ part.toolInvocation?.result && (
+
+ ),
)}
- {!doesIncludeStreamingTool && textParts.length > 0 && (
-
0 && (
+
@@ -382,7 +340,7 @@ export function AIChat({
),
)}
-
+
)}
);
@@ -390,12 +348,10 @@ export function AIChat({
)}
{(status === 'submitted' || status === 'streaming') && (
-
-
-
- zero is thinking...
-
-
+
+
+ zero is thinking...
+
)}
{(status === 'error' || !!error) && (
diff --git a/apps/mail/components/mail/mail-display.tsx b/apps/mail/components/mail/mail-display.tsx
index 25fd702890..49a35203a8 100644
--- a/apps/mail/components/mail/mail-display.tsx
+++ b/apps/mail/components/mail/mail-display.tsx
@@ -297,7 +297,7 @@ const ThreadAttachments = ({ attachments }: { attachments: Attachment[] }) => {
{attachments.map((attachment) => (