From 607cf12a7fb295837b250755371288dca9b1b86a Mon Sep 17 00:00:00 2001 From: Mike Fortman Date: Wed, 13 May 2026 14:43:25 -0500 Subject: [PATCH 1/4] add feedback tracking for assistant messages --- .../chat/_components/assistant-message.tsx | 17 ++++++ .../app/chat/_components/message-actions.tsx | 54 +++++++++++++++++++ frontend/app/chat/_types/types.ts | 6 +++ frontend/app/chat/page.tsx | 26 +++------ frontend/contexts/chat-context.tsx | 11 ++-- frontend/tsconfig.json | 16 ++++-- 6 files changed, 98 insertions(+), 32 deletions(-) create mode 100644 frontend/app/chat/_components/message-actions.tsx diff --git a/frontend/app/chat/_components/assistant-message.tsx b/frontend/app/chat/_components/assistant-message.tsx index c4ac16e81..f15fd8b1f 100644 --- a/frontend/app/chat/_components/assistant-message.tsx +++ b/frontend/app/chat/_components/assistant-message.tsx @@ -11,6 +11,7 @@ const MarkdownRenderer = dynamic( { ssr: false }, ); +import { trackButton } from "@/lib/analytics"; import { cn } from "@/lib/utils"; import type { FunctionCall, @@ -18,6 +19,7 @@ import type { } from "../_types/types"; import { FunctionCalls } from "./function-calls"; import { Message } from "./message"; +import MessageActions from "./message-actions"; import { TokenUsage } from "./token-usage"; interface AssistantMessageProps { @@ -35,6 +37,7 @@ interface AssistantMessageProps { delay?: number; isInitialGreeting?: boolean; usage?: TokenUsageType; + timestamp?: Date; } export function AssistantMessage({ @@ -52,7 +55,18 @@ export function AssistantMessage({ delay = 0.2, isInitialGreeting = false, usage, + timestamp, }: AssistantMessageProps) { + const trackFeedback = (feedback: "like" | "dislike") => { + trackButton({ + action: feedback, + elementId: "message-feedback", + namespace: "chat", + CTA: feedback === "like" ? "Like Message" : "Dislike Message", + timestamp: timestamp?.getTime(), + }); + }; + return ( {usage && !isStreaming && } + {!isInitialGreeting && ( + + )} diff --git a/frontend/app/chat/_components/message-actions.tsx b/frontend/app/chat/_components/message-actions.tsx new file mode 100644 index 000000000..cc745add5 --- /dev/null +++ b/frontend/app/chat/_components/message-actions.tsx @@ -0,0 +1,54 @@ +import { ThumbsDown, ThumbsUp } from "lucide-react"; +import { useState } from "react"; +import { Button } from "@/components/ui/button"; + +interface MessageActionsProps { + trackFeedback: (feedback: "like" | "dislike") => void; +} + +const MessageActions = ({ trackFeedback }: MessageActionsProps) => { + const [feedbackSelected, setFeedbackSelected] = useState< + "like" | "dislike" | null + >(null); + + const handleFeedback = (feedback: "like" | "dislike") => { + if (feedbackSelected === feedback) return; // Prevent multiple tracking events for the same feedback + trackFeedback(feedback); + setFeedbackSelected(feedback); + }; + + return ( +
+ + +
+ ); +}; + +export default MessageActions; diff --git a/frontend/app/chat/_types/types.ts b/frontend/app/chat/_types/types.ts index cd39daba3..fde98c543 100644 --- a/frontend/app/chat/_types/types.ts +++ b/frontend/app/chat/_types/types.ts @@ -21,6 +21,12 @@ export interface Message { usage?: TokenUsage; } +export const INITIAL_ASSISTANT_MESSAGE: Message = { + role: "assistant", + content: "How can I assist?", + timestamp: new Date(), +}; + export interface FunctionCall { name: string; arguments?: Record; diff --git a/frontend/app/chat/page.tsx b/frontend/app/chat/page.tsx index 524cc991d..a2ba33fdb 100644 --- a/frontend/app/chat/page.tsx +++ b/frontend/app/chat/page.tsx @@ -29,6 +29,7 @@ import type { RequestBody, ToolCallResult, } from "./_types/types"; +import { INITIAL_ASSISTANT_MESSAGE } from "./_types/types"; function ChatPage() { const isDebugMode = process.env.NEXT_PUBLIC_OPENRAG_DEBUG === "true"; @@ -52,11 +53,7 @@ function ChatPage() { setConversationFilter, } = useChat(); const [messages, setMessages] = useState([ - { - role: "assistant", - content: "How can I assist?", - timestamp: new Date(), - }, + INITIAL_ASSISTANT_MESSAGE, ]); const [input, setInput] = useState(""); const { loading, setLoading } = useLoadingStore(); @@ -328,13 +325,7 @@ function ChatPage() { // Abort any in-flight streaming so it doesn't bleed into new chat abortStream(); // Reset chat UI even if context state was already 'new' - setMessages([ - { - role: "assistant", - content: "How can I assist?", - timestamp: new Date(), - }, - ]); + setMessages([INITIAL_ASSISTANT_MESSAGE]); setInput(""); setExpandedFunctionCalls(new Set()); setIsFilterHighlighted(false); @@ -572,13 +563,7 @@ function ChatPage() { useEffect(() => { if (placeholderConversation && currentConversationId === null) { console.log("Starting new conversation"); - setMessages([ - { - role: "assistant", - content: "How can I assist?", - timestamp: new Date(), - }, - ]); + setMessages([INITIAL_ASSISTANT_MESSAGE]); lastLoadedConversationRef.current = null; // Focus input when starting a new conversation @@ -1142,9 +1127,10 @@ function ChatPage() { isInitialGreeting={ index === 0 && messages.length === 1 && - message.content === "How can I assist?" + message === INITIAL_ASSISTANT_MESSAGE } usage={message.usage} + timestamp={message.timestamp} /> )} diff --git a/frontend/contexts/chat-context.tsx b/frontend/contexts/chat-context.tsx index 10147a3db..8eb687fca 100644 --- a/frontend/contexts/chat-context.tsx +++ b/frontend/contexts/chat-context.tsx @@ -11,6 +11,7 @@ import { useState, } from "react"; import { useGetSettingsQuery } from "@/app/api/queries/useGetSettingsQuery"; +import { INITIAL_ASSISTANT_MESSAGE } from "@/app/chat/_types/types"; export type EndpointType = "chat" | "langflow"; @@ -22,7 +23,7 @@ interface ConversationDocument { interface ConversationMessage { role: string; content: string; - timestamp?: string; + timestamp?: Date; response_id?: string; } @@ -340,13 +341,7 @@ export function ChatProvider({ children }: ChatProviderProps) { response_id: "new-conversation-" + Date.now(), title: "New conversation", endpoint: endpoint, - messages: [ - { - role: "assistant", - content: "How can I assist?", - timestamp: new Date().toISOString(), - }, - ], + messages: [INITIAL_ASSISTANT_MESSAGE], created_at: new Date().toISOString(), last_activity: new Date().toISOString(), }; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 705f5ce5e..74f656098 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,7 +1,11 @@ { "compilerOptions": { "target": "ES2017", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -11,7 +15,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "react-jsx", + "jsx": "preserve", "incremental": true, "plugins": [ { @@ -19,7 +23,9 @@ } ], "paths": { - "@/*": ["./*"] + "@/*": [ + "./*" + ] } }, "include": [ @@ -29,5 +35,7 @@ ".next/types/**/*.ts", ".next/dev/types/**/*.ts" ], - "exclude": ["node_modules"] + "exclude": [ + "node_modules" + ] } From 2367913e78f12d81ed84af816926f931b230598e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 13 May 2026 19:44:14 +0000 Subject: [PATCH 2/4] style: apply biome auto-fixes [skip ci] --- frontend/tsconfig.json | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 74f656098..4b73c4bcc 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,11 +1,7 @@ { "compilerOptions": { "target": "ES2017", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -23,9 +19,7 @@ } ], "paths": { - "@/*": [ - "./*" - ] + "@/*": ["./*"] } }, "include": [ @@ -35,7 +29,5 @@ ".next/types/**/*.ts", ".next/dev/types/**/*.ts" ], - "exclude": [ - "node_modules" - ] + "exclude": ["node_modules"] } From 3f3f3a5c4d66e2f5c95c360c248b0ce368913c88 Mon Sep 17 00:00:00 2001 From: Mike Fortman Date: Wed, 13 May 2026 14:51:09 -0500 Subject: [PATCH 3/4] don't show during onboarding --- frontend/app/chat/_components/assistant-message.tsx | 4 +++- frontend/app/onboarding/_components/onboarding-content.tsx | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/app/chat/_components/assistant-message.tsx b/frontend/app/chat/_components/assistant-message.tsx index f15fd8b1f..0d1a1bf52 100644 --- a/frontend/app/chat/_components/assistant-message.tsx +++ b/frontend/app/chat/_components/assistant-message.tsx @@ -38,6 +38,7 @@ interface AssistantMessageProps { isInitialGreeting?: boolean; usage?: TokenUsageType; timestamp?: Date; + showFeedback?: boolean; } export function AssistantMessage({ @@ -56,6 +57,7 @@ export function AssistantMessage({ isInitialGreeting = false, usage, timestamp, + showFeedback = true, }: AssistantMessageProps) { const trackFeedback = (feedback: "like" | "dislike") => { trackButton({ @@ -165,7 +167,7 @@ export function AssistantMessage({ } /> {usage && !isStreaming && } - {!isInitialGreeting && ( + {!isInitialGreeting && showFeedback && ( )} diff --git a/frontend/app/onboarding/_components/onboarding-content.tsx b/frontend/app/onboarding/_components/onboarding-content.tsx index 7ad47428d..4a4b7cf3c 100644 --- a/frontend/app/onboarding/_components/onboarding-content.tsx +++ b/frontend/app/onboarding/_components/onboarding-content.tsx @@ -287,6 +287,7 @@ export function OnboardingContent({ onToggle={() => {}} isStreaming={!!streamingMessage} isCompleted={currentStep > 3} + showFeedback={false} /> )} From 924bde920f218812a9bdc703979cf8dfb9c6c145 Mon Sep 17 00:00:00 2001 From: Mike Fortman Date: Wed, 13 May 2026 16:09:39 -0500 Subject: [PATCH 4/4] coderabbit suggestions --- frontend/app/chat/_components/assistant-message.tsx | 2 +- frontend/app/chat/_components/message-actions.tsx | 4 ++++ frontend/app/chat/page.tsx | 3 ++- frontend/contexts/chat-context.tsx | 10 ++++++++-- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/frontend/app/chat/_components/assistant-message.tsx b/frontend/app/chat/_components/assistant-message.tsx index 0d1a1bf52..02ba2e061 100644 --- a/frontend/app/chat/_components/assistant-message.tsx +++ b/frontend/app/chat/_components/assistant-message.tsx @@ -167,7 +167,7 @@ export function AssistantMessage({ } /> {usage && !isStreaming && } - {!isInitialGreeting && showFeedback && ( + {!isInitialGreeting && showFeedback && !isStreaming && ( )} diff --git a/frontend/app/chat/_components/message-actions.tsx b/frontend/app/chat/_components/message-actions.tsx index cc745add5..35bd41ce0 100644 --- a/frontend/app/chat/_components/message-actions.tsx +++ b/frontend/app/chat/_components/message-actions.tsx @@ -22,6 +22,8 @@ const MessageActions = ({ trackFeedback }: MessageActionsProps) => {