Compare commits

..
Author SHA1 Message Date
Joffrey JAFFEUX 91a97d75da FIX: prevents double escaping of filters
We were passing: `{"category": 4}` which was then escape by Ember, basically causing a double Json stringify and preventing code to work down the road.
2025-03-10 21:05:38 +01:00
157 changed files with 2577 additions and 4241 deletions
+45 -59
View File
@@ -1,93 +1,79 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (8.0.2)
activesupport (7.1.3.4)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1)
mutex_m
tzinfo (~> 2.0)
ast (2.4.2)
base64 (0.2.0)
benchmark (0.4.0)
bigdecimal (3.1.9)
concurrent-ruby (1.3.5)
connection_pool (2.5.0)
bigdecimal (3.1.8)
concurrent-ruby (1.3.3)
connection_pool (2.4.1)
drb (2.2.1)
i18n (1.14.7)
i18n (1.14.5)
concurrent-ruby (~> 1.0)
json (2.10.2)
language_server-protocol (3.17.0.4)
lint_roller (1.1.0)
logger (1.6.6)
minitest (5.25.5)
parallel (1.26.3)
parser (3.3.7.1)
json (2.7.2)
language_server-protocol (3.17.0.3)
minitest (5.24.1)
mutex_m (0.2.0)
parallel (1.25.1)
parser (3.3.3.0)
ast (~> 2.4.1)
racc
prettier_print (1.2.1)
racc (1.8.1)
rack (3.1.12)
racc (1.8.0)
rack (3.1.10)
rainbow (3.1.1)
regexp_parser (2.10.0)
rubocop (1.74.0)
regexp_parser (2.9.2)
rexml (3.3.9)
rubocop (1.64.1)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.38.0, < 2.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.31.1, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.38.1)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.31.3)
parser (>= 3.3.1.0)
rubocop-capybara (2.22.1)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-discourse (3.12.1)
rubocop-capybara (2.21.0)
rubocop (~> 1.41)
rubocop-discourse (3.8.1)
activesupport (>= 6.1)
lint_roller (>= 1.1.0)
rubocop (>= 1.73.2)
rubocop-capybara (>= 2.22.0)
rubocop-factory_bot (>= 2.27.0)
rubocop-rails (>= 2.30.3)
rubocop (>= 1.59.0)
rubocop-capybara (>= 2.0.0)
rubocop-factory_bot (>= 2.0.0)
rubocop-rails (>= 2.25.0)
rubocop-rspec (>= 3.0.1)
rubocop-rspec_rails (>= 2.31.0)
rubocop-factory_bot (2.27.1)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rails (2.30.3)
rubocop-rspec_rails (>= 2.30.0)
rubocop-factory_bot (2.26.1)
rubocop (~> 1.61)
rubocop-rails (2.25.1)
activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1)
rubocop (>= 1.72.1, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0)
rubocop-rspec (3.5.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec_rails (2.31.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec (~> 3.5)
rubocop (>= 1.33.0, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0)
rubocop-rspec (3.0.2)
rubocop (~> 1.61)
rubocop-rspec_rails (2.30.0)
rubocop (~> 1.61)
rubocop-rspec (~> 3, >= 3.0.1)
ruby-progressbar (1.13.0)
securerandom (0.4.1)
syntax_tree (6.2.0)
prettier_print (>= 1.2.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (3.1.4)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
uri (1.0.3)
unicode-display_width (2.5.0)
PLATFORMS
ruby
@@ -97,4 +83,4 @@ DEPENDENCIES
syntax_tree
BUNDLED WITH
2.6.6
2.5.10
@@ -1,10 +1,6 @@
import DiscourseRoute from "discourse/routes/discourse";
export default class DiscourseAiToolsNewRoute extends DiscourseRoute {
beforeModel(transition) {
this.preset = transition.to.queryParams.presetId || "empty_tool";
}
async model() {
return this.store.createRecord("ai-tool");
}
@@ -12,10 +8,10 @@ export default class DiscourseAiToolsNewRoute extends DiscourseRoute {
setupController(controller) {
super.setupController(...arguments);
const toolsModel = this.modelFor("adminPlugins.show.discourse-ai-tools");
controller.set("allTools", toolsModel);
controller.set("presets", toolsModel.resultSetMeta.presets);
controller.set("llms", toolsModel.resultSetMeta.llms);
controller.set("settings", toolsModel.resultSetMeta.settings);
controller.set("selectedPreset", this.preset);
}
}
@@ -5,6 +5,5 @@
@presets={{this.presets}}
@llms={{this.llms}}
@settings={{this.settings}}
@selectedPreset={{this.selectedPreset}}
/>
</section>
@@ -53,12 +53,7 @@ module DiscourseAi
end
def suggest_title
if params[:topic_id]
topic = Topic.find_by(id: params[:topic_id])
input = DiscourseAi::Summarization::Strategies::TopicSummary.new(topic).targets_data
else
input = get_text_param!
end
input = get_text_param!
prompt = CompletionPrompt.enabled_by_name("generate_titles")
raise Discourse::InvalidParameters.new(:mode) if !prompt
@@ -78,26 +73,22 @@ module DiscourseAi
end
def suggest_category
if params[:topic_id]
opts = { topic_id: params[:topic_id] }
else
input = get_text_param!
opts = { text: input }
end
input = get_text_param!
input_hash = { text: input }
render json: DiscourseAi::AiHelper::SemanticCategorizer.new(current_user, opts).categories,
render json:
DiscourseAi::AiHelper::SemanticCategorizer.new(
input_hash,
current_user,
).categories,
status: 200
end
def suggest_tags
if params[:topic_id]
opts = { topic_id: params[:topic_id] }
else
input = get_text_param!
opts = { text: input }
end
input = get_text_param!
input_hash = { text: input }
render json: DiscourseAi::AiHelper::SemanticCategorizer.new(current_user, opts).tags,
render json: DiscourseAi::AiHelper::SemanticCategorizer.new(input_hash, current_user).tags,
status: 200
end
-8
View File
@@ -26,23 +26,17 @@ class LlmModel < ActiveRecord::Base
access_key_id: :text,
region: :text,
disable_native_tools: :checkbox,
disable_temperature: :checkbox,
disable_top_p: :checkbox,
enable_reasoning: :checkbox,
reasoning_tokens: :number,
},
anthropic: {
disable_native_tools: :checkbox,
disable_temperature: :checkbox,
disable_top_p: :checkbox,
enable_reasoning: :checkbox,
reasoning_tokens: :number,
},
open_ai: {
organization: :text,
disable_native_tools: :checkbox,
disable_temperature: :checkbox,
disable_top_p: :checkbox,
disable_streaming: :checkbox,
reasoning_effort: {
type: :enum,
@@ -75,8 +69,6 @@ class LlmModel < ActiveRecord::Base
provider_order: :text,
provider_quantizations: :text,
disable_streaming: :checkbox,
disable_temperature: :checkbox,
disable_top_p: :checkbox,
},
}
end
@@ -32,10 +32,8 @@ export default class AiTool extends RestModel {
if (parameter.enum && parameter.enum.length) {
parameter.enum = new TrackedArray(parameter.enum);
parameter.isEnum = true;
} else {
parameter.enum = null;
parameter.isEnum = false;
}
return parameter;
@@ -268,7 +268,6 @@ export default class AdminReportSentimentAnalysis extends Component {
this.router.transitionTo(this.router.currentRoute.name, {
queryParams: {
...currentQueryParams,
filters: JSON.parse(currentQueryParams.filters), // avoids a double escaping
selectedChart: null,
},
});
@@ -13,7 +13,6 @@ import getURL from "discourse/lib/get-url";
export default class AiArtifactComponent extends Component {
@service siteSettings;
@tracked expanded = false;
@tracked showingArtifact = false;
@@ -15,7 +15,6 @@ export default class AiComposerHelperMenu extends Component {
@service siteSettings;
@service currentUser;
@service site;
@tracked newSelectedText;
@tracked diff;
@tracked customPromptValue = "";
File diff suppressed because it is too large Load Diff
@@ -1,49 +0,0 @@
import Component from "@glimmer/component";
import { service } from "@ember/service";
import DButton from "discourse/components/d-button";
import icon from "discourse/helpers/d-icon";
import { i18n } from "discourse-i18n";
import DTooltip from "float-kit/components/d-tooltip";
export default class AiSearchDiscoveriesTooltip extends Component {
@service discobotDiscoveries;
<template>
<span class="ai-search-discoveries-tooltip">
<DTooltip @placement="top-end" @interactive={{true}}>
<:trigger>
{{icon "circle-info"}}
</:trigger>
<:content>
<div class="ai-search-discoveries-tooltip__content">
<div class="ai-search-discoveries-tooltip__header">
{{i18n "discourse_ai.discobot_discoveries.tooltip.header"}}
</div>
<div class="ai-search-discoveries-tooltip__description">
{{#if this.discobotDiscoveries.modelUsed}}
{{i18n
"discourse_ai.discobot_discoveries.tooltip.content"
model=this.discobotDiscoveries.modelUsed
}}
{{/if}}
</div>
<div class="ai-search-discoveries-tooltip__actions">
<DButton
class="btn-transparent btn-primary"
@label="discourse_ai.discobot_discoveries.tooltip.actions.info"
@href="https://meta.discourse.org/t/conversational-ai-search-coming-to-discourse-ai/355939"
/>
<DButton
class="btn-transparent btn-danger"
@label="discourse_ai.discobot_discoveries.tooltip.actions.disable"
@action={{this.discobotDiscoveries.disableDiscoveries}}
/>
</div>
</div>
</:content>
</DTooltip>
</span>
</template>
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,36 +1,13 @@
import Component from "@glimmer/component";
import { fn } from "@ember/helper";
import { action } from "@ember/object";
import { LinkTo } from "@ember/routing";
import { service } from "@ember/service";
import { eq } from "truth-helpers";
import DBreadcrumbsItem from "discourse/components/d-breadcrumbs-item";
import DButton from "discourse/components/d-button";
import DPageSubheader from "discourse/components/d-page-subheader";
import DropdownMenu from "discourse/components/dropdown-menu";
import { i18n } from "discourse-i18n";
import AdminConfigAreaEmptyList from "admin/components/admin-config-area-empty-list";
import DMenu from "float-kit/components/d-menu";
export default class AiToolListEditor extends Component {
@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>
<DBreadcrumbsItem
@@ -43,33 +20,13 @@ export default class AiToolListEditor extends Component {
@learnMoreUrl="https://meta.discourse.org/t/ai-bot-custom-tools/314103"
@descriptionLabel={{i18n "discourse_ai.tools.subheader_description"}}
>
<:actions>
<DMenu
@triggerClass="btn-primary btn-small ai-tool-list-editor__new-button"
@label={{i18n "discourse_ai.tools.new"}}
<:actions as |actions|>
<actions.Primary
@label="discourse_ai.tools.new"
@route="adminPlugins.show.discourse-ai-tools.new"
@icon="plus"
@placement="bottom-end"
>
<:content>
<DropdownMenu as |dropdown|>
{{#each @tools.resultSetMeta.presets as |preset index|}}
{{#if (eq index this.lastIndexOfPresets)}}
<dropdown.divider />
{{/if}}
<dropdown.item>
<DButton
@translatedLabel={{preset.preset_name}}
@action={{fn this.routeToNewTool preset}}
class="btn-transparent"
data-option={{preset.preset_id}}
/>
</dropdown.item>
{{/each}}
</DropdownMenu>
</:content>
</DMenu>
class="ai-tool-list-editor__new-button"
/>
</:actions>
</DPageSubheader>
@@ -0,0 +1,155 @@
import Component from "@glimmer/component";
import { fn } from "@ember/helper";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import { TrackedArray, TrackedObject } from "@ember-compat/tracked-built-ins";
import DButton from "discourse/components/d-button";
import withEventValue from "discourse/helpers/with-event-value";
import { i18n } from "discourse-i18n";
import ComboBox from "select-kit/components/combo-box";
const PARAMETER_TYPES = [
{ name: "string", id: "string" },
{ name: "number", id: "number" },
{ name: "boolean", id: "boolean" },
{ name: "array", id: "array" },
];
export default class AiToolParameterEditor extends Component {
@action
addParameter() {
this.args.parameters.push(
new TrackedObject({
name: "",
description: "",
type: "string",
required: false,
enum: null,
})
);
}
@action
removeParameter(parameter) {
const index = this.args.parameters.indexOf(parameter);
this.args.parameters.splice(index, 1);
}
@action
toggleRequired(parameter, event) {
parameter.required = event.target.checked;
}
@action
toggleEnum(parameter) {
if (parameter.enum) {
parameter.enum = null;
} else {
this.addEnumValue(parameter);
}
}
@action
addEnumValue(parameter) {
parameter.enum ||= new TrackedArray();
parameter.enum.push("");
}
@action
removeEnumValue(parameter, index) {
parameter.enum.splice(index, 1);
if (parameter.enum.length === 0) {
parameter.enum = null;
}
}
@action
updateEnumValue(parameter, index, event) {
parameter.enum[index] = event.target.value;
}
<template>
{{#each @parameters as |parameter|}}
<div class="ai-tool-parameter">
<div class="parameter-row">
<input
{{on "input" (withEventValue (fn (mut parameter.name)))}}
value={{parameter.name}}
type="text"
placeholder={{i18n "discourse_ai.tools.parameter_name"}}
/>
<ComboBox @value={{parameter.type}} @content={{PARAMETER_TYPES}} />
</div>
<div class="parameter-row">
<input
{{on "input" (withEventValue (fn (mut parameter.description)))}}
value={{parameter.description}}
type="text"
placeholder={{i18n "discourse_ai.tools.parameter_description"}}
/>
</div>
<div class="parameter-row">
<label>
<input
{{on "input" (fn this.toggleRequired parameter)}}
checked={{parameter.required}}
type="checkbox"
class="parameter-row__required-toggle"
/>
{{i18n "discourse_ai.tools.parameter_required"}}
</label>
<label>
<input
{{on "input" (fn this.toggleEnum parameter)}}
checked={{parameter.enum}}
type="checkbox"
class="parameter-row__enum-toggle"
/>
{{i18n "discourse_ai.tools.parameter_enum"}}
</label>
<DButton
@action={{fn this.removeParameter parameter}}
@icon="trash-can"
class="btn-danger"
/>
</div>
{{#if parameter.enum}}
<div class="parameter-enum-values">
{{#each parameter.enum as |enumValue enumIndex|}}
<div class="enum-value-row">
<input
{{on "change" (fn this.updateEnumValue parameter enumIndex)}}
value={{enumValue}}
type="text"
placeholder={{i18n "discourse_ai.tools.enum_value"}}
/>
<DButton
@action={{fn this.removeEnumValue parameter enumIndex}}
@icon="trash-can"
class="btn-danger"
/>
</div>
{{/each}}
<DButton
@action={{fn this.addEnumValue parameter}}
@label="discourse_ai.tools.add_enum_value"
@icon="plus"
/>
</div>
{{/if}}
</div>
{{/each}}
<DButton
@action={{this.addParameter}}
@label="discourse_ai.tools.add_parameter"
@icon="plus"
/>
</template>
}
@@ -23,7 +23,6 @@ import ComboBox from "select-kit/components/combo-box";
export default class AiUsage extends Component {
@service store;
@tracked startDate = moment().subtract(30, "days").toDate();
@tracked endDate = new Date();
@tracked data = this.args.model;
@@ -13,7 +13,6 @@ import AiIndicatorWave from "../ai-indicator-wave";
export default class ModalDiffModal extends Component {
@service currentUser;
@tracked loading = false;
@tracked diff;
@tracked suggestion = "";
@@ -13,7 +13,6 @@ import { i18n } from "discourse-i18n";
export default class ShareModal extends Component {
@service toasts;
@tracked shareKey = "";
constructor() {
@@ -16,7 +16,6 @@ export default class ShareModal extends Component {
@service modal;
@service siteSettings;
@service currentUser;
@tracked contextValue = 1;
@tracked htmlContext = "";
@tracked maxContext = 0;
@@ -9,7 +9,6 @@ import { i18n } from "discourse-i18n";
export default class RagUploadProgress extends Component {
@service messageBus;
@tracked updatedProgress = null;
willDestroy() {
@@ -16,7 +16,6 @@ import RagUploadProgress from "./rag-upload-progress";
export default class RagUploader extends Component {
@service appEvents;
@tracked term = null;
@tracked filteredUploads = null;
@tracked ragIndexingStatuses = null;
@@ -137,10 +136,7 @@ export default class RagUploader extends Component {
{{#if this.ragUploads}}
<div class="rag-uploader__search-input-container">
<div class="rag-uploader__search-input">
{{icon
"magnifying-glass"
class="rag-uploader__search-input__search-icon"
}}
{{icon "search" class="rag-uploader__search-input__search-icon"}}
<Input
class="rag-uploader__search-input__input"
placeholder={{i18n "discourse_ai.rag.uploads.filter"}}
@@ -15,19 +15,32 @@ import { MIN_CHARACTER_COUNT } from "../../lib/ai-helper-suggestions";
export default class AiCategorySuggester extends Component {
@service siteSettings;
@tracked loading = false;
@tracked suggestions = null;
@tracked untriggers = [];
@tracked triggerIcon = "discourse-sparkles";
@tracked content = null;
@tracked topicContent = null;
constructor() {
super(...arguments);
if (!this.topicContent && this.args.composer?.reply === undefined) {
this.fetchTopicContent();
}
}
async fetchTopicContent() {
await ajax(`/t/${this.args.buffered.content.id}.json`).then(
({ post_stream }) => {
this.topicContent = post_stream.posts[0].cooked;
}
);
}
get showSuggestionButton() {
const composerFields = document.querySelector(".composer-fields");
this.content = this.args.composer?.reply;
const showTrigger =
this.content?.length > MIN_CHARACTER_COUNT ||
this.args.topicState === "edit";
this.content = this.args.composer?.reply || this.topicContent;
const showTrigger = this.content?.length > MIN_CHARACTER_COUNT;
if (composerFields) {
if (showTrigger) {
@@ -49,20 +62,12 @@ export default class AiCategorySuggester extends Component {
this.loading = true;
this.triggerIcon = "spinner";
const data = {};
if (this.content) {
data.text = this.content;
} else {
data.topic_id = this.args.buffered.content.id;
}
try {
const { assistant } = await ajax(
"/discourse-ai/ai-helper/suggest_category",
{
method: "POST",
data,
data: { text: this.content },
}
);
this.suggestions = assistant;
@@ -16,19 +16,32 @@ import { MIN_CHARACTER_COUNT } from "../../lib/ai-helper-suggestions";
export default class AiTagSuggester extends Component {
@service siteSettings;
@service toasts;
@tracked loading = false;
@tracked suggestions = null;
@tracked untriggers = [];
@tracked triggerIcon = "discourse-sparkles";
@tracked content = null;
@tracked topicContent = null;
constructor() {
super(...arguments);
if (!this.topicContent && this.args.composer?.reply === undefined) {
this.fetchTopicContent();
}
}
async fetchTopicContent() {
await ajax(`/t/${this.args.buffered.content.id}.json`).then(
({ post_stream }) => {
this.topicContent = post_stream.posts[0].cooked;
}
);
}
get showSuggestionButton() {
const composerFields = document.querySelector(".composer-fields");
this.content = this.args.composer?.reply;
const showTrigger =
this.content?.length > MIN_CHARACTER_COUNT ||
this.args.topicState === "edit";
this.content = this.args.composer?.reply || this.topicContent;
const showTrigger = this.content?.length > MIN_CHARACTER_COUNT;
if (composerFields) {
if (showTrigger) {
@@ -61,25 +74,15 @@ export default class AiTagSuggester extends Component {
this.loading = true;
this.triggerIcon = "spinner";
const data = {};
if (this.content) {
data.text = this.content;
} else {
data.topic_id = this.args.buffered.content.id;
}
try {
const { assistant } = await ajax("/discourse-ai/ai-helper/suggest_tags", {
method: "POST",
data,
data: { text: this.content },
});
this.suggestions = assistant;
const model = this.args.composer
? this.args.composer
: this.args.buffered;
if (this.#tagSelectorHasValues()) {
this.suggestions = this.suggestions.filter(
(s) => !model.get("tags").includes(s.name)
@@ -17,15 +17,30 @@ export default class AiTitleSuggester extends Component {
@tracked untriggers = [];
@tracked triggerIcon = "discourse-sparkles";
@tracked content = null;
@tracked topicContent = null;
constructor() {
super(...arguments);
if (!this.topicContent && this.args.composer?.reply === undefined) {
this.fetchTopicContent();
}
}
async fetchTopicContent() {
await ajax(`/t/${this.args.buffered.content.id}.json`).then(
({ post_stream }) => {
this.topicContent = post_stream.posts[0].cooked;
}
);
}
get showSuggestionButton() {
const composerFields = document.querySelector(".composer-fields");
const editTopicTitleField = document.querySelector(".edit-topic-title");
this.content = this.args.composer?.reply;
const showTrigger =
this.content?.length > MIN_CHARACTER_COUNT ||
this.args.topicState === "edit";
this.content = this.args.composer?.reply || this.topicContent;
const showTrigger = this.content?.length > MIN_CHARACTER_COUNT;
if (composerFields) {
if (showTrigger) {
@@ -54,20 +69,13 @@ export default class AiTitleSuggester extends Component {
this.loading = true;
this.triggerIcon = "spinner";
const data = {};
if (this.content) {
data.text = this.content;
} else {
data.topic_id = this.args.buffered.content.id;
}
try {
const { suggestions } = await ajax(
"/discourse-ai/ai-helper/suggest_title",
{
method: "POST",
data,
data: { text: this.content },
}
);
this.suggestions = suggestions;
@@ -13,6 +13,6 @@ export default class AiCategorySuggestion extends Component {
}
<template>
<AiCategorySuggester @composer={{@outletArgs.composer}} @topicState="new" />
<AiCategorySuggester @composer={{@outletArgs.composer}} />
</template>
}
@@ -13,6 +13,6 @@ export default class AiTagSuggestion extends Component {
}
<template>
<AiTagSuggester @composer={{@outletArgs.composer}} @topicState="new" />
<AiTagSuggester @composer={{@outletArgs.composer}} />
</template>
}
@@ -13,6 +13,6 @@ export default class AiTitleSuggestion extends Component {
}
<template>
<AiTitleSuggester @composer={{@outletArgs.composer}} @topicState="new" />
<AiTitleSuggester @composer={{@outletArgs.composer}} />
</template>
}
@@ -9,5 +9,7 @@ export default class AiTopicGist extends Component {
return !this.topicThumbnails?.enabledForRoute;
}
<template><AiGistToggle /></template>
<template>
<AiGistToggle />
</template>
}
@@ -31,7 +31,6 @@ export default class BotSelector extends Component {
@service currentUser;
@service siteSettings;
@tracked llm;
@tracked allowLLMSelector = true;
@@ -13,9 +13,6 @@ export default class AiCategorySuggestion extends Component {
}
<template>
<AiCategorySuggester
@buffered={{@outletArgs.buffered}}
@topicState="edit"
/>
<AiCategorySuggester @buffered={{@outletArgs.buffered}} />
</template>
}

Some files were not shown because too many files have changed in this diff Show More