Class: Ask::Providers::Cloudflare

Inherits:
Ask::Provider
  • Object
show all
Includes:
LLM::SSEBuffer
Defined in:
lib/ask/provider/cloudflare.rb

Overview

Cloudflare Workers AI provider. Supports both direct Workers AI and AI Gateway.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from LLM::SSEBuffer

#each_sse_event, #init_sse_buffer

Constructor Details

#initialize(config = {}) ⇒ Cloudflare

Returns a new instance of Cloudflare.



8
9
10
11
12
# File 'lib/ask/provider/cloudflare.rb', line 8

def initialize(config = {})
  config = normalize_config(config)
  super(config)
  @http = build_http
end

Class Method Details

.capabilitiesObject



55
56
57
# File 'lib/ask/provider/cloudflare.rb', line 55

def capabilities
  { chat: true, streaming: true, vision: true }
end

.configuration_optionsObject



58
# File 'lib/ask/provider/cloudflare.rb', line 58

def configuration_options; %i[api_key account_id gateway_id]; end

.configuration_requirementsObject



59
# File 'lib/ask/provider/cloudflare.rb', line 59

def configuration_requirements; %i[api_key account_id]; end

.slugObject



60
# File 'lib/ask/provider/cloudflare.rb', line 60

def slug; "cloudflare"; end

Instance Method Details

#api_baseObject



14
15
16
17
18
19
20
# File 'lib/ask/provider/cloudflare.rb', line 14

def api_base
  if @config.gateway_id
    "https://gateway.ai.cloudflare.com/v1/#{@config.}/#{@config.gateway_id}"
  else
    "https://api.cloudflare.com/client/v4/accounts/#{@config.}/ai/v1"
  end
end

#chat(messages, model:, tools: nil, temperature: nil, stream: nil, schema: nil, **params, &block) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/ask/provider/cloudflare.rb', line 26

def chat(messages, model:, tools: nil, temperature: nil, stream: nil, schema: nil, **params, &block)
  msgs = messages.is_a?(Ask::Conversation) ? messages.to_a : messages
  endpoint = @config.gateway_id ? "chat/completions" : "run/#{model}"
  payload = if @config.gateway_id
              { model: model, messages: msgs.map { |m| { role: (m[:role] || m["role"]).to_s, content: m[:content] || m["content"] } }, stream: stream || false }
            else
              { messages: msgs.map { |m| { role: (m[:role] || m["role"]).to_s, content: m[:content] || m["content"] } } }
            end
  payload[:temperature] = temperature if temperature
  payload.merge(params)

  if stream && @config.gateway_id
    chat_stream_gateway(endpoint, payload, model, &block)
  else
    chat_nonstream(endpoint, payload, model)
  end
end

#headersObject



22
23
24
# File 'lib/ask/provider/cloudflare.rb', line 22

def headers
  { "Content-Type" => "application/json", "Authorization" => "Bearer #{@config.api_key}" }.compact
end

#list_modelsObject



44
45
46
47
# File 'lib/ask/provider/cloudflare.rb', line 44

def list_models
  # Workers AI lists models differently — rely on model catalog
  []
end

#parse_error(response) ⇒ Object



49
50
51
52
# File 'lib/ask/provider/cloudflare.rb', line 49

def parse_error(response)
  body = response.body rescue nil
  body&.dig("errors", 0, "message") || body&.dig("error", "message")
end