require "net/http"require "json"require "uri"class FirecrawlService BASE_URL = "https://api.firecrawl.dev/v2" def initialize(api_key: ENV.fetch("FIRECRAWL_API_KEY")) @api_key = api_key end def search(query, limit: 5) post("/search", { query: query, limit: limit }) end def scrape(url, **options) post("/scrape", { url: url }.merge(options)) end def interact(url, prompt, follow_up: nil) # 1. Scrape to open a browser session scrape_result = scrape(url, formats: ["markdown"]) scrape_id = scrape_result.dig("data", "metadata", "scrapeId") # 2. Send first prompt post("/scrape/#{scrape_id}/interact", { prompt: prompt }) # 3. Send follow-up prompt result = nil if follow_up result = post("/scrape/#{scrape_id}/interact", { prompt: follow_up }) end # 4. Close the session delete("/scrape/#{scrape_id}/interact") result || scrape_result end private def post(endpoint, payload) uri = URI("#{BASE_URL}#{endpoint}") request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer #{@api_key}" request["Content-Type"] = "application/json" request.body = payload.to_json response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end JSON.parse(response.body) end def delete(endpoint) uri = URI("#{BASE_URL}#{endpoint}") request = Net::HTTP::Delete.new(uri) request["Authorization"] = "Bearer #{@api_key}" Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end endend