feat(feedback): feedback button, per-message thumbs, PostHog events#3623
feat(feedback): feedback button, per-message thumbs, PostHog events#3623rafavalls wants to merge 6 commits into
Conversation
Adds a Feedback menu item to the account popover that opens a general feedback modal. Adds thumbs up/thumbs down actions on each assistant chat message — thumbs up tracks a positive signal, thumbs down opens a structured "Share feedback" modal with reason chips and optional details. All events are sent to PostHog with thread_id, message_id, message content snippet, and a session_replay_url for direct recording links. Removes Terms of Use and Privacy Policy from the account menu. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🧪 BenchmarkShould we run the Virtual MCP strategy benchmark for this PR? React with 👍 to run the benchmark.
Benchmark will run on the next push after you react. |
Release OptionsSuggested: Minor ( React with an emoji to override the release type:
Current version:
|
There was a problem hiding this comment.
4 issues found across 5 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/mesh/src/web/components/chat/message/parts/text-part.tsx">
<violation number="1" location="apps/mesh/src/web/components/chat/message/parts/text-part.tsx:46">
P2: Positive feedback events miss `message_content`. Add snippet like negative flow so analytics stays consistent per message.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| const handleThumbsUp = () => { | ||
| if (feedback === "positive") { | ||
| setFeedback(null); | ||
| track("chat_message_feedback_positive_undone", { |
There was a problem hiding this comment.
P2: Positive feedback events miss message_content. Add snippet like negative flow so analytics stays consistent per message.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/mesh/src/web/components/chat/message/parts/text-part.tsx, line 46:
<comment>Positive feedback events miss `message_content`. Add snippet like negative flow so analytics stays consistent per message.</comment>
<file context>
@@ -35,8 +40,30 @@ export function MessageTextPart({
+ const handleThumbsUp = () => {
+ if (feedback === "positive") {
+ setFeedback(null);
+ track("chat_message_feedback_positive_undone", {
+ message_id: id,
+ thread_id: threadId,
</file context>
There was a problem hiding this comment.
Disagree — omitting message_content from the positive event is intentional, not an oversight.
The negative flow originally included it but it was removed because chat messages in this MCP control plane regularly contain API keys, OAuth tokens, and connection strings. Sending raw message content to PostHog (a third-party SaaS) is a data leak risk regardless of whether the feedback is positive or negative.
Both flows use message_id + thread_id for correlation. Full content can be retrieved internally from those IDs. Keeping the two events symmetric means both are safe, not both are unsafe.
There was a problem hiding this comment.
Thanks for the feedback! I've saved this as a new learning to improve future reviews.
…ity and UX issues - Add POST /api/:org/feedback backend route; free-text is logged server-side instead of being sent verbatim to PostHog (chat messages may contain secrets) - Remove message_content from chat_message_feedback_negative PostHog event; message_id + thread_id are sufficient for correlation - Move getSessionReplayUrl() call to inside handleSubmit (was captured at render time, now captured at submission time) - Remove dead sending state from FeedbackDialog - Fix Ctrl/Cmd+Enter keyboard shortcut bypassing empty-feedback guard in MessageFeedbackDialog - Restore Terms of Use and Privacy Policy links to account popover - Revert showCopyButton to copyable && !!extraActions (last part only) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
4 issues found across 6 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/mesh/src/web/components/chat/message/parts/text-part.tsx">
<violation number="1" location="apps/mesh/src/web/components/chat/message/parts/text-part.tsx:46">
P2: Positive feedback events miss `message_content`. Add snippet like negative flow so analytics stays consistent per message.</violation>
</file>
<file name="apps/mesh/src/web/components/feedback-dialog.tsx">
<violation number="1" location="apps/mesh/src/web/components/feedback-dialog.tsx:35">
P2: Event name changed from expected contract. Analytics keyed on `user_feedback` will miss these submissions.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| headers: { "Content-Type": "application/json" }, | ||
| body: JSON.stringify({ message: message.trim() }), | ||
| }); | ||
| track("user_feedback_submitted", { |
There was a problem hiding this comment.
P2: Event name changed from expected contract. Analytics keyed on user_feedback will miss these submissions.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/mesh/src/web/components/feedback-dialog.tsx, line 35:
<comment>Event name changed from expected contract. Analytics keyed on `user_feedback` will miss these submissions.</comment>
<file context>
@@ -15,20 +15,26 @@ import { track, getSessionReplayUrl } from "@/web/lib/posthog-client";
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ message: message.trim() }),
+ });
+ track("user_feedback_submitted", {
session_replay_url: getSessionReplayUrl(),
});
</file context>
There was a problem hiding this comment.
Intentional. The old user_feedback event carried the raw message field in the PostHog payload — sending free-text user input to a third-party SaaS. The rename signals a schema break: user_feedback_submitted carries only session_replay_url, no message content. Any dashboards on the old event were reading PII-containing data and need to be updated to the new event name and schema regardless.
There was a problem hiding this comment.
Thanks for the feedback! I've saved this as a new learning to improve future reviews.
- FeedbackDialog.handleSubmit is now async: awaits the fetch, closes and shows success only on res.ok, shows error toast on failure; sending state disables the button and keyboard shortcut during the in-flight request - feedback.ts: wrap c.req.json() in try/catch so malformed bodies return 400 instead of 500 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Free-text feedback no longer hardcodes a destination. Introduce a typed FeedbackSink that the route awaits; default to a structured log line, and let operators swap in their own (Linear, Slack, DB, webhook) at the mount site. Final destination is still being decided. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Require auth, cap payload size, handle sink failures, and send negative chat details through POST /feedback instead of PostHog. Add unit and e2e tests. Co-authored-by: Cursor <cursoragent@cursor.com>
The root app onError handler maps thrown HTTPException to 500, breaking the unauthenticated e2e assertion. Co-authored-by: Cursor <cursoragent@cursor.com>
pedrofrxncx
left a comment
There was a problem hiding this comment.
this cant ship, we need to do another way. i'll elaborate
What is this contribution about?
Adds two feedback surfaces to Studio: a Feedback item in the account popover menu that opens a general feedback modal, and thumbs up / thumbs down buttons on each assistant chat message. Thumbs up tracks a positive signal (togglable); thumbs down opens a structured "Share feedback" modal with reason chips (Incorrect or incomplete, Not what I asked for, etc.) and an optional details field. All PostHog events include `message_id`, `thread_id`, `message_content` snippet, and a `session_replay_url` timestamped to the exact moment of feedback. Terms of Use and Privacy Policy were removed from the account menu to reduce clutter.
Screenshots/Demonstration
How to Test
user_feedback,chat_message_feedback_positive, andchat_message_feedback_negativewith expected propertiesMigration Notes
No migrations required. Requires
POSTHOG_KEYto be set for events to be captured (no-op on self-hosted installs without it).Review Checklist
Summary by cubic
Adds a Feedback button in the account menu and per‑message thumbs to collect chat feedback. Free‑text is posted to a new, org‑scoped
POST /api/:org/feedbackroute and PostHog receives safe events with session replay links.New Features
POST /api/:org/feedback(pluggableFeedbackSink, default structured log), and sendsuser_feedback_submitted.chat_message_feedback_positive,chat_message_feedback_positive_undone, andchat_message_feedback_negative.message_id,thread_id, and a timestamped session replay URL.Bug Fixes
message_contentremoved from negative events; session replay URL captured at submit time.Written for commit 67dbfa8. Summary will update on new commits.