diff --git a/app/controllers/discourse_ai/ai_bot/conversations_controller.rb b/app/controllers/discourse_ai/ai_bot/conversations_controller.rb deleted file mode 100644 index ee569b8a..00000000 --- a/app/controllers/discourse_ai/ai_bot/conversations_controller.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: true - -module DiscourseAi - module AiBot - class ConversationsController < ::ApplicationController - requires_plugin ::DiscourseAi::PLUGIN_NAME - requires_login - - def index - page = params[:page].to_i - per_page = params[:per_page]&.to_i || 40 - - bot_user_ids = EntryPoint.all_bot_ids - base_query = - Topic - .private_messages_for_user(current_user) - .joins(:topic_users) - .where(topic_users: { user_id: bot_user_ids }) - .distinct - total = base_query.count - pms = base_query.order(last_posted_at: :desc).offset(page * per_page).limit(per_page) - - render json: { - conversations: serialize_data(pms, BasicTopicSerializer), - meta: { - total: total, - page: page, - per_page: per_page, - has_more: total > (page + 1) * per_page, - }, - } - end - end - end -end diff --git a/assets/javascripts/discourse/components/ai-bot-header-icon.gjs b/assets/javascripts/discourse/components/ai-bot-header-icon.gjs index 3cbda25c..1907f517 100644 --- a/assets/javascripts/discourse/components/ai-bot-header-icon.gjs +++ b/assets/javascripts/discourse/components/ai-bot-header-icon.gjs @@ -9,7 +9,6 @@ export default class AiBotHeaderIcon extends Component { @service currentUser; @service siteSettings; @service composer; - @service router; get bots() { const availableBots = this.currentUser.ai_enabled_chat_bots @@ -25,9 +24,6 @@ export default class AiBotHeaderIcon extends Component { @action compose() { - if (this.siteSettings.ai_enable_experimental_bot_ux) { - return this.router.transitionTo("discourse-ai-bot-conversations"); - } composeAiBotMessage(this.bots[0], this.composer); } diff --git a/assets/javascripts/discourse/components/ai-bot-sidebar-new-conversation.gjs b/assets/javascripts/discourse/components/ai-bot-sidebar-new-conversation.gjs deleted file mode 100644 index 915b8283..00000000 --- a/assets/javascripts/discourse/components/ai-bot-sidebar-new-conversation.gjs +++ /dev/null @@ -1,27 +0,0 @@ -import Component from "@glimmer/component"; -import { service } from "@ember/service"; -import DButton from "discourse/components/d-button"; -import { AI_CONVERSATIONS_PANEL } from "../services/ai-conversations-sidebar-manager"; - -export default class AiBotSidebarNewConversation extends Component { - @service router; - @service sidebarState; - - get shouldRender() { - return ( - this.router.currentRouteName !== "discourse-ai-bot-conversations" && - this.sidebarState.isCurrentPanel(AI_CONVERSATIONS_PANEL) - ); - } - - - {{#if this.shouldRender}} - - {{/if}} - -} diff --git a/assets/javascripts/discourse/controllers/discourse-ai-bot-conversations.js b/assets/javascripts/discourse/controllers/discourse-ai-bot-conversations.js deleted file mode 100644 index c23923a3..00000000 --- a/assets/javascripts/discourse/controllers/discourse-ai-bot-conversations.js +++ /dev/null @@ -1,70 +0,0 @@ -import Controller from "@ember/controller"; -import { action } from "@ember/object"; -import { service } from "@ember/service"; -import { tracked } from "@ember-compat/tracked-built-ins"; - -export default class DiscourseAiBotConversations extends Controller { - @service aiBotConversationsHiddenSubmit; - @service currentUser; - - @tracked selectedPersona = this.personaOptions[0].username; - - textarea = null; - - init() { - super.init(...arguments); - this.selectedPersonaChanged(this.selectedPersona); - } - - get personaOptions() { - if (this.currentUser.ai_enabled_personas) { - return this.currentUser.ai_enabled_personas - .filter((persona) => persona.username) - .map((persona) => { - return { - id: persona.id, - username: persona.username, - name: persona.name, - description: persona.description, - }; - }); - } - } - - get displayPersonaSelector() { - return this.personaOptions.length > 1; - } - - get filterable() { - return this.personaOptions.length > 4; - } - - @action - selectedPersonaChanged(username) { - this.selectedPersona = username; - this.aiBotConversationsHiddenSubmit.personaUsername = username; - } - - @action - updateInputValue(event) { - this._autoExpandTextarea(); - this.aiBotConversationsHiddenSubmit.inputValue = event.target.value; - } - - @action - handleKeyDown(event) { - if (event.key === "Enter" && !event.shiftKey) { - this.aiBotConversationsHiddenSubmit.submitToBot(); - } - } - - @action - setTextArea(element) { - this.textarea = element; - } - - _autoExpandTextarea() { - this.textarea.style.height = "auto"; - this.textarea.style.height = this.textarea.scrollHeight + "px"; - } -} diff --git a/assets/javascripts/discourse/discourse-ai-bot-dashboard-route-map.js b/assets/javascripts/discourse/discourse-ai-bot-dashboard-route-map.js deleted file mode 100644 index 0c5b9213..00000000 --- a/assets/javascripts/discourse/discourse-ai-bot-dashboard-route-map.js +++ /dev/null @@ -1,5 +0,0 @@ -export default function () { - this.route("discourse-ai-bot-conversations", { - path: "/discourse-ai/ai-bot/conversations", - }); -} diff --git a/assets/javascripts/discourse/lib/ai-bot-helper.js b/assets/javascripts/discourse/lib/ai-bot-helper.js index d7fb0132..69832586 100644 --- a/assets/javascripts/discourse/lib/ai-bot-helper.js +++ b/assets/javascripts/discourse/lib/ai-bot-helper.js @@ -23,43 +23,24 @@ export function showShareConversationModal(modal, topicId) { .catch(popupAjaxError); } -export async function composeAiBotMessage( - targetBot, - composer, - options = { - skipFocus: false, - topicBody: "", - personaUsername: null, - } -) { +export function composeAiBotMessage(targetBot, composer) { const currentUser = composer.currentUser; const draftKey = "new_private_message_ai_" + new Date().getTime(); - let botUsername; - if (targetBot) { - botUsername = currentUser.ai_enabled_chat_bots.find( - (bot) => bot.model_name === targetBot - )?.username; - } else if (options.personaUsername) { - botUsername = options.personaUsername; - } else { - botUsername = currentUser.ai_enabled_chat_bots[0].username; - } + let botUsername = currentUser.ai_enabled_chat_bots.find( + (bot) => bot.model_name === targetBot + ).username; - const data = { - action: Composer.PRIVATE_MESSAGE, - recipients: botUsername, - topicTitle: i18n("discourse_ai.ai_bot.default_pm_prefix"), - archetypeId: "private_message", - draftKey, - hasGroups: false, - warningsDisabled: true, - }; - - if (options.skipFocus) { - data.topicBody = options.topicBody; - await composer.open(data); - } else { - composer.focusComposer({ fallbackToNewTopic: true, openOpts: data }); - } + composer.focusComposer({ + fallbackToNewTopic: true, + openOpts: { + action: Composer.PRIVATE_MESSAGE, + recipients: botUsername, + topicTitle: i18n("discourse_ai.ai_bot.default_pm_prefix"), + archetypeId: "private_message", + draftKey, + hasGroups: false, + warningsDisabled: true, + }, + }); } diff --git a/assets/javascripts/discourse/services/ai-bot-conversations-hidden-submit.js b/assets/javascripts/discourse/services/ai-bot-conversations-hidden-submit.js deleted file mode 100644 index 7796007d..00000000 --- a/assets/javascripts/discourse/services/ai-bot-conversations-hidden-submit.js +++ /dev/null @@ -1,62 +0,0 @@ -import { action } from "@ember/object"; -import { next } from "@ember/runloop"; -import Service, { service } from "@ember/service"; -import { popupAjaxError } from "discourse/lib/ajax-error"; -import { i18n } from "discourse-i18n"; -import { composeAiBotMessage } from "../lib/ai-bot-helper"; - -export default class AiBotConversationsHiddenSubmit extends Service { - @service composer; - @service aiConversationsSidebarManager; - @service dialog; - - personaUsername; - - inputValue = ""; - - @action - focusInput() { - this.composer.destroyDraft(); - this.composer.close(); - next(() => { - document.getElementById("custom-homepage-input").focus(); - }); - } - - @action - async submitToBot() { - this.composer.destroyDraft(); - this.composer.close(); - - if (this.inputValue.length < 10) { - return this.dialog.alert({ - message: i18n( - "discourse_ai.ai_bot.conversations.min_input_length_message" - ), - didConfirm: () => this.focusInput(), - didCancel: () => this.focusInput(), - }); - } - - // we are intentionally passing null as the targetBot to allow for the - // function to select the first available bot. This will be refactored in the - // future to allow for selecting a specific bot. - await composeAiBotMessage(null, this.composer, { - skipFocus: true, - topicBody: this.inputValue, - personaUsername: this.personaUsername, - }); - - try { - await this.composer.save(); - this.aiConversationsSidebarManager.newTopicForceSidebar = true; - if (this.inputValue.length > 10) { - // prevents submitting same message again when returning home - // but avoids deleting too-short message on submit - this.inputValue = ""; - } - } catch (e) { - popupAjaxError(e); - } - } -} diff --git a/assets/javascripts/discourse/services/ai-conversations-sidebar-manager.js b/assets/javascripts/discourse/services/ai-conversations-sidebar-manager.js deleted file mode 100644 index ce41d0f1..00000000 --- a/assets/javascripts/discourse/services/ai-conversations-sidebar-manager.js +++ /dev/null @@ -1,40 +0,0 @@ -import { tracked } from "@glimmer/tracking"; -import Service, { service } from "@ember/service"; -import { ADMIN_PANEL, MAIN_PANEL } from "discourse/lib/sidebar/panels"; - -export const AI_CONVERSATIONS_PANEL = "ai-conversations"; - -export default class AiConversationsSidebarManager extends Service { - @service sidebarState; - - @tracked newTopicForceSidebar = false; - - forceCustomSidebar() { - // Set the panel to your custom panel - this.sidebarState.setPanel(AI_CONVERSATIONS_PANEL); - - // Use separated mode to ensure independence from hamburger menu - this.sidebarState.setSeparatedMode(); - - // Hide panel switching buttons to keep UI clean - this.sidebarState.hideSwitchPanelButtons(); - - this.sidebarState.isForcingSidebar = true; - document.body.classList.add("has-ai-conversations-sidebar"); - return true; - } - - stopForcingCustomSidebar() { - // This method is called when leaving your route - // Only restore main panel if we previously forced ours - document.body.classList.remove("has-ai-conversations-sidebar"); - const isAdminSidebarActive = - this.sidebarState.currentPanel?.key === ADMIN_PANEL; - // only restore main panel if we previously forced our sidebar - // and not if we are in admin sidebar - if (this.sidebarState.isForcingSidebar && !isAdminSidebarActive) { - this.sidebarState.setPanel(MAIN_PANEL); // Return to main sidebar panel - this.sidebarState.isForcingSidebar = false; - } - } -} diff --git a/assets/javascripts/discourse/templates/discourse-ai-bot-conversations.gjs b/assets/javascripts/discourse/templates/discourse-ai-bot-conversations.gjs deleted file mode 100644 index 0085e06b..00000000 --- a/assets/javascripts/discourse/templates/discourse-ai-bot-conversations.gjs +++ /dev/null @@ -1,51 +0,0 @@ -import { hash } from "@ember/helper"; -import { on } from "@ember/modifier"; -import didInsert from "@ember/render-modifiers/modifiers/did-insert"; -import RouteTemplate from "ember-route-template"; -import DButton from "discourse/components/d-button"; -import { i18n } from "discourse-i18n"; -import DropdownSelectBox from "select-kit/components/dropdown-select-box"; - -export default RouteTemplate( - - - {{#if @controller.displayPersonaSelector}} - - - - {{/if}} - - - - {{i18n "discourse_ai.ai_bot.conversations.header"}} - - - - - - {{i18n "discourse_ai.ai_bot.conversations.disclaimer"}} - - - - -); diff --git a/assets/javascripts/initializers/ai-conversations-sidebar.js b/assets/javascripts/initializers/ai-conversations-sidebar.js deleted file mode 100644 index 662624f5..00000000 --- a/assets/javascripts/initializers/ai-conversations-sidebar.js +++ /dev/null @@ -1,256 +0,0 @@ -import { tracked } from "@glimmer/tracking"; -import { TrackedArray } from "@ember-compat/tracked-built-ins"; -import { ajax } from "discourse/lib/ajax"; -import { bind } from "discourse/lib/decorators"; -import { withPluginApi } from "discourse/lib/plugin-api"; -import { i18n } from "discourse-i18n"; -import AiBotSidebarNewConversation from "../discourse/components/ai-bot-sidebar-new-conversation"; -import { isPostFromAiBot } from "../discourse/lib/ai-bot-helper"; -import { AI_CONVERSATIONS_PANEL } from "../discourse/services/ai-conversations-sidebar-manager"; - -export default { - name: "ai-conversations-sidebar", - - initialize() { - withPluginApi((api) => { - const currentUser = api.container.lookup("service:current-user"); - if (!currentUser) { - return; - } - - const aiConversationsSidebarManager = api.container.lookup( - "service:ai-conversations-sidebar-manager" - ); - const appEvents = api.container.lookup("service:app-events"); - const messageBus = api.container.lookup("service:message-bus"); - - api.addSidebarPanel( - (BaseCustomSidebarPanel) => - class AiConversationsSidebarPanel extends BaseCustomSidebarPanel { - key = AI_CONVERSATIONS_PANEL; - hidden = true; - displayHeader = true; - expandActiveSection = true; - } - ); - - api.renderInOutlet("sidebar-footer-actions", AiBotSidebarNewConversation); - api.addSidebarSection( - (BaseCustomSidebarSection, BaseCustomSidebarSectionLink) => { - const AiConversationLink = class extends BaseCustomSidebarSectionLink { - route = "topic.fromParamsNear"; - - constructor(topic) { - super(...arguments); - this.topic = topic; - } - - get name() { - return this.topic.title; - } - - get models() { - return [ - this.topic.slug, - this.topic.id, - this.topic.last_read_post_number || 0, - ]; - } - - get title() { - return this.topic.title; - } - - get text() { - return this.topic.title; - } - - get classNames() { - return `ai-conversation-${this.topic.id}`; - } - }; - - return class extends BaseCustomSidebarSection { - @tracked links = new TrackedArray(); - @tracked topics = []; - @tracked hasMore = []; - page = 0; - isFetching = false; - totalTopicsCount = 0; - - constructor() { - super(...arguments); - this.fetchMessages(); - - appEvents.on("topic:created", this, "addNewMessageToSidebar"); - } - - @bind - willDestroy() { - this.removeScrollListener(); - appEvents.on("topic:created", this, "addNewMessageToSidebar"); - } - - get name() { - return "ai-conversations-history"; - } - - get text() { - return i18n( - "discourse_ai.ai_bot.conversations.messages_sidebar_title" - ); - } - - get sidebarElement() { - return document.querySelector( - ".sidebar-wrapper .sidebar-sections" - ); - } - - addNewMessageToSidebar(topic) { - this.addNewMessage(topic); - this.watchForTitleUpdate(topic); - } - - @bind - removeScrollListener() { - const sidebar = this.sidebarElement; - if (sidebar) { - sidebar.removeEventListener("scroll", this.scrollHandler); - } - } - - @bind - attachScrollListener() { - const sidebar = this.sidebarElement; - if (sidebar) { - sidebar.addEventListener("scroll", this.scrollHandler); - } - } - - @bind - scrollHandler() { - const sidebarElement = this.sidebarElement; - if (!sidebarElement) { - return; - } - - const scrollPosition = sidebarElement.scrollTop; - const scrollHeight = sidebarElement.scrollHeight; - const clientHeight = sidebarElement.clientHeight; - - // When user has scrolled to bottom with a small threshold - if (scrollHeight - scrollPosition - clientHeight < 100) { - if (this.hasMore && !this.isFetching) { - this.loadMore(); - } - } - } - - async fetchMessages(isLoadingMore = false) { - if (this.isFetching) { - return; - } - - try { - this.isFetching = true; - const data = await ajax( - "/discourse-ai/ai-bot/conversations.json", - { - data: { page: this.page, per_page: 40 }, - } - ); - - if (isLoadingMore) { - this.topics = [...this.topics, ...data.conversations]; - } else { - this.topics = data.conversations; - } - - this.totalTopicsCount = data.meta.total; - this.hasMore = data.meta.has_more; - this.isFetching = false; - this.removeScrollListener(); - this.buildSidebarLinks(); - this.attachScrollListener(); - } catch { - this.isFetching = false; - } - } - - loadMore() { - if (this.isFetching || !this.hasMore) { - return; - } - - this.page = this.page + 1; - this.fetchMessages(true); - } - - buildSidebarLinks() { - this.links = this.topics.map( - (topic) => new AiConversationLink(topic) - ); - } - - addNewMessage(newTopic) { - this.links = [new AiConversationLink(newTopic), ...this.links]; - } - - watchForTitleUpdate(topic) { - const channel = `/discourse-ai/ai-bot/topic/${topic.topic_id}`; - const topicId = topic.topic_id; - const callback = this.updateTopicTitle.bind(this); - messageBus.subscribe(channel, ({ title }) => { - callback(topicId, title); - messageBus.unsubscribe(channel); - }); - } - - updateTopicTitle(topicId, title) { - // update the topic title in the sidebar, instead of the default title - const text = document.querySelector( - `.sidebar-section-link-wrapper .ai-conversation-${topicId} .sidebar-section-link-content-text` - ); - if (text) { - text.innerText = title; - } - } - }; - }, - AI_CONVERSATIONS_PANEL - ); - - const setSidebarPanel = (transition) => { - if (transition?.to?.name === "discourse-ai-bot-conversations") { - return aiConversationsSidebarManager.forceCustomSidebar(); - } - - const topic = api.container.lookup("controller:topic").model; - if ( - topic?.archetype === "private_message" && - topic.postStream.posts.some((post) => - isPostFromAiBot(post, currentUser) - ) - ) { - return aiConversationsSidebarManager.forceCustomSidebar(); - } - - // newTopicForceSidebar is set to true when a new topic is created. We have - // this because the condition `postStream.posts` above will not be true as the bot response - // is not in the postStream yet when this initializer is ran. So we need to force - // the sidebar to open when creating a new topic. After that, we set it to false again. - if (aiConversationsSidebarManager.newTopicForceSidebar) { - aiConversationsSidebarManager.newTopicForceSidebar = false; - return aiConversationsSidebarManager.forceCustomSidebar(); - } - - aiConversationsSidebarManager.stopForcingCustomSidebar(); - }; - - api.container - .lookup("service:router") - .on("routeDidChange", setSidebarPanel); - }); - }, -}; diff --git a/assets/stylesheets/modules/ai-bot-conversations/common.scss b/assets/stylesheets/modules/ai-bot-conversations/common.scss deleted file mode 100644 index 3bff178f..00000000 --- a/assets/stylesheets/modules/ai-bot-conversations/common.scss +++ /dev/null @@ -1,325 +0,0 @@ -// Hide the new question button from the hamburger menu's footer -.hamburger-panel .ai-new-question-button { - display: none; -} - -body.has-ai-conversations-sidebar { - .sidebar-wrapper { - .sidebar-footer-actions { - display: flex; - flex-direction: column; - margin-left: 0; - align-items: flex-end; - width: 100%; - - .ai-new-question-button { - width: 100%; - } - } - - .sidebar-container { - border: none; - } - - // ai related sidebar content - [data-section-name="ai-conversations-history"] { - .sidebar-section-header-wrapper { - pointer-events: none; - font-size: var(--font-down-1); - - .sidebar-section-header-caret { - display: none; - } - - .sidebar-section-header-text { - letter-spacing: 0.5px; - } - } - - .sidebar-section-link-wrapper { - .sidebar-section-link { - height: unset; - padding-block: 0.65em; - font-size: var(--font-down-1); - letter-spacing: 0.35px; - border-radius: 0 var(--border-radius) var(--border-radius) 0; - - .sidebar-section-link-content-text { - white-space: normal; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 2; - overflow: hidden; - } - } - } - - .sidebar-section-link-prefix { - align-self: start; - } - } - } - - // topic elements - #topic-footer-button-share-and-invite, - body:not(.staff) #topic-footer-button-archive, - #topic-footer-buttons .topic-notifications-button, - .bookmark-menu-trigger, - .more-topics__container, - .private-message-glyph-wrapper, - .topic-header-participants, - .topic-above-footer-buttons-outlet, - .topic-map, - .timeline-ago, - #topic-footer-buttons .topic-footer-main-buttons details { - display: none; - } - - .topic-timer-info { - border: none; - } - - .topic-owner .actions .create-flag { - // why flag my own post - display: none; - } - - .container.posts { - margin-bottom: 0; - - .topic-navigation.with-timeline { - top: calc(var(--header-offset, 60px) + 5.5em); - } - - .topic-navigation { - .topic-notifications-button { - display: none; - } - } - } - - #topic-title { - display: flex; - justify-content: center; - width: 100%; - - .title-wrapper { - width: 100%; - max-width: 960px; - } - } - - .small-action, - .onscreen-post .row { - justify-content: center; - } - - #topic-footer-buttons { - width: calc(100% - 6.5em); - margin-top: 0; - - @media screen and (max-width: 924px) { - max-width: unset; - width: 100%; - } - - @media screen and (min-width: 1300px) { - width: 100%; - max-width: 51em; - } - - .topic-footer-main-buttons { - justify-content: flex-end; - - @media screen and (min-width: 1180px) { - margin-right: 0.6em; - } - - @media screen and (max-width: 924px) { - margin-right: 0.6em; - } - } - } - - #topic-progress-wrapper.docked { - display: none; - } - - @media screen and (max-width: 924px) { - .archetype-private_message .topic-post:last-child { - margin-bottom: 0; - } - } - - nav.post-controls .actions button { - padding: 0.5em 0.65em; - - &.reply { - .d-icon { - margin-right: 0.45em; - } - } - } - - .topic-footer-main-buttons { - margin-left: calc(var(--topic-avatar-width) - 1.15em); - } - - .ai-bot-conversations { - height: calc(100dvh - var(--header-offset) - 1.25em); - - @media screen and (min-width: 675px) { - border: 1px solid var(--primary-low); - padding: 2em 2em 3em; - border-radius: var(--border-radius); - height: calc(100dvh - var(--header-offset) - 10em); - } - - &__persona-selector { - display: flex; - justify-content: flex-end; - } - - &__content-wrapper { - display: flex; - flex-direction: column; - box-sizing: border-box; - align-items: center; - justify-content: center; - height: 100%; - } - - &__input-wrapper { - display: flex; - align-items: stretch; - gap: 0.5em; - width: 100%; - max-width: 90dvw; - margin-top: 2em; - - @media screen and (min-width: 600px) { - width: 80%; - max-width: 46em; - } - - .btn-primary { - align-self: end; - min-height: 2.5em; - } - - #ai-bot-conversations-input { - width: 100%; - margin: 0; - resize: none; - border-radius: var(--d-button-border-radius); - max-height: 30vh; - - &:focus { - outline: none; - border-color: var(--primary-high); - } - } - } - - h1 { - margin-bottom: 0.45em; - max-width: 20em; - text-align: center; - font-size: var(--font-up-6); - line-height: var(--line-height-medium); - - @media screen and (min-height: 300px) { - margin-top: -1em; - } - - @media screen and (min-height: 600px) { - margin-top: -3em; - } - - @media screen and (min-height: 900px) { - margin-top: -6em; - } - } - - .ai-disclaimer { - text-align: center; - font-size: var(--font-down-1); - color: var(--primary-700); - - @media screen and (min-width: 600px) { - width: 80%; - max-width: 46em; - } - } - - .sidebar-footer-wrapper { - display: flex; - - .powered-by-discourse { - display: block; - } - - button { - display: none; - } - } - } - - // composer - .reply-details .dropdown-select-box.composer-actions, - .composer-fields { - display: none; - } - - // hide user stuff - .new-user-wrapper { - .user-navigation { - display: none; - } - } - - .user-main .about.collapsed-info .details { - display: none; - } - - .user-content { - margin-top: 0; - } - - @media screen and (max-width: 600px) { - .share-ai-conversation-button { - .d-icon { - margin: 0; - } - - .d-button-label { - display: none; - } - } - } - - .mobile-view { - nav.post-controls .actions button.reply .d-icon { - margin: 0; - } - - .search-dropdown { - display: none; - } - - .sidebar-custom-sections { - display: none; - } - } - - // custom user card link - .user-card-meta__profile-link { - display: block; - padding: 0.5em 0 0.25em; - - .d-icon { - font-size: var(--font-down-1); - margin-right: 0.15em; - } - } -} diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 2a5f7138..1811de61 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -716,14 +716,6 @@ en: 5-pro: "Gemini" mixtral-8x7B-Instruct-V0: "1": "Mixtral-8x7B V0.1" - conversations: - header: "What can I help with?" - submit: "Submit question" - disclaimer: "Generative AI can make mistakes. Verify important information." - placeholder: "Ask a question..." - new: "New Question" - min_input_length_message: "Message must be longer than 10 characters" - messages_sidebar_title: "Conversations" sentiments: dashboard: title: "Sentiment" diff --git a/config/routes.rb b/config/routes.rb index a41c966a..c5df0fc7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -37,10 +37,6 @@ DiscourseAi::Engine.routes.draw do get "/preview/:topic_id" => "shared_ai_conversations#preview" end - scope module: :ai_bot, path: "/ai-bot/conversations" do - get "/" => "conversations#index" - end - scope module: :ai_bot, path: "/ai-bot/artifacts" do get "/:id" => "artifacts#show" get "/:id/:version" => "artifacts#show" diff --git a/config/settings.yml b/config/settings.yml index cf679d7a..c8d9fb8d 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -390,7 +390,3 @@ discourse_ai: ai_rag_images_enabled: default: false hidden: true - ai_enable_experimental_bot_ux: - default: false - client: true - diff --git a/plugin.rb b/plugin.rb index e83d8df7..e495f250 100644 --- a/plugin.rb +++ b/plugin.rb @@ -43,8 +43,6 @@ register_asset "stylesheets/modules/ai-bot/common/ai-persona.scss" register_asset "stylesheets/modules/ai-bot/common/ai-discobot-discoveries.scss" register_asset "stylesheets/modules/ai-bot/mobile/ai-persona.scss", :mobile -register_asset "stylesheets/modules/ai-bot-conversations/common.scss" - register_asset "stylesheets/modules/embeddings/common/semantic-related-topics.scss" register_asset "stylesheets/modules/embeddings/common/semantic-search.scss" diff --git a/spec/system/ai_bot/personal_message_spec.rb b/spec/system/ai_bot/personal_message_spec.rb deleted file mode 100644 index 0dd76355..00000000 --- a/spec/system/ai_bot/personal_message_spec.rb +++ /dev/null @@ -1,185 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe "AI Bot - Personal Message", type: :system do - let(:topic_page) { PageObjects::Pages::Topic.new } - let(:composer) { PageObjects::Components::Composer.new } - let(:ai_pm_homepage) { PageObjects::Components::AiPmHomepage.new } - let(:sidebar) { PageObjects::Components::NavigationMenu::Sidebar.new } - let(:header_dropdown) { PageObjects::Components::NavigationMenu::HeaderDropdown.new } - let(:dialog) { PageObjects::Components::Dialog.new } - - fab!(:user) { Fabricate(:user, refresh_auto_groups: true) } - - fab!(:claude_2) do - Fabricate( - :llm_model, - provider: "anthropic", - url: "https://api.anthropic.com/v1/messages", - name: "claude-2", - ) - end - fab!(:bot_user) do - toggle_enabled_bots(bots: [claude_2]) - SiteSetting.ai_bot_enabled = true - claude_2.reload.user - end - fab!(:bot) do - persona = - AiPersona - .find(DiscourseAi::Personas::Persona.system_personas[DiscourseAi::Personas::General]) - .class_instance - .new - DiscourseAi::Personas::Bot.as(bot_user, persona: persona) - end - - fab!(:pm) do - Fabricate( - :private_message_topic, - title: "This is my special PM", - user: user, - topic_allowed_users: [ - Fabricate.build(:topic_allowed_user, user: user), - Fabricate.build(:topic_allowed_user, user: bot_user), - ], - ) - end - fab!(:first_post) do - Fabricate(:post, topic: pm, user: user, post_number: 1, raw: "This is a reply by the user") - end - fab!(:second_post) do - Fabricate(:post, topic: pm, user: bot_user, post_number: 2, raw: "This is a bot reply") - end - fab!(:third_post) do - Fabricate( - :post, - topic: pm, - user: user, - post_number: 3, - raw: "This is a second reply by the user", - ) - end - fab!(:topic_user) { Fabricate(:topic_user, topic: pm, user: user) } - fab!(:topic_bot_user) { Fabricate(:topic_user, topic: pm, user: bot_user) } - - fab!(:persona) do - persona = - AiPersona.create!( - name: "Test Persona", - description: "A test persona", - allowed_group_ids: [Group::AUTO_GROUPS[:trust_level_0]], - enabled: true, - system_prompt: "You are a helpful bot", - ) - - persona.create_user! - persona.update!( - default_llm_id: claude_2.id, - allow_chat_channel_mentions: true, - allow_topic_mentions: true, - ) - persona - end - - before do - SiteSetting.ai_enable_experimental_bot_ux = true - SiteSetting.ai_bot_enabled = true - Jobs.run_immediately! - SiteSetting.ai_bot_allowed_groups = "#{Group::AUTO_GROUPS[:trust_level_0]}" - sign_in(user) - end - - it "has normal bot interaction when `ai_enable_experimental_bot_ux` is disabled" do - SiteSetting.ai_enable_experimental_bot_ux = false - visit "/" - find(".ai-bot-button").click - - expect(ai_pm_homepage).to have_no_homepage - expect(composer).to be_opened - end - - context "when `ai_enable_experimental_bot_ux` is enabled" do - it "renders landing page on bot click" do - visit "/" - find(".ai-bot-button").click - expect(ai_pm_homepage).to have_homepage - expect(sidebar).to be_visible - end - - it "displays error when message is too short" do - visit "/" - find(".ai-bot-button").click - - ai_pm_homepage.input.fill_in(with: "a") - ai_pm_homepage.submit - expect(ai_pm_homepage).to have_too_short_dialog - dialog.click_yes - expect(composer).to be_closed - end - - it "renders sidebar even when navigation menu is set to header" do - SiteSetting.navigation_menu = "header dropdown" - visit "/" - find(".ai-bot-button").click - expect(ai_pm_homepage).to have_homepage - expect(sidebar).to be_visible - expect(header_dropdown).to be_visible - end - - it "hides default content in the sidebar" do - visit "/" - find(".ai-bot-button").click - - expect(ai_pm_homepage).to have_homepage - expect(sidebar).to have_no_tags_section - expect(sidebar).to have_no_section("categories") - expect(sidebar).to have_no_section("messages") - expect(sidebar).to have_no_section("chat-dms") - expect(sidebar).to have_no_section("chat-channels") - expect(sidebar).to have_no_section("user-threads") - end - - it "shows the bot conversation in the sidebar" do - visit "/" - find(".ai-bot-button").click - - expect(ai_pm_homepage).to have_homepage - expect(sidebar).to have_section("ai-conversations-history") - expect(sidebar).to have_section_link(pm.title) - expect(sidebar).to have_no_css("button.ai-new-question-button") - end - - it "navigates to the bot conversation when clicked" do - visit "/" - find(".ai-bot-button").click - - expect(ai_pm_homepage).to have_homepage - sidebar.find( - ".sidebar-section[data-section-name='ai-conversations-history'] a.sidebar-section-link", - ).click - expect(topic_page).to have_topic_title(pm.title) - end - - it "displays sidebar and 'new question' on the topic page" do - topic_page.visit_topic(pm) - expect(sidebar).to be_visible - expect(sidebar).to have_css("button.ai-new-question-button") - end - - it "redirect to the homepage when 'new question' is clicked" do - topic_page.visit_topic(pm) - expect(sidebar).to be_visible - sidebar.find("button.ai-new-question-button").click - expect(ai_pm_homepage).to have_homepage - end - - it "can send a new message to the bot" do - topic_page.visit_topic(pm) - topic_page.click_reply_button - expect(composer).to be_opened - - composer.fill_in(with: "Hello bot replying to you") - composer.submit - expect(page).to have_content("Hello bot replying to you") - end - end -end diff --git a/spec/system/page_objects/components/ai_pm_homepage.rb b/spec/system/page_objects/components/ai_pm_homepage.rb deleted file mode 100644 index 8b158522..00000000 --- a/spec/system/page_objects/components/ai_pm_homepage.rb +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -module PageObjects - module Components - class AiPmHomepage < PageObjects::Components::Base - HOMEPAGE_WRAPPER_CLASS = ".ai-bot-conversations__content-wrapper" - - def input - page.find("#ai-bot-conversations-input") - end - - def submit - page.find(".ai-conversation-submit").click - end - - def has_too_short_dialog? - page.find( - ".dialog-content", - text: I18n.t("js.discourse_ai.ai_bot.conversations.min_input_length_message"), - ) - end - - def has_homepage? - page.has_css?(HOMEPAGE_WRAPPER_CLASS) - end - - def has_no_homepage? - page.has_no_css?(HOMEPAGE_WRAPPER_CLASS) - end - end - end -end diff --git a/test/javascripts/acceptance/post-helper-menu-test.js b/test/javascripts/acceptance/post-helper-menu-test.js index c8bf67f5..3100d7c3 100644 --- a/test/javascripts/acceptance/post-helper-menu-test.js +++ b/test/javascripts/acceptance/post-helper-menu-test.js @@ -50,8 +50,6 @@ acceptance("AI Helper - Post Helper Menu", function (needs) { done: false, }); }); - - server.get("/discourse-ai/ai-bot/conversations.json", () => {}); }); test("displays streamed explanation", async function (assert) { diff --git a/test/javascripts/acceptance/topic-summary-test.js b/test/javascripts/acceptance/topic-summary-test.js index be8a3e87..11290c04 100644 --- a/test/javascripts/acceptance/topic-summary-test.js +++ b/test/javascripts/acceptance/topic-summary-test.js @@ -29,8 +29,6 @@ acceptance("Topic - Summary", function (needs) { done: false, }); }); - - server.get("/discourse-ai/ai-bot/conversations.json", () => {}); }); needs.hooks.beforeEach(() => {
- {{i18n "discourse_ai.ai_bot.conversations.disclaimer"}} -