From e15df9d949cb06ce0d1294ab0e8f0e9e2ea486d2 Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Tue, 2 Jun 2026 20:13:31 +0530 Subject: [PATCH 01/26] feat(migration): add automation_runs table to gateway migration --- .../versions/149_add_gateway_tables.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/surfsense_backend/alembic/versions/149_add_gateway_tables.py b/surfsense_backend/alembic/versions/149_add_gateway_tables.py index 888da0691..a77e6a69b 100644 --- a/surfsense_backend/alembic/versions/149_add_gateway_tables.py +++ b/surfsense_backend/alembic/versions/149_add_gateway_tables.py @@ -54,6 +54,17 @@ USER_COLS = [ "premium_credit_micros_used", ] +AUTOMATION_RUN_COLS = [ + "id", + "automation_id", + "trigger_id", + "status", + "step_results", + "started_at", + "finished_at", + "created_at", +] + def _has_zero_version(conn, table: str) -> bool: return ( conn.execute( @@ -150,7 +161,8 @@ def _build_set_table_ddl( f"new_chat_messages, " f"chat_comments, " f"chat_session_state, " - f'"user" ({_cols(user_cols)})' + f'"user" ({_cols(user_cols)}), ' + f"automation_runs ({_cols(AUTOMATION_RUN_COLS)})" ) @@ -523,7 +535,7 @@ def downgrade() -> None: if exists: documents_has_zero_ver = _has_zero_version(conn, "documents") user_has_zero_ver = _has_zero_version(conn, "user") - # Restore the publication shape from migration 143. + # Restore the publication shape from migration 148. doc_cols = DOCUMENT_COLS + (['"_0_version"'] if documents_has_zero_ver else []) user_cols = USER_COLS + (['"_0_version"'] if user_has_zero_ver else []) ddl = ( @@ -535,7 +547,8 @@ def downgrade() -> None: f"new_chat_messages, " f"chat_comments, " f"chat_session_state, " - f'"user" ({_cols(user_cols)})' + f'"user" ({_cols(user_cols)}), ' + f"automation_runs ({_cols(AUTOMATION_RUN_COLS)})" ) tx = conn.begin_nested() if conn.in_transaction() else conn.begin() with tx: From 5fce4e162133ddf7ac499e4211e1095fb700376a Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Tue, 2 Jun 2026 22:52:48 +0530 Subject: [PATCH 02/26] feat(chat): enhance ChatViewport with conditional footer rendering and update ChatExamplePrompts for improved category selection --- .../components/assistant-ui/chat-viewport.tsx | 22 ++-- .../new-chat/chat-example-prompts.tsx | 114 ++++++++++++------ surfsense_web/lib/chat/example-prompts.ts | 4 - 3 files changed, 87 insertions(+), 53 deletions(-) diff --git a/surfsense_web/components/assistant-ui/chat-viewport.tsx b/surfsense_web/components/assistant-ui/chat-viewport.tsx index cb0fd2005..83308b642 100644 --- a/surfsense_web/components/assistant-ui/chat-viewport.tsx +++ b/surfsense_web/components/assistant-ui/chat-viewport.tsx @@ -1,6 +1,6 @@ "use client"; -import { ThreadPrimitive } from "@assistant-ui/react"; +import { AuiIf, ThreadPrimitive } from "@assistant-ui/react"; import { ArrowDownIcon } from "lucide-react"; import type { FC, ReactNode } from "react"; import { Button } from "@/components/ui/button"; @@ -40,15 +40,17 @@ export const ChatViewport: FC = ({ children, footer }) => ( /> {children} {footer ? ( - -
- - {footer} -
-
+ !thread.isEmpty}> + +
+ + {footer} +
+
+
) : null} ); diff --git a/surfsense_web/components/new-chat/chat-example-prompts.tsx b/surfsense_web/components/new-chat/chat-example-prompts.tsx index 95d7a0eaa..f36247f37 100644 --- a/surfsense_web/components/new-chat/chat-example-prompts.tsx +++ b/surfsense_web/components/new-chat/chat-example-prompts.tsx @@ -1,10 +1,17 @@ "use client"; -import { CornerDownLeft, Lightbulb } from "lucide-react"; -import { memo, useCallback } from "react"; +import { + FilePlus2, + Search, + Settings2, + type LucideIcon, + WandSparkles, + Workflow, + X, +} from "lucide-react"; +import { memo, useCallback, useState } from "react"; import { Button } from "@/components/ui/button"; import { ScrollArea } from "@/components/ui/scroll-area"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { CHAT_EXAMPLE_CATEGORIES } from "@/lib/chat/example-prompts"; interface ChatExamplePromptsProps { @@ -12,6 +19,13 @@ interface ChatExamplePromptsProps { onSelect: (prompt: string) => void; } +const CATEGORY_ICONS: Record = { + search: Search, + create: FilePlus2, + automate: Workflow, + tools: Settings2, +}; + const ExamplePromptButton = memo(function ExamplePromptButton({ prompt, onSelect, @@ -26,50 +40,72 @@ const ExamplePromptButton = memo(function ExamplePromptButton({ type="button" variant="ghost" onClick={handleClick} - className="h-auto w-full items-start justify-start gap-2.5 whitespace-normal rounded-md border bg-background px-3 py-2 text-left font-normal text-muted-foreground hover:bg-accent hover:text-accent-foreground" + className="h-auto w-full items-start justify-start whitespace-normal rounded-lg bg-transparent px-2.5 py-1.5 text-left font-normal text-muted-foreground shadow-none hover:bg-foreground/10 hover:text-foreground sm:rounded-xl sm:px-3 sm:py-2" > -