diff --git a/app/javascript/dashboard/components/widgets/conversation/ConversationSummary.vue b/app/javascript/dashboard/components/widgets/conversation/ConversationSummary.vue index 2ece5e0f5..769dc571a 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ConversationSummary.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ConversationSummary.vue @@ -7,6 +7,8 @@ import { useMessageFormatter } from 'shared/composables/useMessageFormatter'; import { FEATURE_FLAGS } from 'dashboard/featureFlags'; import TasksAPI from 'dashboard/api/captain/tasks'; import Button from 'dashboard/components-next/button/Button.vue'; +import { useTrack } from 'dashboard/composables'; +import { CAPTAIN_EVENTS } from 'dashboard/helper/AnalyticsHelper/events'; const props = defineProps({ chat: { @@ -74,6 +76,10 @@ const toggleSummary = async () => { return; } isExpanded.value = true; + useTrack(CAPTAIN_EVENTS.SUMMARIZE_USED, { + conversationId: props.chat.id, + uiFrom: 'conversation_list', + }); // Only fetch if no cached summary if (!cachedSummary.value && !error.value) { await fetchSummary(); diff --git a/app/javascript/dashboard/composables/useCopilotReply.js b/app/javascript/dashboard/composables/useCopilotReply.js index 492bcb43e..7c1a2551e 100644 --- a/app/javascript/dashboard/composables/useCopilotReply.js +++ b/app/javascript/dashboard/composables/useCopilotReply.js @@ -34,11 +34,21 @@ function getEventPrefix(action) { * @param {string} action - The action type * @param {number} conversationId - The conversation ID * @param {number} [followUpCount] - Optional follow-up count + * @param {string} [uiFrom] - Optional UI source identifier * @returns {Object} The payload object */ -function buildPayload(action, conversationId, followUpCount = undefined) { +function buildPayload( + action, + conversationId, + followUpCount = undefined, + uiFrom = undefined +) { const payload = { conversationId }; + if (uiFrom) { + payload.uiFrom = uiFrom; + } + // Add operation for rewrite actions if (REWRITE_ACTIONS.includes(action)) { payload.operation = action; @@ -75,6 +85,7 @@ export function useCopilotReply() { const trackedConversationId = ref(null); const conversationId = computed(() => currentChat.value?.id); + const uiFrom = 'editor'; const isActive = computed(() => showEditor.value || isGenerating.value); const isButtonDisabled = computed( @@ -97,7 +108,8 @@ export function useCopilotReply() { buildPayload( currentAction.value, trackedConversationId.value, - followUpCount.value + followUpCount.value, + uiFrom ) ); } @@ -168,7 +180,7 @@ export function useCopilotReply() { const eventKey = `${getEventPrefix(action)}_USED`; useTrack( CAPTAIN_EVENTS[eventKey], - buildPayload(action, trackedConversationId.value) + buildPayload(action, trackedConversationId.value, undefined, uiFrom) ); } isGenerating.value = false; @@ -194,6 +206,7 @@ export function useCopilotReply() { // Track follow-up sent event useTrack(CAPTAIN_EVENTS.FOLLOW_UP_SENT, { conversationId: trackedConversationId.value, + uiFrom, }); followUpCount.value += 1; @@ -237,7 +250,8 @@ export function useCopilotReply() { buildPayload( currentAction.value, trackedConversationId.value, - followUpCount.value + followUpCount.value, + uiFrom ) ); } diff --git a/app/javascript/dashboard/routes/dashboard/conversation/ConversationSummary.vue b/app/javascript/dashboard/routes/dashboard/conversation/ConversationSummary.vue index a25740426..782e2d410 100644 --- a/app/javascript/dashboard/routes/dashboard/conversation/ConversationSummary.vue +++ b/app/javascript/dashboard/routes/dashboard/conversation/ConversationSummary.vue @@ -8,6 +8,8 @@ import { FEATURE_FLAGS } from 'dashboard/featureFlags'; import TasksAPI from 'dashboard/api/captain/tasks'; import Button from 'dashboard/components-next/button/Button.vue'; import Spinner from 'dashboard/components-next/spinner/Spinner.vue'; +import { useTrack } from 'dashboard/composables'; +import { CAPTAIN_EVENTS } from 'dashboard/helper/AnalyticsHelper/events'; const props = defineProps({ conversationId: { @@ -34,6 +36,7 @@ const cachedSummaryAt = computed( () => currentChat.value?.cached_summary_at || 0 ); const lastActivityAt = computed(() => currentChat.value?.last_activity_at || 0); +const uiFrom = 'conversation_sidebar'; const isStale = computed(() => { if (!cachedSummaryAt.value) return true; @@ -77,7 +80,28 @@ const fetchSummary = async (forceRegenerate = false) => { } }; -const regenerate = () => fetchSummary(true); +const trackSummary = action => { + useTrack(CAPTAIN_EVENTS.SUMMARIZE_USED, { + conversationId: props.conversationId, + uiFrom, + action, + }); +}; + +const generateSummary = () => { + trackSummary('generate'); + return fetchSummary(false); +}; + +const regenerate = () => { + trackSummary('regenerate'); + return fetchSummary(true); +}; + +const retryGenerate = () => { + trackSummary('retry'); + return fetchSummary(true); +}; watch( () => props.conversationId, @@ -107,7 +131,7 @@ defineExpose({ size="sm" variant="link" class="ml-2" - @click="() => fetchSummary(true)" + @click="retryGenerate" /> @@ -119,7 +143,7 @@ defineExpose({ :label="t('CONVERSATION_SIDEBAR.SUMMARY.GENERATE')" icon="i-material-symbols-auto-awesome" size="sm" - @click="() => fetchSummary(false)" + @click="generateSummary" />