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 1 commit
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
1 change: 1 addition & 0 deletions app/models/ai_tool.rb
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ def self.preamble
* base_64_content (string): Base64 encoded content of the file.
* Returns: { id: number, url: string, short_url: string } - Details of the created upload record.
*
* upload.getUrl(shortUrl): Given a short URL, eg upload://12345, returns the full CDN friendly URL of the upload.
* 5. chain
* Controls the execution flow.
*
Expand Down
18 changes: 18 additions & 0 deletions lib/personas/tool_runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ def framework_script

const upload = {
create: _upload_create,
getUrl: _upload_get_url,
}

const chain = {
Expand Down Expand Up @@ -570,6 +571,23 @@ def attach_discourse(mini_racer_context)
end

def attach_upload(mini_racer_context)
mini_racer_context.attach(
"_upload_get_url",
->(short_url) do
in_attached_function do
return nil if short_url.blank?

sha1 = Upload.sha1_from_short_url(short_url)
return nil if sha1.blank?

upload = Upload.find_by(sha1: sha1)
return nil if upload.nil?
# TODO we may need to introduce an API to unsecure, secure uploads

GlobalPath.full_cdn_url(upload.url)
end
end,
)
mini_racer_context.attach(
"_upload_create",
->(filename, base_64_content) do
Expand Down
60 changes: 60 additions & 0 deletions spec/models/ai_tool_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -675,4 +675,64 @@ def stub_embeddings
expect(ai_persona.temperature).to eq(0.5)
end
end

describe "upload URL resolution" do
it "can resolve upload short URLs to public URLs" do
upload =
Fabricate(
:upload,
sha1: "abcdef1234567890abcdef1234567890abcdef12",
url: "/uploads/default/original/1X/test.jpg",
original_filename: "test.jpg",
)

script = <<~JS
function invoke(params) {
return upload.getUrl(params.short_url);
}
JS

tool = create_tool(script: script)
runner = tool.runner({ "short_url" => upload.short_url }, llm: nil, bot_user: nil)

result = runner.invoke

expect(result).to eq(GlobalPath.full_cdn_url(upload.url))
end

it "returns null for invalid upload short URLs" do
script = <<~JS
function invoke(params) {
return upload.getUrl(params.short_url);
}
JS

tool = create_tool(script: script)
runner = tool.runner({ "short_url" => "upload://invalid" }, llm: nil, bot_user: nil)

result = runner.invoke

expect(result).to be_nil
end

it "returns null for non-existent uploads" do
script = <<~JS
function invoke(params) {
return upload.getUrl(params.short_url);
}
JS

tool = create_tool(script: script)
runner =
tool.runner(
{ "short_url" => "upload://hwmUkTAL9mwhQuRMLsXw6tvDi5C.jpeg" },
llm: nil,
bot_user: nil,
)

result = runner.invoke

expect(result).to be_nil
end
end
end
Loading