diff --git a/assets/javascripts/discourse/connectors/post-text-selection-buttons-after/ai-helper-options-menu.gjs b/assets/javascripts/discourse/connectors/post-text-selection-buttons-after/ai-helper-options-menu.gjs new file mode 100644 index 00000000..c31f14ac --- /dev/null +++ b/assets/javascripts/discourse/connectors/post-text-selection-buttons-after/ai-helper-options-menu.gjs @@ -0,0 +1,123 @@ +import Component from '@glimmer/component'; +import DButton from "discourse/components/d-button"; +import { tracked } from "@glimmer/tracking"; +import { action } from "@ember/object"; +import { ajax } from "discourse/lib/ajax"; +import showAIHelper from "../../lib/show-ai-helper"; +import eq from "truth-helpers/helpers/eq"; +import { popupAjaxError } from "discourse/lib/ajax-error"; +import I18n from "I18n"; + +const i18n = I18n.t.bind(I18n); + +export default class AIHelperOptionsMenu extends Component { + + + static shouldRender(outletArgs, helper) { + return showAIHelper(outletArgs, helper); + } + @tracked helperOptions = []; + @tracked menuState = this.MENU_STATES.triggers; + @tracked loading = false; + @tracked suggestion = ""; + + MENU_STATES = { + triggers: "TRIGGERS", + options: "OPTIONS", + loading: "LOADING", + result: "RESULT" + }; + + @tracked _activeAIRequest = null; + + + constructor() { + super(...arguments); + + if (this.helperOptions.length === 0) { + this.loadPrompts(); + } + } + + @action + async showAIHelperOptions() { + this.args.outletArgs.hidePrimaryActions(); + this.menuState = this.MENU_STATES.options; + } + + @action + async performAISuggestion(option) { + this.menuState = this.MENU_STATES.loading; + + this._activeAIRequest = ajax("/discourse-ai/ai-helper/suggest", { + method: "POST", + data: { + mode: option.value, + text: this.args.outletArgs.data.quoteState.buffer, + custom_prompt: "", + } + }); + + this._activeAIRequest.then(({ suggestions }) => { + this.suggestion = suggestions[0]; + }).catch(popupAjaxError).finally(() => { + this.loading = false; + this.menuState = this.MENU_STATES.result; + }); + + return this._activeAIRequest; + } + + @action + cancelAIAction() { + if (this._activeAIRequest) { + this._activeAIRequest.abort(); + this._activeAIRequest = null; + this.loading = false; + this.menuState = this.MENU_STATES.options; + } + } + + async loadPrompts() { + let prompts = await ajax("/discourse-ai/ai-helper/prompts"); + + const promptsToRemove = ["generate_titles", "markdown_table", "custom_prompt"]; + + this.helperOptions = prompts.filter(item => !promptsToRemove.includes(item.name)).map((p) => { + return { + name: p.translated_name, + value: p.id, + icon: p.icon, + }; + }); + } +} \ No newline at end of file diff --git a/assets/stylesheets/modules/ai-helper/common/ai-helper.scss b/assets/stylesheets/modules/ai-helper/common/ai-helper.scss index b292571d..03631fc8 100644 --- a/assets/stylesheets/modules/ai-helper/common/ai-helper.scss +++ b/assets/stylesheets/modules/ai-helper/common/ai-helper.scss @@ -319,3 +319,17 @@ transform: rotate(359deg); } } + +.ai-post-helper { + &__options { + display: flex; + flex-flow: column nowrap; + align-items: flex-start; + gap: 0.25rem; + justify-content: flex-start; + } + + &__suggestion { + padding: 1rem; + } +} diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 91c2b612..2ab2f7ba 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -66,6 +66,10 @@ en: title: "Custom Prompt" placeholder: "Enter a custom prompt..." submit: "Send Prompt" + post_options_menu: + trigger: "Ask AI" + loading: "AI is generating" + close: "Close" reviewables: model_used: "Model used:" accuracy: "Accuracy:" diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 767d3d30..c498e366 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -107,6 +107,7 @@ en: proofread: Proofread text markdown_table: Generate Markdown table custom_prompt: "Custom Prompt" + explain: "Explain" ai_bot: personas: diff --git a/lib/modules/ai_helper/llm_prompt.rb b/lib/modules/ai_helper/llm_prompt.rb index 07185e7a..01d5e693 100644 --- a/lib/modules/ai_helper/llm_prompt.rb +++ b/lib/modules/ai_helper/llm_prompt.rb @@ -64,6 +64,8 @@ module DiscourseAi "comment" when "rewrite" "pen" + when "explain" + "question" else nil end diff --git a/lib/modules/ai_helper/topic_helper.rb b/lib/modules/ai_helper/topic_helper.rb index e5b9d364..3368f5c8 100644 --- a/lib/modules/ai_helper/topic_helper.rb +++ b/lib/modules/ai_helper/topic_helper.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module DiscourseAi module AiHelper class TopicHelper @@ -16,10 +17,7 @@ module DiscourseAi topic = reply_to.topic llm_prompt = - DiscourseAi::AiHelper::LlmPrompt - .new - .available_prompts(name_filter: "explain") - .first + DiscourseAi::AiHelper::LlmPrompt.new.available_prompts(name_filter: "explain").first prompt = CompletionPrompt.find_by(id: llm_prompt[:id]) prompt.messages.first["content"] << <<~MSG @@ -40,11 +38,7 @@ module DiscourseAi MSG - DiscourseAi::AiHelper::LlmPrompt.new.generate_and_send_prompt( - prompt, - nil, - ) - + DiscourseAi::AiHelper::LlmPrompt.new.generate_and_send_prompt(prompt, nil) end end end