DEV: Select tool presets via DMenu instead

This commit is contained in:
Keegan George 2025-02-20 13:25:12 -08:00
parent cb5785cacd
commit 42faa6bf86
No known key found for this signature in database
GPG Key ID: 91B40E38537AC000
5 changed files with 147 additions and 150 deletions

View File

@ -1,6 +1,10 @@
import DiscourseRoute from "discourse/routes/discourse"; import DiscourseRoute from "discourse/routes/discourse";
export default class DiscourseAiToolsNewRoute extends DiscourseRoute { export default class DiscourseAiToolsNewRoute extends DiscourseRoute {
beforeModel(transition) {
this.preset = transition.to.queryParams.presetId || "empty_tool";
}
async model() { async model() {
return this.store.createRecord("ai-tool"); return this.store.createRecord("ai-tool");
} }
@ -8,10 +12,10 @@ export default class DiscourseAiToolsNewRoute extends DiscourseRoute {
setupController(controller) { setupController(controller) {
super.setupController(...arguments); super.setupController(...arguments);
const toolsModel = this.modelFor("adminPlugins.show.discourse-ai-tools"); const toolsModel = this.modelFor("adminPlugins.show.discourse-ai-tools");
controller.set("allTools", toolsModel); controller.set("allTools", toolsModel);
controller.set("presets", toolsModel.resultSetMeta.presets); controller.set("presets", toolsModel.resultSetMeta.presets);
controller.set("llms", toolsModel.resultSetMeta.llms); controller.set("llms", toolsModel.resultSetMeta.llms);
controller.set("settings", toolsModel.resultSetMeta.settings); controller.set("settings", toolsModel.resultSetMeta.settings);
controller.set("selectedPreset", this.preset);
} }
} }

View File

@ -5,5 +5,6 @@
@presets={{this.presets}} @presets={{this.presets}}
@llms={{this.llms}} @llms={{this.llms}}
@settings={{this.settings}} @settings={{this.settings}}
@selectedPreset={{this.selectedPreset}}
/> />
</section> </section>

View File

@ -13,7 +13,6 @@ import DTooltip from "discourse/components/d-tooltip";
import withEventValue from "discourse/helpers/with-event-value"; import withEventValue from "discourse/helpers/with-event-value";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import { i18n } from "discourse-i18n"; import { i18n } from "discourse-i18n";
import ComboBox from "select-kit/components/combo-box";
import AiToolParameterEditor from "./ai-tool-parameter-editor"; import AiToolParameterEditor from "./ai-tool-parameter-editor";
import AiToolTestModal from "./modal/ai-tool-test-modal"; import AiToolTestModal from "./modal/ai-tool-test-modal";
import RagOptions from "./rag-options"; import RagOptions from "./rag-options";
@ -33,34 +32,26 @@ export default class AiToolEditor extends Component {
@tracked isSaving = false; @tracked isSaving = false;
@tracked editingModel = null; @tracked editingModel = null;
@tracked showDelete = false; @tracked showDelete = false;
@tracked selectedPreset = null;
get presets() { get selectedPreset() {
return this.args.presets.map((preset) => { if (!this.args.selectedPreset) {
return { return null;
name: preset.preset_name, }
id: preset.preset_id,
};
});
}
get showPresets() { return this.args.presets.findBy("preset_id", this.args.selectedPreset);
return !this.selectedPreset && this.args.model.isNew;
} }
@action @action
updateModel() { updateModel() {
this.editingModel = this.args.model.workingCopy(); if (this.args.model.isNew) {
this.showDelete = !this.args.model.isNew; this.editingModel = this.store
} .createRecord("ai-tool", this.selectedPreset)
.workingCopy();
@action this.showDelete = false;
configurePreset() { } else {
this.selectedPreset = this.args.presets.findBy("preset_id", this.presetId); this.editingModel = this.args.model.workingCopy();
this.editingModel = this.store this.showDelete = !this.args.model.isNew;
.createRecord("ai-tool", this.selectedPreset) }
.workingCopy();
this.showDelete = false;
} }
@action @action
@ -148,138 +139,116 @@ export default class AiToolEditor extends Component {
{{didUpdate this.updateModel @model.id}} {{didUpdate this.updateModel @model.id}}
class="form-horizontal ai-tool-editor" class="form-horizontal ai-tool-editor"
> >
{{#if this.showPresets}} <div class="control-group">
<div class="control-group"> <label>{{i18n "discourse_ai.tools.name"}}</label>
<label>{{i18n "discourse_ai.tools.presets"}}</label> <input
<ComboBox {{on "input" (withEventValue (fn (mut this.editingModel.name)))}}
@value={{this.presetId}} value={{this.editingModel.name}}
@content={{this.presets}} type="text"
class="ai-tool-editor__presets" class="ai-tool-editor__name"
/> />
</div> <DTooltip
@icon="circle-question"
@content={{i18n "discourse_ai.tools.name_help"}}
/>
</div>
<div class="control-group ai-llm-editor__action_panel"> <div class="control-group">
<DButton <label>{{i18n "discourse_ai.tools.tool_name"}}</label>
@action={{this.configurePreset}} <input
@label="discourse_ai.tools.next.title" {{on "input" (withEventValue (fn (mut this.editingModel.tool_name)))}}
class="ai-tool-editor__next" value={{this.editingModel.tool_name}}
/> type="text"
</div> class="ai-tool-editor__tool_name"
{{else}} />
<div class="control-group"> <DTooltip
<label>{{i18n "discourse_ai.tools.name"}}</label> @icon="circle-question"
<input @content={{i18n "discourse_ai.tools.tool_name_help"}}
{{on "input" (withEventValue (fn (mut this.editingModel.name)))}} />
value={{this.editingModel.name}} </div>
type="text"
class="ai-tool-editor__name"
/>
<DTooltip
@icon="circle-question"
@content={{i18n "discourse_ai.tools.name_help"}}
/>
</div>
<div class="control-group"> <div class="control-group">
<label>{{i18n "discourse_ai.tools.tool_name"}}</label> <label>{{i18n "discourse_ai.tools.description"}}</label>
<input <textarea
{{on {{on
"input" "input"
(withEventValue (fn (mut this.editingModel.tool_name))) (withEventValue (fn (mut this.editingModel.description)))
}} }}
value={{this.editingModel.tool_name}} placeholder={{i18n "discourse_ai.tools.description_help"}}
type="text" class="ai-tool-editor__description input-xxlarge"
class="ai-tool-editor__tool_name" >{{this.editingModel.description}}</textarea>
/> </div>
<DTooltip
@icon="circle-question"
@content={{i18n "discourse_ai.tools.tool_name_help"}}
/>
</div>
<div class="control-group"> <div class="control-group">
<label>{{i18n "discourse_ai.tools.description"}}</label> <label>{{i18n "discourse_ai.tools.summary"}}</label>
<textarea <input
{{on {{on "input" (withEventValue (fn (mut this.editingModel.summary)))}}
"input" value={{this.editingModel.summary}}
(withEventValue (fn (mut this.editingModel.description))) type="text"
}} class="ai-tool-editor__summary input-xxlarge"
placeholder={{i18n "discourse_ai.tools.description_help"}} />
class="ai-tool-editor__description input-xxlarge" <DTooltip
>{{this.editingModel.description}}</textarea> @icon="circle-question"
</div> @content={{i18n "discourse_ai.tools.summary_help"}}
/>
</div>
<div class="control-group"> <div class="control-group">
<label>{{i18n "discourse_ai.tools.summary"}}</label> <label>{{i18n "discourse_ai.tools.parameters"}}</label>
<input <AiToolParameterEditor @parameters={{this.editingModel.parameters}} />
{{on "input" (withEventValue (fn (mut this.editingModel.summary)))}} </div>
value={{this.editingModel.summary}}
type="text"
class="ai-tool-editor__summary input-xxlarge"
/>
<DTooltip
@icon="circle-question"
@content={{i18n "discourse_ai.tools.summary_help"}}
/>
</div>
<div class="control-group"> <div class="control-group">
<label>{{i18n "discourse_ai.tools.parameters"}}</label> <label>{{i18n "discourse_ai.tools.script"}}</label>
<AiToolParameterEditor @parameters={{this.editingModel.parameters}} /> <AceEditor
</div> @content={{this.editingModel.script}}
@onChange={{fn (mut this.editingModel.script)}}
@mode={{ACE_EDITOR_MODE}}
@theme={{ACE_EDITOR_THEME}}
@editorId="ai-tool-script-editor"
/>
</div>
{{#if this.siteSettings.ai_embeddings_enabled}}
<div class="control-group"> <div class="control-group">
<label>{{i18n "discourse_ai.tools.script"}}</label> <RagUploader
<AceEditor @target={{this.editingModel}}
@content={{this.editingModel.script}} @updateUploads={{this.updateUploads}}
@onChange={{fn (mut this.editingModel.script)}} @onRemove={{this.removeUpload}}
@mode={{ACE_EDITOR_MODE}}
@theme={{ACE_EDITOR_THEME}}
@editorId="ai-tool-script-editor"
/>
</div>
{{#if this.siteSettings.ai_embeddings_enabled}}
<div class="control-group">
<RagUploader
@target={{this.editingModel}}
@updateUploads={{this.updateUploads}}
@onRemove={{this.removeUpload}}
@allowImages={{@settings.rag_images_enabled}}
/>
</div>
<RagOptions
@model={{this.editingModel}}
@llms={{@llms}}
@allowImages={{@settings.rag_images_enabled}} @allowImages={{@settings.rag_images_enabled}}
/> />
{{/if}}
<div class="control-group ai-tool-editor__action_panel">
{{#unless @model.isNew}}
<DButton
@action={{this.openTestModal}}
@label="discourse_ai.tools.test"
class="ai-tool-editor__test-button"
/>
{{/unless}}
<DButton
@action={{this.save}}
@label="discourse_ai.tools.save"
@disabled={{this.isSaving}}
class="btn-primary ai-tool-editor__save"
/>
{{#if this.showDelete}}
<DButton
@action={{this.delete}}
@label="discourse_ai.tools.delete"
class="btn-danger ai-tool-editor__delete"
/>
{{/if}}
</div> </div>
<RagOptions
@model={{this.editingModel}}
@llms={{@llms}}
@allowImages={{@settings.rag_images_enabled}}
/>
{{/if}} {{/if}}
<div class="control-group ai-tool-editor__action_panel">
{{#unless @model.isNew}}
<DButton
@action={{this.openTestModal}}
@label="discourse_ai.tools.test"
class="ai-tool-editor__test-button"
/>
{{/unless}}
<DButton
@action={{this.save}}
@label="discourse_ai.tools.save"
@disabled={{this.isSaving}}
class="btn-primary ai-tool-editor__save"
/>
{{#if this.showDelete}}
<DButton
@action={{this.delete}}
@label="discourse_ai.tools.delete"
class="btn-danger ai-tool-editor__delete"
/>
{{/if}}
</div>
</form> </form>
</template> </template>
} }

View File

@ -1,6 +1,9 @@
import Component from "@glimmer/component"; import Component from "@glimmer/component";
import { array, fn } from "@ember/helper";
import { action } from "@ember/object";
import { LinkTo } from "@ember/routing"; import { LinkTo } from "@ember/routing";
import { service } from "@ember/service"; import { service } from "@ember/service";
import { eq } from "truth-helpers";
import DBreadcrumbsItem from "discourse/components/d-breadcrumbs-item"; import DBreadcrumbsItem from "discourse/components/d-breadcrumbs-item";
import DButton from "discourse/components/d-button"; import DButton from "discourse/components/d-button";
import DPageSubheader from "discourse/components/d-page-subheader"; import DPageSubheader from "discourse/components/d-page-subheader";
@ -11,6 +14,23 @@ import DMenu from "float-kit/components/d-menu";
export default class AiToolListEditor extends Component { export default class AiToolListEditor extends Component {
@service adminPluginNavManager; @service adminPluginNavManager;
@service router;
get lastIndexOfPresets() {
return this.args.tools.resultSetMeta.presets.length - 1;
}
@action
routeToNewTool(preset) {
return this.router.transitionTo(
"adminPlugins.show.discourse-ai-tools.new",
{
queryParams: {
presetId: preset.preset_id,
},
}
);
}
<template> <template>
<DBreadcrumbsItem <DBreadcrumbsItem
@ -28,19 +48,25 @@ export default class AiToolListEditor extends Component {
@triggerClass="btn-primary btn-small" @triggerClass="btn-primary btn-small"
@label={{i18n "discourse_ai.tools.new"}} @label={{i18n "discourse_ai.tools.new"}}
@icon="plus" @icon="plus"
@placement="bottom-end"
> >
<:content> <:content>
{{! TODO add action to dropdown button that prefills editor }}
<DropdownMenu as |dropdown|> <DropdownMenu as |dropdown|>
{{#each @tools.resultSetMeta.presets as |preset|}} {{#each @tools.resultSetMeta.presets as |preset index|}}
{{#if (eq index this.lastIndexOfPresets)}}
<dropdown.divider />
{{/if}}
<dropdown.item> <dropdown.item>
<DButton <DButton
@translatedLabel={{preset.preset_name}} @translatedLabel={{preset.preset_name}}
@action={{fn this.routeToNewTool preset}}
class="btn-transparent" class="btn-transparent"
/> />
</dropdown.item> </dropdown.item>
{{/each}} {{/each}}
</DropdownMenu> </DropdownMenu>
</:content> </:content>
</DMenu> </DMenu>
</:actions> </:actions>

View File

@ -327,10 +327,7 @@ en:
test: "Run test" test: "Run test"
delete: "Delete" delete: "Delete"
saved: "Tool saved" saved: "Tool saved"
presets: "Select a preset..."
confirm_delete: "Are you sure you want to delete this tool?" confirm_delete: "Are you sure you want to delete this tool?"
next:
title: "Next"
test_modal: test_modal:
title: "Test AI tool" title: "Test AI tool"
run: "Run test" run: "Run test"