Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 91b6a0e

Browse files
committed
Allow system personas to use tool options
This unlocks tool options to system personas and introduces llm and enum options for tools
1 parent 8bfa066 commit 91b6a0e

File tree

15 files changed

+157
-17
lines changed

15 files changed

+157
-17
lines changed

app/models/ai_persona.rb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,19 @@ def chat_preconditions
263263
end
264264

265265
def system_persona_unchangeable
266-
if top_p_changed? || temperature_changed? || system_prompt_changed? || tools_changed? ||
267-
name_changed? || description_changed?
266+
if top_p_changed? || temperature_changed? || system_prompt_changed? || name_changed? ||
267+
description_changed?
268268
errors.add(:base, I18n.t("discourse_ai.ai_bot.personas.cannot_edit_system_persona"))
269+
elsif tools_changed?
270+
old_tools = tools_change[0]
271+
new_tools = tools_change[1]
272+
273+
old_tool_names = old_tools.map { |t| t.is_a?(Array) ? t[0] : t }.to_set
274+
new_tool_names = new_tools.map { |t| t.is_a?(Array) ? t[0] : t }.to_set
275+
276+
if old_tool_names != new_tool_names
277+
errors.add(:base, I18n.t("discourse_ai.ai_bot.personas.cannot_edit_system_persona"))
278+
end
269279
end
270280
end
271281

app/serializers/ai_tool_serializer.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ def options
2626
name: option.localized_name,
2727
description: option.localized_description,
2828
type: option.type,
29+
values: option.values,
30+
default: option.default,
2931
}
3032
end
3133
options

assets/javascripts/discourse/admin/models/ai-persona.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const SYSTEM_ATTRIBUTES = [
4141
"enabled",
4242
"system",
4343
"priority",
44+
"tools",
4445
"user_id",
4546
"default_llm",
4647
"force_default_llm",

assets/javascripts/discourse/components/ai-llm-selector.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ export default class AiLlmSelector extends ComboBox {
1515

1616
@computed
1717
get content() {
18+
const blankName =
19+
this.attrs.blankName || i18n("discourse_ai.ai_persona.no_llm_selected");
1820
return [
1921
{
2022
id: "blank",
21-
name: i18n("discourse_ai.ai_persona.no_llm_selected"),
23+
name: blankName,
2224
},
2325
].concat(this.llms);
2426
}

assets/javascripts/discourse/components/ai-persona-editor.gjs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -420,13 +420,12 @@ export default class PersonaEditor extends Component {
420420
</div>
421421
{{/if}}
422422
{{/if}}
423-
{{#unless this.editingModel.system}}
424-
<AiPersonaToolOptions
425-
@persona={{this.editingModel}}
426-
@tools={{this.selectedToolNames}}
427-
@allTools={{@personas.resultSetMeta.tools}}
428-
/>
429-
{{/unless}}
423+
<AiPersonaToolOptions
424+
@persona={{this.editingModel}}
425+
@tools={{this.selectedToolNames}}
426+
@llms={{@personas.resultSetMeta.llms}}
427+
@allTools={{@personas.resultSetMeta.tools}}
428+
/>
430429
<div class="control-group">
431430
<label>{{i18n "discourse_ai.ai_persona.allowed_groups"}}</label>
432431
<GroupChooser

assets/javascripts/discourse/components/ai-persona-tool-option-editor.gjs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,78 @@ import Component from "@glimmer/component";
22
import { Input } from "@ember/component";
33
import { on } from "@ember/modifier";
44
import { action } from "@ember/object";
5+
import { eq } from "truth-helpers";
6+
import { i18n } from "discourse-i18n";
7+
import AiLlmSelector from "./ai-llm-selector";
58

69
export default class AiPersonaToolOptionEditor extends Component {
710
get isBoolean() {
811
return this.args.option.type === "boolean";
912
}
1013

14+
get isEnum() {
15+
return this.args.option.type === "enum";
16+
}
17+
18+
get isLlm() {
19+
return this.args.option.type === "llm";
20+
}
21+
1122
get selectedValue() {
1223
return this.args.option.value.value === "true";
1324
}
1425

26+
get selectedLlm() {
27+
if (this.args.option.value.value) {
28+
return `custom:${this.args.option.value.value}`;
29+
} else {
30+
return "blank";
31+
}
32+
}
33+
34+
set selectedLlm(value) {
35+
if (value === "blank") {
36+
this.args.option.value.value = null;
37+
} else {
38+
this.args.option.value.value = value.replace("custom:", "");
39+
}
40+
}
41+
1542
@action
1643
onCheckboxChange(event) {
1744
this.args.option.value.value = event.target.checked ? "true" : "false";
1845
}
1946

47+
@action
48+
onSelectOption(event) {
49+
this.args.option.value.value = event.target.value;
50+
}
51+
2052
<template>
2153
<div class="control-group ai-persona-tool-option-editor">
2254
<label>
2355
{{@option.name}}
2456
</label>
2557
<div class="">
26-
{{#if this.isBoolean}}
58+
{{#if this.isEnum}}
59+
<select name="input" {{on "change" this.onSelectOption}}>
60+
{{#each this.args.option.values as |value|}}
61+
<option
62+
value={{value}}
63+
selected={{eq value this.args.option.value.value}}
64+
>
65+
{{value}}
66+
</option>
67+
{{/each}}
68+
</select>
69+
{{else if this.isLlm}}
70+
<AiLlmSelector
71+
class="ai-persona-tool-option-editor__llms"
72+
@value={{this.selectedLlm}}
73+
@llms={{@llms}}
74+
@blankName={{i18n "discourse_ai.ai_persona.use_parent_llm"}}
75+
/>
76+
{{else if this.isBoolean}}
2777
<input
2878
type="checkbox"
2979
checked={{this.selectedValue}}

assets/javascripts/discourse/components/ai-persona-tool-options.gjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ export default class AiPersonaToolOptions extends Component {
6767
</div>
6868
<div class="ai-persona-editor__tool-option-options">
6969
{{#each toolOption.options as |option|}}
70-
<AiPersonaToolOptionEditor @option={{option}} />
70+
<AiPersonaToolOptionEditor
71+
@option={{option}}
72+
@llms={{@llms}}
73+
/>
7174
{{/each}}
7275
</div>
7376
</div>

config/locales/client.en.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ en:
213213
edit: "Edit"
214214
description: "Description"
215215
no_llm_selected: "No language model selected"
216+
use_parent_llm: "Use personas language model"
216217
max_context_posts: "Max context posts"
217218
max_context_posts_help: "The maximum number of posts to use as context for the AI when responding to a user. (empty for default)"
218219
vision_enabled: Vision enabled

config/locales/server.en.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,20 @@ en:
293293
summarizing: "Summarizing topic"
294294
searching: "Searching for: '%{query}'"
295295
tool_options:
296+
create_artifact:
297+
creator_llm:
298+
name: "LLM"
299+
description: "Language model to use for artifact creation"
300+
echo_artifact:
301+
name: "Echo Artifact"
302+
description: "Include full artifact source in subsequent replies"
303+
update_artifact:
304+
editor_llm:
305+
name: "LLM"
306+
description: "Language model to use for artifact edits"
307+
update_algorithm:
308+
name: "Update Algorithm"
309+
description: "Algorithm used for artifact updates (full vs diff)"
296310
google:
297311
base_query:
298312
name: "Base Search Query"

db/fixtures/ai_bot/603_bot_ai_personas.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,19 @@
3737

3838
persona.system = true
3939
instance = persona_class.new
40-
persona.tools = instance.tools.map { |tool| tool.to_s.split("::").last }
40+
tools = {}
41+
instance.tools.map { |tool| tool.to_s.split("::").last }.each { |name| tools[name] = nil }
42+
existing_tools = persona.tools || []
43+
44+
existing_tools.each do |tool|
45+
if tool.is_a?(Array)
46+
name, value = tool
47+
tools[name] = value if tools.key?(name)
48+
end
49+
end
50+
51+
persona.tools = tools.map { |name, value| [name, value] }
52+
4153
persona.system_prompt = instance.system_prompt
4254
persona.top_p = instance.top_p
4355
persona.temperature = instance.temperature

0 commit comments

Comments
 (0)