DEV: Add front-end and lint
This commit is contained in:
parent
cd46825057
commit
d68c586b91
|
@ -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 {
|
||||
<template>
|
||||
<div class="ai-post-helper">
|
||||
{{#if (eq this.menuState this.MENU_STATES.triggers)}}
|
||||
<DButton @class="btn-flat" @icon="discourse-sparkles" @label="discourse_ai.ai_helper.post_options_menu.trigger" @action={{this.showAIHelperOptions}} />
|
||||
|
||||
{{else if (eq this.menuState this.MENU_STATES.options)}}
|
||||
<div class="ai-post-helper__options">
|
||||
{{#each this.helperOptions as |option|}}
|
||||
<DButton @class="btn-flat" @icon={{option.icon}} @translatedLabel={{option.name}} @action={{this.performAISuggestion}} @actionParam={{option}} />
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
{{else if (eq this.menuState this.MENU_STATES.loading)}}
|
||||
<div class="ai-helper-context-menu__loading">
|
||||
<div class="dot-falling"></div>
|
||||
<span>
|
||||
{{i18n "discourse_ai.ai_helper.context_menu.loading"}}
|
||||
</span>
|
||||
<DButton
|
||||
@icon="times"
|
||||
@title="discourse_ai.ai_helper.context_menu.cancel"
|
||||
@action={{this.cancelAIAction}}
|
||||
class="btn-flat cancel-request"
|
||||
/>
|
||||
</div>
|
||||
{{else if (eq this.menuState this.MENU_STATES.result)}}
|
||||
<div class="ai-post-helper__suggestion">{{this.suggestion}}</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
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,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:"
|
||||
|
|
|
@ -107,6 +107,7 @@ en:
|
|||
proofread: Proofread text
|
||||
markdown_table: Generate Markdown table
|
||||
custom_prompt: "Custom Prompt"
|
||||
explain: "Explain"
|
||||
|
||||
ai_bot:
|
||||
personas:
|
||||
|
|
|
@ -64,6 +64,8 @@ module DiscourseAi
|
|||
"comment"
|
||||
when "rewrite"
|
||||
"pen"
|
||||
when "explain"
|
||||
"question"
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
|
|
@ -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
|
|||
</post>
|
||||
MSG
|
||||
|
||||
DiscourseAi::AiHelper::LlmPrompt.new.generate_and_send_prompt(
|
||||
prompt,
|
||||
nil,
|
||||
)
|
||||
|
||||
DiscourseAi::AiHelper::LlmPrompt.new.generate_and_send_prompt(prompt, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue