Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
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>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import Component from "@glimmer/component";
import { service } from "@ember/service";
import icon from "discourse/helpers/d-icon";
import { i18n } from "discourse-i18n";
import DTooltip from "float-kit/components/d-tooltip";
import AiSearchDiscoveries from "../../components/ai-search-discoveries";
import AiSearchDiscoveriesTooltip from "../../components/ai-search-discoveries-tooltip";

export default class AiFullPageDiscobotDiscoveries extends Component {
static shouldRender(_args, { siteSettings, currentUser }) {
return (
siteSettings.ai_bot_discover_persona &&
currentUser?.can_use_ai_bot_discover_persona
currentUser?.can_use_ai_bot_discover_persona &&
currentUser?.user_option?.ai_search_discoveries
);
}

Expand All @@ -29,29 +30,7 @@ export default class AiFullPageDiscobotDiscoveries extends Component {
{{i18n "discourse_ai.discobot_discoveries.main_title"}}
</span>

<span class="ai-search-discoveries-tooltip">
<DTooltip @placement="top-end">
<: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__content">
{{#if this.discobotDiscoveries.modelUsed}}
{{i18n
"discourse_ai.discobot_discoveries.tooltip.content"
model=this.discobotDiscoveries.modelUsed
}}
{{/if}}
</div>
</div>
</:content>
</DTooltip>
</span>
<AiSearchDiscoveriesTooltip />
</h3>
<div class="full-page-discoveries">
<AiSearchDiscoveries @searchTerm={{@outletArgs.search}} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ import Component from "@glimmer/component";
import { service } from "@ember/service";
import icon from "discourse/helpers/d-icon";
import { i18n } from "discourse-i18n";
import DTooltip from "float-kit/components/d-tooltip";
import AiSearchDiscoveries from "../../components/ai-search-discoveries";
import AiSearchDiscoveriesTooltip from "../../components/ai-search-discoveries-tooltip";

export default class AiDiscobotDiscoveries extends Component {
static shouldRender(args, { siteSettings, currentUser }) {
return (
args.resultType.type === "topic" &&
siteSettings.ai_bot_discover_persona &&
currentUser?.can_use_ai_bot_discover_persona
currentUser?.can_use_ai_bot_discover_persona &&
currentUser?.user_option?.ai_search_discoveries
);
}

Expand All @@ -24,29 +25,7 @@ export default class AiDiscobotDiscoveries extends Component {
{{i18n "discourse_ai.discobot_discoveries.main_title"}}
</span>

<span class="ai-search-discoveries-tooltip">
<DTooltip @placement="top-end">
<: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__content">
{{#if this.discobotDiscoveries.modelUsed}}
{{i18n
"discourse_ai.discobot_discoveries.tooltip.content"
model=this.discobotDiscoveries.modelUsed
}}
{{/if}}
</div>
</div>
</:content>
</DTooltip>
</span>
<AiSearchDiscoveriesTooltip />
</h3>

<AiSearchDiscoveries @discoveryPreviewLength={{50}} />
Expand Down
55 changes: 44 additions & 11 deletions assets/javascripts/discourse/controllers/preferences-ai.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,62 @@ import { service } from "@ember/service";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { isTesting } from "discourse/lib/environment";

const AI_ATTRS = ["auto_image_caption"];

export default class PreferencesAiController extends Controller {
@service siteSettings;
@tracked saved = false;

get showAutoImageCaptionSetting() {
const aiHelperEnabledFeatures =
this.siteSettings.ai_helper_enabled_features.split("|");
get booleanSettings() {
return [
{
key: "auto_image_caption",
label: "discourse_ai.ai_helper.image_caption.automatic_caption_setting",
settingName: "auto-image-caption",
checked: this.model.user_option.auto_image_caption,
isIncluded: (() => {
const aiHelperEnabledFeatures =
this.siteSettings.ai_helper_enabled_features.split("|");

return (
this.model?.user_allowed_ai_auto_image_captions &&
aiHelperEnabledFeatures.includes("image_caption") &&
this.siteSettings.ai_helper_enabled
);
})(),
},
{
key: "ai_search_discoveries",
label: "discourse_ai.discobot_discoveries.user_setting",
settingName: "ai-search-discoveries",
checked: this.model.user_option.ai_search_discoveries,
isIncluded: (() => {
return (
this.siteSettings.ai_bot_discover_persona &&
this.model?.can_use_ai_bot_discover_persona &&
this.siteSettings.ai_bot_enabled
);
})(),
},
];
}

get userSettingAttributes() {
const attrs = [];

this.booleanSettings.forEach((setting) => {
if (setting.isIncluded) {
attrs.push(setting.key);
}
});

return (
this.model?.user_allowed_ai_auto_image_captions &&
aiHelperEnabledFeatures.includes("image_caption") &&
this.siteSettings.ai_helper_enabled
);
return attrs;
}

@action
save() {
this.saved = false;

return this.model
.save(AI_ATTRS)
.save(this.userSettingAttributes)
.then(() => {
this.saved = true;
if (!isTesting()) {
Expand Down
12 changes: 11 additions & 1 deletion assets/javascripts/discourse/services/discobot-discoveries.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { tracked } from "@glimmer/tracking";
import Service from "@ember/service";
import { action } from "@ember/object";
import Service, { service } from "@ember/service";

export default class DiscobotDiscoveries extends Service {
// We use this to retain state after search menu gets closed.
// Similar to discourse/discourse#25504
@service currentUser;

@tracked discovery = "";
@tracked lastQuery = "";
@tracked discoveryTimedOut = false;
Expand All @@ -14,4 +17,11 @@ export default class DiscobotDiscoveries extends Service {
this.discoveryTimedOut = false;
this.modelUsed = "";
}

@action
async disableDiscoveries() {
this.currentUser.user_option.ai_search_discoveries = false;
await this.currentUser.save(["ai_search_discoveries"]);
location.reload();
}
}
49 changes: 27 additions & 22 deletions assets/javascripts/discourse/templates/preferences/ai.hbs
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
{{!
Later when we have more preferences,
move the conditional (showAutoImageCaptionSetting)
to be only around the auto-image-caption preference.
}}
{{#if this.showAutoImageCaptionSetting}}
<label class="control-label">{{i18n "discourse_ai.title"}}</label>
<div class="ai-user-preferences">
<legend class="control-label">{{i18n "discourse_ai.title"}}</legend>

<div class="control-group ai-setting">
<PreferenceCheckbox
@labelKey="discourse_ai.ai_helper.image_caption.automatic_caption_setting"
@checked={{this.model.user_option.auto_image_caption}}
data-setting-name="auto-image-caption"
class="pref-auto-image-caption"
/>
</div>
{{#each this.booleanSettings as |setting|}}
{{#if setting.isIncluded}}
<div class="control-group ai-setting">
<PreferenceCheckbox
@labelKey={{setting.label}}
@checked={{get this.model.user_option setting.key}}
data-setting-name={{setting.settingName}}
class="pref-{{setting.settingName}}"
/>
</div>
{{/if}}
{{/each}}

{{#if (eq this.userSettingAttributes.length 0)}}
{{i18n "discourse_ai.user_preferences.empty"}}
{{/if}}

<SaveControls
@id="user_ai_preference_save"
@model={{this.model}}
@action={{this.save}}
@saved={{this.saved}}
/>
{{/if}}
{{#unless (eq this.userSettingAttributes.length 0)}}
<SaveControls
@id="user_ai_preference_save"
@model={{this.model}}
@action={{this.save}}
@saved={{this.saved}}
/>
{{/unless}}
</div>
15 changes: 15 additions & 0 deletions assets/javascripts/initializers/ai-search-discoveries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
const currentUser = api.getCurrentUser();
const settings = api.container.lookup("service:site-settings");

if (
!settings.ai_bot_enabled ||
!currentUser?.can_use_ai_bot_discover_persona
) {
return;
}

api.addSaveableUserOptionField("ai_search_discoveries");
});
13 changes: 13 additions & 0 deletions assets/stylesheets/common/ai-user-settings.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.user-preferences .ai-user-preferences {
legend {
margin-bottom: 1rem;
}

.control-group {
margin-bottom: 0;
}

.save-button {
margin-top: 2rem;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,26 @@
}

.ai-search-discoveries-tooltip {
&__content {
padding: 0.5rem;
}

&__header {
font-weight: bold;
margin-bottom: 0.5em;
}

&__actions {
display: flex;
justify-content: space-between;
gap: 1rem;
margin-top: 1rem;

.btn {
padding: 0;
}
}

.fk-d-tooltip__trigger {
vertical-align: middle;
}
Expand Down
8 changes: 7 additions & 1 deletion config/locales/client.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ en:
label: "Tool"
description: "Tool to use for triage (tool must have no parameters defined)"


llm_persona_triage:
fields:
persona:
Expand Down Expand Up @@ -714,9 +713,16 @@ en:
tell_me_more: "Tell me more..."
collapse: "Collapse"
timed_out: "Discobot couldn't find any discoveries. Something went wrong."
user_setting: "Enable search discoveries"
tooltip:
header: "AI powered search"
content: "Natural language search powered by %{model}"
actions:
info: "How does it work?"
disable: "Disable"

user_preferences:
empty: "There are no relevant settings available at this time"
review:
types:
reviewable_ai_post:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class AddAiSearchDiscoveriesToUserOptions < ActiveRecord::Migration[7.2]
def change
add_column :user_options, :ai_search_discoveries, :boolean, default: true, null: false
end
end
Loading