Skip to content
Snippets Groups Projects
Verified Commit 18aff951 authored by Lesley Razzaghian's avatar Lesley Razzaghian Committed by GitLab
Browse files

Dynamically populate Duo Chat slash command suggestions based on URL

EE: true
Changelog: added
parent d3c3f5b9
No related branches found
No related tags found
1 merge request!173052Resolve "Display Adaptive Slash Command Menu"
query getAiSlashCommands($url: String!) {
aiSlashCommands(url: $url) {
description
name
shouldSubmit
}
}
......@@ -14,7 +14,8 @@ import chatMutation from 'ee/ai/graphql/chat.mutation.graphql';
import duoUserFeedbackMutation from 'ee/ai/graphql/duo_user_feedback.mutation.graphql';
import Tracking from '~/tracking';
import { i18n, GENIE_CHAT_RESET_MESSAGE, GENIE_CHAT_CLEAR_MESSAGE } from 'ee/ai/constants';
import { TANUKI_BOT_TRACKING_EVENT_NAME, SLASH_COMMANDS, MESSAGE_TYPES } from '../constants';
import getAiSlashCommands from 'ee/ai/graphql/get_ai_slash_commands.query.graphql';
import { TANUKI_BOT_TRACKING_EVENT_NAME, MESSAGE_TYPES } from '../constants';
import TanukiBotSubscriptions from './tanuki_bot_subscriptions.vue';
export default {
......@@ -35,7 +36,6 @@ export default {
__('How do I create a template?'),
],
},
SLASH_COMMANDS,
helpPagePath: helpPagePath('policy/experiment-beta-support', { anchor: 'beta' }),
components: {
DuoChat,
......@@ -77,6 +77,22 @@ export default {
this.onError(err);
},
},
aiSlashCommands: {
query: getAiSlashCommands,
variables() {
return {
url: typeof window !== 'undefined' && window.location ? window.location.href : '',
};
},
result({ data }) {
if (data?.aiSlashCommands) {
this.aiSlashCommands = data.aiSlashCommands;
}
},
error(err) {
this.onError(err);
},
},
},
data() {
return {
......@@ -87,6 +103,7 @@ export default {
isResponseTracked: false,
cancelledRequestIds: [],
completedRequestId: null,
aiSlashCommands: [],
};
},
computed: {
......@@ -258,7 +275,7 @@ export default {
<duo-chat
id="duo-chat"
:slash-commands="$options.SLASH_COMMANDS"
:slash-commands="aiSlashCommands"
:title="$options.i18n.gitlabChat"
:messages="messages"
:error="error"
......
......@@ -6,24 +6,6 @@ export const MESSAGE_TYPES = {
TANUKI: GENIE_CHAT_MODEL_ROLES.assistant,
};
export const SLASH_COMMANDS = [
{
name: '/reset',
shouldSubmit: true,
description: s__('DuoChat|Reset conversation and ignore the previous messages.'),
},
{
name: '/clear',
shouldSubmit: true,
description: s__('DuoChat|Delete all messages in this conversation.'),
},
{
name: '/help',
shouldSubmit: true,
description: s__('DuoChat|Learn what Duo Chat can do.'),
},
];
export const SOURCE_TYPES = {
HANDBOOK: {
value: 'handbook',
......
......@@ -20,6 +20,7 @@ import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { duoChatGlobalState } from '~/super_sidebar/constants';
import { describeSkipVue3, SkipReason } from 'helpers/vue3_conditional';
import getAiSlashCommands from 'ee/ai/graphql/get_ai_slash_commands.query.graphql';
import {
MOCK_USER_MESSAGE,
......@@ -58,6 +59,7 @@ describeSkipVue3(skipReason, () => {
const chatMutationHandlerMock = jest.fn().mockResolvedValue(MOCK_TANUKI_BOT_MUTATATION_RES);
const duoUserFeedbackMutationHandlerMock = jest.fn().mockResolvedValue({});
const queryHandlerMock = jest.fn().mockResolvedValue(MOCK_CHAT_CACHED_MESSAGES_RES);
const slashCommandsQueryHandlerMock = jest.fn().mockResolvedValue(MOCK_SLASH_COMMANDS);
const feedbackData = {
feedbackChoices: ['useful', 'not_relevant'],
......@@ -92,6 +94,7 @@ describeSkipVue3(skipReason, () => {
[chatMutation, chatMutationHandlerMock],
[duoUserFeedbackMutation, duoUserFeedbackMutationHandlerMock],
[getAiMessages, queryHandlerMock],
[getAiSlashCommands, slashCommandsQueryHandlerMock],
]);
wrapper = shallowMountExtended(TanukiBotChatApp, {
......@@ -161,9 +164,35 @@ describeSkipVue3(skipReason, () => {
expect(findDuoChat().props('badgeType')).toBe(null);
});
it('passes the correct slashCommands prop to DuoChat', () => {
it('calls the slash commands GraphQL query when component loads', () => {
expect(slashCommandsQueryHandlerMock).toHaveBeenCalledWith({
url: 'http://test.host/',
});
});
it('passes the correct slash commands to the DuoChat component', async () => {
createComponent();
expect(findDuoChat().props('slashCommands')).toEqual(MOCK_SLASH_COMMANDS);
await waitForPromises();
const duoChat = findDuoChat();
expect(duoChat.props('slashCommands')).toEqual([
{
description: 'Reset conversation and ignore previous messages.',
name: '/reset',
shouldSubmit: true,
},
{
description: 'Delete all messages in the current conversation.',
name: '/clear',
shouldSubmit: true,
},
{
description: 'Learn what Duo Chat can do.',
name: '/help',
shouldSubmit: true,
},
]);
});
it('renders the duo-chat-callout component', () => {
......
import { MESSAGE_TYPES, SOURCE_TYPES } from 'ee/ai/tanuki_bot/constants';
import { PROMO_URL } from '~/constants';
export const MOCK_SLASH_COMMANDS = [
{
name: '/reset',
shouldSubmit: true,
description: 'Reset conversation and ignore the previous messages.',
},
{
name: '/clear',
shouldSubmit: true,
description: 'Delete all messages in this conversation.',
},
{
name: '/help',
shouldSubmit: true,
description: 'Learn what Duo Chat can do.',
export const MOCK_SLASH_COMMANDS = {
data: {
aiSlashCommands: [
{
description: 'Reset conversation and ignore previous messages.',
name: '/reset',
shouldSubmit: true,
},
{
description: 'Delete all messages in the current conversation.',
name: '/clear',
shouldSubmit: true,
},
{
description: 'Learn what Duo Chat can do.',
name: '/help',
shouldSubmit: true,
},
],
},
];
};
export const MOCK_SOURCE_TYPES = {
HANDBOOK: {
......
......@@ -20313,9 +20313,6 @@ msgstr ""
msgid "DuoChat|Ask a question about GitLab"
msgstr ""
 
msgid "DuoChat|Delete all messages in this conversation."
msgstr ""
msgid "DuoChat|For example, %{linkStart}what is a fork%{linkEnd}?"
msgstr ""
 
......@@ -20331,15 +20328,9 @@ msgstr ""
msgid "DuoChat|Included references"
msgstr ""
 
msgid "DuoChat|Learn what Duo Chat can do."
msgstr ""
msgid "DuoChat|No results found"
msgstr ""
 
msgid "DuoChat|Reset conversation and ignore the previous messages."
msgstr ""
msgid "DuoChat|Search %{categoryLabel}..."
msgstr ""
 
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment