From 616bbced9caa7ae5302209c90b942b86fb1da7d7 Mon Sep 17 00:00:00 2001 From: Vishnu Narayanan Date: Sat, 1 Mar 2025 04:50:39 +0530 Subject: [PATCH] feat: allow copilot use without connecting an inbox (#10992) This PR allows Copilot to be used without connecting the Captain assistant to an inbox. Currently, if Captain is enabled on an account, it takes over conversations and responds directly to users. This PR enables the use of Captain as a Copilot without allowing it to respond to users. Additionally, it allows using a different assistant for Copilot instead of the default Captain assistant. The selection logic for the Copilot assistant follows this order of preference: - If the user has selected a specific assistant, it takes first preference for Copilot. - If the above is not available, the assistant connected to the inbox takes preference. - If neither of the above is available, the first assistant in the account takes preference. --- .../dashboard/api/inbox/conversation.js | 4 + .../components-next/copilot/Copilot.vue | 35 ++++++-- .../copilot/ToggleCopilotAssistant.vue | 81 +++++++++++++++++++ .../dropdown-menu/base/DropdownBody.vue | 2 +- .../components/copilot/CopilotContainer.vue | 59 +++++++++++++- .../i18n/locale/en/integrations.json | 3 +- .../store/modules/conversations/actions.js | 9 +++ .../store/modules/conversations/getters.js | 4 + .../store/modules/conversations/index.js | 4 + .../specs/conversations/actions.spec.js | 19 +++++ .../specs/conversations/getters.spec.js | 17 ++++ .../specs/conversations/mutations.spec.js | 16 ++++ .../dashboard/store/mutation-types.js | 3 + config/routes.rb | 1 + .../v1/accounts/conversations_controller.rb | 22 ++++- 15 files changed, 265 insertions(+), 14 deletions(-) create mode 100644 app/javascript/dashboard/components-next/copilot/ToggleCopilotAssistant.vue diff --git a/app/javascript/dashboard/api/inbox/conversation.js b/app/javascript/dashboard/api/inbox/conversation.js index 8b9eacf3f..39546096f 100644 --- a/app/javascript/dashboard/api/inbox/conversation.js +++ b/app/javascript/dashboard/api/inbox/conversation.js @@ -137,6 +137,10 @@ class ConversationApi extends ApiClient { requestCopilot(conversationId, body) { return axios.post(`${this.url}/${conversationId}/copilot`, body); } + + getInboxAssistant(conversationId) { + return axios.get(`${this.url}/${conversationId}/inbox_assistant`); + } } export default new ConversationApi(); diff --git a/app/javascript/dashboard/components-next/copilot/Copilot.vue b/app/javascript/dashboard/components-next/copilot/Copilot.vue index cf867789b..e284bb983 100644 --- a/app/javascript/dashboard/components-next/copilot/Copilot.vue +++ b/app/javascript/dashboard/components-next/copilot/Copilot.vue @@ -7,6 +7,7 @@ import CopilotInput from './CopilotInput.vue'; import CopilotLoader from './CopilotLoader.vue'; import CopilotAgentMessage from './CopilotAgentMessage.vue'; import CopilotAssistantMessage from './CopilotAssistantMessage.vue'; +import ToggleCopilotAssistant from './ToggleCopilotAssistant.vue'; import Icon from '../icon/Icon.vue'; const props = defineProps({ @@ -26,9 +27,17 @@ const props = defineProps({ type: String, required: true, }, + assistants: { + type: Array, + default: () => [], + }, + activeAssistant: { + type: Object, + default: () => ({}), + }, }); -const emit = defineEmits(['sendMessage', 'reset']); +const emit = defineEmits(['sendMessage', 'reset', 'setAssistant']); const COPILOT_USER_ROLES = ['assistant', 'system']; @@ -97,14 +106,18 @@ watch( -
-
+ +
+
{{ $t('COPILOT.TRY_THESE_PROMPTS') }}
-
+
+ +
+
+ +
-
+
diff --git a/app/javascript/dashboard/components-next/copilot/ToggleCopilotAssistant.vue b/app/javascript/dashboard/components-next/copilot/ToggleCopilotAssistant.vue new file mode 100644 index 000000000..ec21cec9f --- /dev/null +++ b/app/javascript/dashboard/components-next/copilot/ToggleCopilotAssistant.vue @@ -0,0 +1,81 @@ + + + diff --git a/app/javascript/dashboard/components-next/dropdown-menu/base/DropdownBody.vue b/app/javascript/dashboard/components-next/dropdown-menu/base/DropdownBody.vue index 246eba5aa..1a67aaa68 100644 --- a/app/javascript/dashboard/components-next/dropdown-menu/base/DropdownBody.vue +++ b/app/javascript/dashboard/components-next/dropdown-menu/base/DropdownBody.vue @@ -19,7 +19,7 @@ const beforeClass = computed(() => { // Add extra blur layer only when strong prop is true, as a hack for Chrome's stacked backdrop-blur limitation // https://issues.chromium.org/issues/40835530 - return "before:content-['\x00A0'] before:absolute before:bottom-0 before:left-0 before:w-full before:h-full before:backdrop-contrast-70 before:backdrop-blur-sm before:z-0 [&>*]:relative"; + return "before:content-['\x00A0'] before:absolute before:bottom-0 before:left-0 before:w-full before:h-full before:rounded-xl before:backdrop-contrast-70 before:backdrop-blur-sm before:z-0 [&>*]:relative"; }); diff --git a/app/javascript/dashboard/components/copilot/CopilotContainer.vue b/app/javascript/dashboard/components/copilot/CopilotContainer.vue index 17d35d82a..0a4638730 100644 --- a/app/javascript/dashboard/components/copilot/CopilotContainer.vue +++ b/app/javascript/dashboard/components/copilot/CopilotContainer.vue @@ -1,8 +1,11 @@