From 027a1b1e6ed7ff97e03568b5e93ba11a493daac3 Mon Sep 17 00:00:00 2001 From: David Sima Date: Mon, 3 Aug 2026 16:24:03 +0300 Subject: [PATCH] feat(ai-assistant): include query and collectionId in feedback payload Stamp the triggering query and the collection the server ran against onto the AI message when the response streams in, persist them across sessionStorage, and send them in the POST /feedback/{requestId} body alongside score/scoreType. --- .../ai-assistant/ai-assistant_api-client.js | 20 +++++++++++++++++-- .../ai-assistant/ai-assistant_chat-bubble.js | 4 ++++ .../ai-assistant_chat-controller.js | 8 +++++++- .../ai-assistant/ai-assistant_chat-history.js | 12 ++++++++++- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/hlx_statics/blocks/ai-assistant/ai-assistant_api-client.js b/hlx_statics/blocks/ai-assistant/ai-assistant_api-client.js index ed7c7cb5f..477e85333 100644 --- a/hlx_statics/blocks/ai-assistant/ai-assistant_api-client.js +++ b/hlx_statics/blocks/ai-assistant/ai-assistant_api-client.js @@ -201,9 +201,25 @@ export class AiApiClient { * @param {'THUMBS_UP_DOWN'} [options.type] * @param {number} options.score * @param {string} options.requestId + * @param {string} [options.query] - The user query that triggered the rated response + * @param {string|null} [options.collectionId] - The collection the query was run against + * @param {string} [options.comment] - Optional free-text feedback comment */ - async submitFeedback({ type = "THUMBS_UP_DOWN", score, requestId }) { + async submitFeedback({ + type = "THUMBS_UP_DOWN", + score, + requestId, + query, + collectionId, + comment, + }) { try { + /** @type {Record} */ + const payload = { scoreType: type, score }; + if (query !== undefined) payload.query = query; + if (collectionId !== undefined) payload.collectionId = collectionId; + if (comment !== undefined) payload.comment = comment; + const response = await fetch( `${this.baseUrl}${AiApiClient.FEEDBACK_ENDPOINT}/${requestId}`, { @@ -212,7 +228,7 @@ export class AiApiClient { "Content-Type": "application/json", "X-Api-Key": this.apiKey, }, - body: JSON.stringify({ scoreType: type, score }), + body: JSON.stringify(payload), }, ); diff --git a/hlx_statics/blocks/ai-assistant/ai-assistant_chat-bubble.js b/hlx_statics/blocks/ai-assistant/ai-assistant_chat-bubble.js index 1e490259a..943e12a8c 100644 --- a/hlx_statics/blocks/ai-assistant/ai-assistant_chat-bubble.js +++ b/hlx_statics/blocks/ai-assistant/ai-assistant_chat-bubble.js @@ -245,9 +245,13 @@ export class ChatBubble { // don't unselect on click if (button.dataset.selected === "true") return; + const message = chatHistory.findById(requestId); + const success = await aiApiClient.submitFeedback({ score, requestId, + query: message?.context?.query, + collectionId: message?.context?.collectionId, }); if (success) { diff --git a/hlx_statics/blocks/ai-assistant/ai-assistant_chat-controller.js b/hlx_statics/blocks/ai-assistant/ai-assistant_chat-controller.js index b0e73a2d3..0159fc1be 100644 --- a/hlx_statics/blocks/ai-assistant/ai-assistant_chat-controller.js +++ b/hlx_statics/blocks/ai-assistant/ai-assistant_chat-controller.js @@ -383,7 +383,13 @@ export const handleUserQuery = async ( callbacks: { onMetadata: (data) => { if (data.requestId) { - chatHistory.updateLast({ id: data.requestId }); + chatHistory.updateLast({ + id: data.requestId, + context: { + query: messageContent, + collectionId: data.collectionId ?? null, + }, + }); targetBubble.setMessageId(data.requestId); } }, diff --git a/hlx_statics/blocks/ai-assistant/ai-assistant_chat-history.js b/hlx_statics/blocks/ai-assistant/ai-assistant_chat-history.js index f0b686d72..2f4cc1424 100644 --- a/hlx_statics/blocks/ai-assistant/ai-assistant_chat-history.js +++ b/hlx_statics/blocks/ai-assistant/ai-assistant_chat-history.js @@ -6,6 +6,14 @@ * @property {string} title */ +/** + * The request context that produced an AI response. + * Used to enrich feedback submissions. + * @typedef {Object} ChatMessageContext + * @property {string} query - The user query that triggered this response + * @property {string|null} collectionId - The collection the query ran agains + */ + /** * @typedef {Object} ChatMessage * @property {string} [id] @@ -14,6 +22,7 @@ * @property {ChatReference[]} [references] * @property {string|null|number} [timestamp] * @property {{type: 'THUMBS_UP_DOWN'; score: 0|1}} [feedback] + * @property {ChatMessageContext} [context] - For AI messages: how the response was generated */ /** @@ -222,13 +231,14 @@ export class ChatHistory { */ _sanitizeMessages(messages) { return messages.map( - ({ id, content, source, references, timestamp, feedback }) => ({ + ({ id, content, source, references, timestamp, feedback, context }) => ({ ...(id && { id }), content, source, ...(references?.length && { references }), ...(timestamp && { timestamp }), ...(feedback && { feedback }), + ...(context && { context }), }), ); }