mirror of
https://github.com/discourse/discourse-ai.git
synced 2025-02-16 08:24:45 +00:00
FIX: Make sure custom tool enums follow json-schema. (#718)
Enums didn't work as expected because we the dialect couldn't translate them correctly. It doesn't understand what "enum_values" is.
This commit is contained in:
parent
0a8195242b
commit
f328b81c78
@ -81,7 +81,7 @@ module DiscourseAi
|
||||
:description,
|
||||
:script,
|
||||
:summary,
|
||||
parameters: [:name, :type, :description, :required, :enum, enum_values: []],
|
||||
parameters: [:name, :type, :description, :required, enum: []],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
@ -27,9 +27,13 @@ export default class AiTool extends RestModel {
|
||||
attrs.parameters?.map((p) => {
|
||||
const parameter = new TrackedObject(p);
|
||||
|
||||
//Backwards-compatibility code.
|
||||
// TODO(roman): Remove aug 2024. Leave only else clause.
|
||||
if (parameter.enum_values) {
|
||||
parameter.enumValues = new TrackedArray(parameter.enum_values);
|
||||
parameter.enum = new TrackedArray(parameter.enum_values);
|
||||
delete parameter.enum_values;
|
||||
} else {
|
||||
parameter.enum = new TrackedArray(parameter.enum);
|
||||
}
|
||||
|
||||
return parameter;
|
||||
|
@ -71,13 +71,6 @@ export default class AiToolEditor extends Component {
|
||||
"summary"
|
||||
);
|
||||
|
||||
for (const p of data.parameters) {
|
||||
if (p.enumValues) {
|
||||
p.enum_values = p.enumValues;
|
||||
delete p.enumValues;
|
||||
}
|
||||
}
|
||||
|
||||
await this.args.model.save(data);
|
||||
|
||||
this.toasts.success({
|
||||
@ -124,7 +117,7 @@ export default class AiToolEditor extends Component {
|
||||
<template>
|
||||
<BackButton
|
||||
@route="adminPlugins.show.discourse-ai-tools"
|
||||
@label="discourse_ai.ai_tool.back"
|
||||
@label="discourse_ai.tools.back"
|
||||
/>
|
||||
|
||||
<form
|
||||
|
@ -7,6 +7,7 @@ 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";
|
||||
import and from "truth-helpers/helpers/and";
|
||||
|
||||
const PARAMETER_TYPES = [
|
||||
{ name: "string", id: "string" },
|
||||
@ -24,8 +25,7 @@ export default class AiToolParameterEditor extends Component {
|
||||
description: "",
|
||||
type: "string",
|
||||
required: false,
|
||||
enum: false,
|
||||
enumValues: null,
|
||||
enum: null,
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -43,26 +43,27 @@ export default class AiToolParameterEditor extends Component {
|
||||
|
||||
@action
|
||||
toggleEnum(parameter) {
|
||||
parameter.enum = !parameter.enum;
|
||||
if (!parameter.enum) {
|
||||
parameter.enumValues = null;
|
||||
if (parameter.enum) {
|
||||
parameter.enum = null;
|
||||
} else {
|
||||
this.addEnumValue(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
addEnumValue(parameter) {
|
||||
parameter.enumValues ||= new TrackedArray();
|
||||
parameter.enumValues.push("");
|
||||
parameter.enum ||= new TrackedArray();
|
||||
parameter.enum.push("");
|
||||
}
|
||||
|
||||
@action
|
||||
removeEnumValue(parameter, index) {
|
||||
parameter.enumValues.splice(index, 1);
|
||||
parameter.enum.splice(index, 1);
|
||||
}
|
||||
|
||||
@action
|
||||
updateEnumValue(parameter, index, event) {
|
||||
parameter.enumValues[index] = event.target.value;
|
||||
parameter.enum[index] = event.target.value;
|
||||
}
|
||||
|
||||
<template>
|
||||
@ -100,7 +101,7 @@ export default class AiToolParameterEditor extends Component {
|
||||
<label>
|
||||
<input
|
||||
{{on "input" (fn this.toggleEnum parameter)}}
|
||||
checked={{parameter.enum}}
|
||||
checked={{and parameter.enum parameter.enum.length}}
|
||||
type="checkbox"
|
||||
/>
|
||||
{{I18n.t "discourse_ai.tools.parameter_enum"}}
|
||||
@ -113,9 +114,9 @@ export default class AiToolParameterEditor extends Component {
|
||||
/>
|
||||
</div>
|
||||
|
||||
{{#if parameter.enum}}
|
||||
{{#if (and parameter.enum parameter.enum.length)}}
|
||||
<div class="parameter-enum-values">
|
||||
{{#each parameter.enumValues as |enumValue enumIndex|}}
|
||||
{{#each parameter.enum as |enumValue enumIndex|}}
|
||||
<div class="enum-value-row">
|
||||
<input
|
||||
{{on "change" (fn this.updateEnumValue parameter enumIndex)}}
|
||||
|
@ -184,6 +184,7 @@ en:
|
||||
remove: "Remove upload"
|
||||
|
||||
tools:
|
||||
back: "Back"
|
||||
short_title: "Tools"
|
||||
new: "New Tool"
|
||||
name: "Name"
|
||||
|
@ -18,7 +18,10 @@ module DiscourseAi
|
||||
name = p[:name]
|
||||
memo[:required] << name if p[:required]
|
||||
|
||||
memo[:properties][name] = p.except(:name, :required, :item_type)
|
||||
except = %i[name required item_type]
|
||||
except << :enum if p[:enum].blank?
|
||||
|
||||
memo[:properties][name] = p.except(*except)
|
||||
|
||||
memo[:properties][name][:items] = { type: p[:item_type] } if p[:item_type]
|
||||
memo
|
||||
|
@ -7,7 +7,15 @@ RSpec.describe DiscourseAi::Admin::AiToolsController do
|
||||
name: "Test Tool",
|
||||
description: "A test tool",
|
||||
script: "function invoke(params) { return params; }",
|
||||
parameters: [{ name: "query", type: "string", description: "perform a search" }],
|
||||
parameters: [
|
||||
{
|
||||
name: "unit",
|
||||
type: "string",
|
||||
description: "the unit of measurement celcius c or fahrenheit f",
|
||||
enum: %w[c f],
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
summary: "Test tool summary",
|
||||
created_by_id: -1,
|
||||
)
|
||||
@ -58,6 +66,27 @@ RSpec.describe DiscourseAi::Admin::AiToolsController do
|
||||
expect(response).to have_http_status(:created)
|
||||
expect(response.parsed_body["ai_tool"]["name"]).to eq("Test Tool")
|
||||
end
|
||||
|
||||
context "when the parameter is a enum" do
|
||||
it "creates the tool with the correct parameters" do
|
||||
attrs = valid_attributes
|
||||
attrs[:parameters] = [attrs[:parameters].first.merge(enum: %w[c f])]
|
||||
|
||||
expect {
|
||||
post "/admin/plugins/discourse-ai/ai-tools.json",
|
||||
params: { ai_tool: valid_attributes }.to_json,
|
||||
headers: {
|
||||
"CONTENT_TYPE" => "application/json",
|
||||
}
|
||||
}.to change(AiTool, :count).by(1)
|
||||
|
||||
expect(response).to have_http_status(:created)
|
||||
expect(response.parsed_body.dig("ai_tool", "parameters", 0, "enum")).to contain_exactly(
|
||||
"c",
|
||||
"f",
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "PUT #update" do
|
||||
@ -72,6 +101,27 @@ RSpec.describe DiscourseAi::Admin::AiToolsController do
|
||||
expect(response).to be_successful
|
||||
expect(ai_tool.reload.name).to eq("Updated Tool")
|
||||
end
|
||||
|
||||
context "when updating an enum parameters" do
|
||||
it "updates the enum fixed values" do
|
||||
put "/admin/plugins/discourse-ai/ai-tools/#{ai_tool.id}.json",
|
||||
params: {
|
||||
ai_tool: {
|
||||
parameters: [
|
||||
{
|
||||
name: "unit",
|
||||
type: "string",
|
||||
description: "the unit of measurement celcius c or fahrenheit f",
|
||||
enum: %w[g d],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
expect(response).to be_successful
|
||||
expect(ai_tool.reload.parameters.dig(0, "enum")).to contain_exactly("g", "d")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE #destroy" do
|
||||
|
Loading…
x
Reference in New Issue
Block a user