diff --git a/packages/app/src/components/chat/ChatMessage.vue b/packages/app/src/components/chat/ChatMessage.vue
index 6731c729..bd516a10 100644
--- a/packages/app/src/components/chat/ChatMessage.vue
+++ b/packages/app/src/components/chat/ChatMessage.vue
@@ -43,6 +43,25 @@
>
+
+
+
()
+function toggleFeedback(value: 'up' | 'down') {
+ const newValue = props.message.feedback === value ? undefined : value
+ emit('feedback', props.message.id, newValue)
+}
+
// Editing state
const isEditing = ref(false)
const editContent = ref('')
diff --git a/packages/app/src/components/chat/ChatWindow.vue b/packages/app/src/components/chat/ChatWindow.vue
index 91d0c3dd..62ed97e6 100644
--- a/packages/app/src/components/chat/ChatWindow.vue
+++ b/packages/app/src/components/chat/ChatWindow.vue
@@ -74,6 +74,7 @@
@regenerate="handleRegenerate"
@branch="handleBranch"
@reply="handleReply"
+ @feedback="handleFeedback"
/>
@@ -249,6 +250,12 @@ function handleBranch(messageId: string) {
chatStore.branchFromMessage(convId, messageId)
}
+function handleFeedback(messageId: string, value: 'up' | 'down' | undefined) {
+ const convId = chatStore.activeConversationId
+ if (!convId) return
+ chatStore.setMessageFeedback(convId, messageId, value)
+}
+
function handleExtract(text: string) {
// Run content extraction without sending to AI
const convId = chatStore.activeConversationId ?? chatStore.createConversation()
diff --git a/packages/app/src/stores/chat.ts b/packages/app/src/stores/chat.ts
index bd652524..c8032bb1 100644
--- a/packages/app/src/stores/chat.ts
+++ b/packages/app/src/stores/chat.ts
@@ -222,6 +222,16 @@ export const useChatStore = defineStore('chat', () => {
}
}
+ function setMessageFeedback(conversationId: string, messageId: string, feedback: 'up' | 'down' | undefined) {
+ const conv = conversations.value.get(conversationId)
+ if (!conv) return
+ const msg = conv.messages.find((m: { id: string }) => m.id === messageId)
+ if (msg) {
+ msg.feedback = feedback
+ debouncedIDBSave(conv)
+ }
+ }
+
function switchSide() {
panelSide.value = panelSide.value === 'right' ? 'left' : 'right'
}
@@ -348,6 +358,7 @@ export const useChatStore = defineStore('chat', () => {
addMessage,
appendToLastMessage,
setMessageWebResults,
+ setMessageFeedback,
switchSide,
toggleChatCollapse,
setActiveConversation,
diff --git a/packages/core/src/types/message.ts b/packages/core/src/types/message.ts
index 0fc7a8bb..717b2a82 100644
--- a/packages/core/src/types/message.ts
+++ b/packages/core/src/types/message.ts
@@ -32,6 +32,8 @@ export interface Message {
editedAt?: number
/** Attached images (base64, max 4) for vision-capable models */
images?: ImageAttachment[]
+ /** User feedback: 'up' = thumbs up, 'down' = thumbs down */
+ feedback?: 'up' | 'down'
}
export interface Reaction {