diff --git a/surfsense_backend/app/agents/new_chat/tools/display_image.py b/surfsense_backend/app/agents/new_chat/tools/display_image.py deleted file mode 100644 index 4424cc0d3..000000000 --- a/surfsense_backend/app/agents/new_chat/tools/display_image.py +++ /dev/null @@ -1,111 +0,0 @@ -""" -Display image tool for the SurfSense agent. - -This module provides a tool for displaying images in the chat UI -with metadata like title, description, and source attribution. -""" - -import hashlib -from typing import Any -from urllib.parse import urlparse - -from langchain_core.tools import tool - - -def extract_domain(url: str) -> str: - """Extract the domain from a URL.""" - try: - parsed = urlparse(url) - domain = parsed.netloc - # Remove 'www.' prefix if present - if domain.startswith("www."): - domain = domain[4:] - return domain - except Exception: - return "" - - -def generate_image_id(src: str) -> str: - """Generate a unique ID for an image.""" - hash_val = hashlib.md5(src.encode()).hexdigest()[:12] - return f"image-{hash_val}" - - -def create_display_image_tool(): - """ - Factory function to create the display_image tool. - - Returns: - A configured tool function for displaying images. - """ - - @tool - async def display_image( - src: str, - alt: str = "Image", - title: str | None = None, - description: str | None = None, - ) -> dict[str, Any]: - """ - Display an image in the chat with metadata. - - Use this tool when you want to show an image to the user. - This displays the image with an optional title, description, - and source attribution. - - Common use cases: - - Showing an image from a URL the user mentioned - - Displaying a diagram or chart you're referencing - - Showing example images when explaining concepts - - Args: - src: The URL of the image to display (must be a valid HTTP/HTTPS URL) - alt: Alternative text describing the image (for accessibility) - title: Optional title to display below the image - description: Optional description providing context about the image - - Returns: - A dictionary containing image metadata for the UI to render: - - id: Unique identifier for this image - - assetId: The image URL (for deduplication) - - src: The image URL - - alt: Alt text for accessibility - - title: Image title (if provided) - - description: Image description (if provided) - - domain: Source domain - """ - image_id = generate_image_id(src) - - # Ensure URL has protocol - if not src.startswith(("http://", "https://")): - src = f"https://{src}" - - domain = extract_domain(src) - - # Determine aspect ratio based on image source - # AI-generated images should use "auto" to preserve their native ratio - is_generated = "/image-generations/" in src - if is_generated: - ratio = "auto" - domain = "ai-generated" - elif "unsplash.com" in src or "pexels.com" in src: - ratio = "16:9" - elif ( - "imgur.com" in src or "github.com" in src or "githubusercontent.com" in src - ): - ratio = "auto" - else: - ratio = "auto" - - return { - "id": image_id, - "assetId": src, - "src": src, - "alt": alt, - "title": title, - "description": description, - "domain": domain, - "ratio": ratio, - } - - return display_image diff --git a/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx index 3f6893169..a6c01dd40 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx @@ -131,7 +131,6 @@ const TOOLS_WITH_UI = new Set([ "generate_podcast", "generate_report", "generate_video_presentation", - "display_image", "generate_image", "delete_notion_page", "create_notion_page", diff --git a/surfsense_web/components/assistant-ui/assistant-message.tsx b/surfsense_web/components/assistant-ui/assistant-message.tsx index 8ac2dcb01..8e1b455a2 100644 --- a/surfsense_web/components/assistant-ui/assistant-message.tsx +++ b/surfsense_web/components/assistant-ui/assistant-message.tsx @@ -17,7 +17,6 @@ import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button import { CommentPanelContainer } from "@/components/chat-comments/comment-panel-container/comment-panel-container"; import { CommentSheet } from "@/components/chat-comments/comment-sheet/comment-sheet"; import { CreateConfluencePageToolUI, DeleteConfluencePageToolUI, UpdateConfluencePageToolUI } from "@/components/tool-ui/confluence"; -import { DisplayImageToolUI } from "@/components/tool-ui/display-image"; import { GenerateImageToolUI } from "@/components/tool-ui/generate-image"; import { GeneratePodcastToolUI } from "@/components/tool-ui/generate-podcast"; import { GenerateReportToolUI } from "@/components/tool-ui/generate-report"; @@ -56,7 +55,7 @@ const AssistantMessageInner: FC = () => { generate_report: GenerateReportToolUI, generate_podcast: GeneratePodcastToolUI, generate_video_presentation: GenerateVideoPresentationToolUI, - display_image: DisplayImageToolUI, + display_image: () => null, generate_image: GenerateImageToolUI, save_memory: SaveMemoryToolUI, recall_memory: RecallMemoryToolUI, diff --git a/surfsense_web/components/public-chat/public-thread.tsx b/surfsense_web/components/public-chat/public-thread.tsx index 0fb34aeb2..99221ec2e 100644 --- a/surfsense_web/components/public-chat/public-thread.tsx +++ b/surfsense_web/components/public-chat/public-thread.tsx @@ -12,7 +12,6 @@ import { type FC, type ReactNode, useState } from "react"; import { MarkdownText } from "@/components/assistant-ui/markdown-text"; import { ToolFallback } from "@/components/assistant-ui/tool-fallback"; import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button"; -import { DisplayImageToolUI } from "@/components/tool-ui/display-image"; import { GenerateImageToolUI } from "@/components/tool-ui/generate-image"; import { GeneratePodcastToolUI } from "@/components/tool-ui/generate-podcast"; import { GenerateReportToolUI } from "@/components/tool-ui/generate-report"; @@ -149,7 +148,7 @@ const PublicAssistantMessage: FC = () => { generate_podcast: GeneratePodcastToolUI, generate_report: GenerateReportToolUI, generate_video_presentation: GenerateVideoPresentationToolUI, - display_image: DisplayImageToolUI, + display_image: () => null, generate_image: GenerateImageToolUI, link_preview: () => null, multi_link_preview: () => null, diff --git a/surfsense_web/components/tool-ui/display-image.tsx b/surfsense_web/components/tool-ui/display-image.tsx deleted file mode 100644 index 824ce0628..000000000 --- a/surfsense_web/components/tool-ui/display-image.tsx +++ /dev/null @@ -1,162 +0,0 @@ -"use client"; - -import type { ToolCallMessagePartProps } from "@assistant-ui/react"; -import { AlertCircleIcon, ImageIcon } from "lucide-react"; -import { z } from "zod"; -import { - Image, - ImageErrorBoundary, - ImageLoading, - parseSerializableImage, -} from "@/components/tool-ui/image"; - -// ============================================================================ -// Zod Schemas -// ============================================================================ - -/** - * Schema for display_image tool arguments - */ -const DisplayImageArgsSchema = z.object({ - src: z.string(), - alt: z.string().nullish(), - title: z.string().nullish(), - description: z.string().nullish(), -}); - -/** - * Schema for display_image tool result - */ -const DisplayImageResultSchema = z.object({ - id: z.string(), - assetId: z.string(), - src: z.string(), - alt: z.string().nullish(), - title: z.string().nullish(), - description: z.string().nullish(), - domain: z.string().nullish(), - ratio: z.string().nullish(), - error: z.string().nullish(), -}); - -// ============================================================================ -// Types -// ============================================================================ - -type DisplayImageArgs = z.infer; -type DisplayImageResult = z.infer; - -/** - * Error state component shown when image display fails - */ -function ImageErrorState({ src, error }: { src: string; error: string }) { - return ( -
-
-
- -
-
-

Failed to display image

-

{src}

-

{error}

-
-
-
- ); -} - -/** - * Cancelled state component - */ -function ImageCancelledState({ src }: { src: string }) { - return ( -
-

- - Image: {src} -

-
- ); -} - -/** - * Parsed Image component with error handling - * Note: Image component has built-in click handling via href/src, - * so no additional responseActions needed. - */ -function ParsedImage({ result }: { result: unknown }) { - const image = parseSerializableImage(result); - - return ; -} - -/** - * Display Image Tool UI Component - * - * This component is registered with assistant-ui to render an image - * when the display_image tool is called by the agent. - * - * It displays images with: - * - Title and description - * - Source attribution - * - Hover overlay effects - * - Click to open full size - */ -export const DisplayImageToolUI = ({ args, result, status }: ToolCallMessagePartProps) => { - const src = args.src || "Unknown"; - - // Loading state - tool is still running - if (status.type === "running" || status.type === "requires-action") { - return ( -
- -
- ); - } - - // Incomplete/cancelled state - if (status.type === "incomplete") { - if (status.reason === "cancelled") { - return ; - } - if (status.reason === "error") { - return ( - - ); - } - } - - // No result yet - if (!result) { - return ( -
- -
- ); - } - - // Error result from the tool - if (result.error) { - return ; - } - - // Success - render the image - return ( -
- - - -
- ); -}; - -export { - DisplayImageArgsSchema, - DisplayImageResultSchema, - type DisplayImageArgs, - type DisplayImageResult, -}; diff --git a/surfsense_web/components/tool-ui/index.ts b/surfsense_web/components/tool-ui/index.ts index b2978f8f3..dee880aee 100644 --- a/surfsense_web/components/tool-ui/index.ts +++ b/surfsense_web/components/tool-ui/index.ts @@ -7,13 +7,6 @@ */ export { Audio } from "./audio"; -export { - type DisplayImageArgs, - DisplayImageArgsSchema, - type DisplayImageResult, - DisplayImageResultSchema, - DisplayImageToolUI, -} from "./display-image"; export { type GenerateImageArgs, GenerateImageArgsSchema,