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

Commit b5d393b

Browse files
authored
FIX: custom tools incorrectly setting all fields to blank enum (#1385)
Previous to this change, enum was set to [] which broke all non enum tools
1 parent 77ae426 commit b5d393b

File tree

3 files changed

+70
-5
lines changed

3 files changed

+70
-5
lines changed

app/models/ai_tool.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ class AiTool < ActiveRecord::Base
2222
message: I18n.t("discourse_ai.tools.name.characters"),
2323
}
2424

25+
validate :validate_parameters_enum
26+
2527
def signature
2628
{
2729
name: function_call_name,
@@ -57,6 +59,30 @@ def regenerate_rag_fragments
5759
end
5860
end
5961

62+
def validate_parameters_enum
63+
return unless parameters.is_a?(Array)
64+
65+
parameters.each_with_index do |param, index|
66+
next if !param.is_a?(Hash) || !param.key?("enum")
67+
enum_values = param["enum"]
68+
69+
if enum_values.empty?
70+
errors.add(
71+
:parameters,
72+
"Parameter '#{param["name"]}' at index #{index}: enum cannot be empty",
73+
)
74+
next
75+
end
76+
77+
if enum_values.uniq.length != enum_values.length
78+
errors.add(
79+
:parameters,
80+
"Parameter '#{param["name"]}' at index #{index}: enum values must be unique",
81+
)
82+
end
83+
end
84+
end
85+
6086
def self.preamble
6187
<<~JS
6288
/**

assets/javascripts/discourse/components/ai-tool-editor-form.gjs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,16 @@ export default class AiToolEditorForm extends Component {
3030

3131
get formData() {
3232
const parameters = (this.args.editingModel.parameters ?? []).map(
33-
(parameter) => ({
34-
...parameter,
35-
isEnum: !!parameter.enum?.length,
36-
enum: (parameter.enum ??= []),
37-
})
33+
(parameter) => {
34+
const mappedParameter = {
35+
...parameter,
36+
};
37+
parameter.isEnum = parameter.enum && parameter.enum.length > 0;
38+
if (!parameter.isEnum) {
39+
delete mappedParameter.enum;
40+
}
41+
return mappedParameter;
42+
}
3843
);
3944

4045
return {

spec/requests/admin/ai_tools_controller_spec.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,40 @@
9292
)
9393
end
9494
end
95+
96+
context "when enum validation fails" do
97+
it "fails to create tool with empty enum" do
98+
attrs = valid_attributes
99+
attrs[:parameters] = [attrs[:parameters].first.merge(enum: [])]
100+
101+
expect {
102+
post "/admin/plugins/discourse-ai/ai-tools.json",
103+
params: { ai_tool: attrs }.to_json,
104+
headers: {
105+
"CONTENT_TYPE" => "application/json",
106+
}
107+
}.not_to change(AiTool, :count)
108+
109+
expect(response).to have_http_status(:unprocessable_entity)
110+
expect(response.parsed_body["errors"]).to include(match(/enum cannot be empty/))
111+
end
112+
113+
it "fails to create tool with duplicate enum values" do
114+
attrs = valid_attributes
115+
attrs[:parameters] = [attrs[:parameters].first.merge(enum: %w[c f c])]
116+
117+
expect {
118+
post "/admin/plugins/discourse-ai/ai-tools.json",
119+
params: { ai_tool: attrs }.to_json,
120+
headers: {
121+
"CONTENT_TYPE" => "application/json",
122+
}
123+
}.not_to change(AiTool, :count)
124+
125+
expect(response).to have_http_status(:unprocessable_entity)
126+
expect(response.parsed_body["errors"]).to include(match(/enum values must be unique/))
127+
end
128+
end
95129
end
96130

97131
describe "PUT #update" do

0 commit comments

Comments
 (0)