discourse-ai/lib/ai_bot/tools/github_file_content.rb

103 lines
2.9 KiB
Ruby

# frozen_string_literal: true
module DiscourseAi
module AiBot
module Tools
class GithubFileContent < Tool
def self.signature
{
name: name,
description: "Retrieves the content of specified GitHub files",
parameters: [
{
name: "repo_name",
description: "The name of the GitHub repository (e.g., 'discourse/discourse')",
type: "string",
required: true,
},
{
name: "file_paths",
description: "The paths of the files to retrieve within the repository",
type: "array",
item_type: "string",
required: true,
},
{
name: "branch",
description:
"The branch or commit SHA to retrieve the files from (default: 'main')",
type: "string",
required: false,
},
],
}
end
def self.name
"github_file_content"
end
def repo_name
parameters[:repo_name]
end
def file_paths
parameters[:file_paths]
end
def branch
parameters[:branch] || "main"
end
def description_args
{ repo_name: repo_name, file_paths: file_paths.join(", "), branch: branch }
end
def invoke
owner, repo = repo_name.split("/")
file_contents = {}
missing_files = []
file_paths.each do |file_path|
api_url =
"https://api.github.com/repos/#{owner}/#{repo}/contents/#{file_path}?ref=#{branch}"
response_code = "-1 unknown"
body = nil
send_http_request(
api_url,
headers: {
"Accept" => "application/vnd.github.v3+json",
},
authenticate_github: true,
) do |response|
response_code = response.code
body = read_response_body(response)
end
if response_code == "200"
file_data = JSON.parse(body)
content = Base64.decode64(file_data["content"])
file_contents[file_path] = content
else
missing_files << file_path
end
end
result = {}
unless file_contents.empty?
blob =
file_contents.map { |path, content| "File Path: #{path}:\n#{content}" }.join("\n")
truncated_blob = truncate(blob, max_length: 20_000, percent_length: 0.3, llm: llm)
result[:file_contents] = truncated_blob
end
result[:missing_files] = missing_files unless missing_files.empty?
result.empty? ? { error: "No files found or retrieved." } : result
end
end
end
end
end