mirror of
https://github.com/discourse/discourse-ai.git
synced 2025-02-07 03:58:18 +00:00
This changeset contains 4 fixes: 1. We were allowing running tests on unsaved tools, this is problematic cause uploads are not yet associated or indexed leading to confusing results. We now only show the test button when tool is saved. 2. We were not properly scoping rag document fragements, this meant that personas and ai tools could get results from other unrelated tools, just to be filtered out later 3. index.search showed options as "optional" but implementation required the second option 4. When testing tools searching through document fragments was not working at all cause we did not properly load the tool
193 lines
5.6 KiB
Ruby
193 lines
5.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe DiscourseAi::Admin::AiToolsController do
|
|
fab!(:admin)
|
|
fab!(:ai_tool) do
|
|
AiTool.create!(
|
|
name: "Test Tool",
|
|
description: "A test tool",
|
|
script: "function invoke(params) { return params; }",
|
|
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,
|
|
)
|
|
end
|
|
|
|
before do
|
|
sign_in(admin)
|
|
SiteSetting.ai_embeddings_enabled = true
|
|
end
|
|
|
|
describe "GET #index" do
|
|
it "returns a success response" do
|
|
get "/admin/plugins/discourse-ai/ai-tools.json"
|
|
expect(response).to be_successful
|
|
expect(response.parsed_body["ai_tools"].length).to eq(AiTool.count)
|
|
expect(response.parsed_body["meta"]["presets"].length).to be > 0
|
|
end
|
|
end
|
|
|
|
describe "GET #show" do
|
|
it "returns a success response" do
|
|
get "/admin/plugins/discourse-ai/ai-tools/#{ai_tool.id}.json"
|
|
expect(response).to be_successful
|
|
expect(response.parsed_body["ai_tool"]["name"]).to eq(ai_tool.name)
|
|
end
|
|
end
|
|
|
|
describe "POST #create" do
|
|
let(:valid_attributes) do
|
|
{
|
|
name: "Test Tool",
|
|
description: "A test tool",
|
|
parameters: [{ name: "query", type: "string", description: "perform a search" }],
|
|
script: "function invoke(params) { return params; }",
|
|
summary: "Test tool summary",
|
|
}
|
|
end
|
|
|
|
it "creates a new AiTool" do
|
|
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["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
|
|
it "updates the requested ai_tool" do
|
|
put "/admin/plugins/discourse-ai/ai-tools/#{ai_tool.id}.json",
|
|
params: {
|
|
ai_tool: {
|
|
name: "Updated Tool",
|
|
},
|
|
}
|
|
|
|
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
|
|
it "destroys the requested ai_tool" do
|
|
expect { delete "/admin/plugins/discourse-ai/ai-tools/#{ai_tool.id}.json" }.to change(
|
|
AiTool,
|
|
:count,
|
|
).by(-1)
|
|
|
|
expect(response).to have_http_status(:no_content)
|
|
end
|
|
end
|
|
|
|
describe "#test" do
|
|
it "runs an existing tool and returns the result" do
|
|
post "/admin/plugins/discourse-ai/ai-tools/#{ai_tool.id}/test.json",
|
|
params: {
|
|
parameters: {
|
|
input: "Hello, World!",
|
|
},
|
|
}
|
|
|
|
expect(response.status).to eq(200)
|
|
expect(response.parsed_body["output"]).to eq("input" => "Hello, World!")
|
|
end
|
|
|
|
it "accept changes to the ai_tool parameters that redefine stuff" do
|
|
post "/admin/plugins/discourse-ai/ai-tools/#{ai_tool.id}/test.json",
|
|
params: {
|
|
ai_tool: {
|
|
script: "function invoke(params) { return 'hi there'; }",
|
|
},
|
|
parameters: {
|
|
input: "Hello, World!",
|
|
},
|
|
}
|
|
|
|
expect(response.status).to eq(200)
|
|
expect(response.parsed_body["output"]).to eq("hi there")
|
|
end
|
|
|
|
it "returns an error for invalid tool_id" do
|
|
post "/admin/plugins/discourse-ai/ai-tools/-1/test.json",
|
|
params: {
|
|
parameters: {
|
|
input: "Hello, World!",
|
|
},
|
|
}
|
|
|
|
expect(response.status).to eq(404)
|
|
end
|
|
|
|
it "handles exceptions during tool execution" do
|
|
ai_tool.update!(script: "function invoke(params) { throw new Error('Test error'); }")
|
|
|
|
post "/admin/plugins/discourse-ai/ai-tools/#{ai_tool.id}/test.json",
|
|
params: {
|
|
id: ai_tool.id,
|
|
parameters: {
|
|
input: "Hello, World!",
|
|
},
|
|
}
|
|
|
|
expect(response.status).to eq(400)
|
|
expect(response.parsed_body["errors"].to_s).to include("Error executing the tool")
|
|
end
|
|
end
|
|
end
|