Class: Mana::Backends::Anthropic
- Defined in:
- lib/mana/backends/anthropic.rb
Overview
Native Anthropic Claude backend.
Sends requests directly to the Anthropic Messages API (/v1/messages). No format conversion needed — Mana's internal format matches Anthropic's.
Constant Summary
Constants inherited from Base
Instance Method Summary collapse
-
#chat(system:, messages:, tools:, model:, max_tokens: 4096) ⇒ Object
Non-streaming request.
-
#chat_stream(system:, messages:, tools:, model:, max_tokens: 4096, &on_event) ⇒ Object
Streaming variant — yields :text_delta, text: "..." events.
Methods inherited from Base
Constructor Details
This class inherits a constructor from Mana::Backends::Base
Instance Method Details
#chat(system:, messages:, tools:, model:, max_tokens: 4096) ⇒ Object
Non-streaming request. Returns content blocks directly since our internal format already matches Anthropic's — no normalization needed (unlike OpenAI).
12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/mana/backends/anthropic.rb', line 12 def chat(system:, messages:, tools:, model:, max_tokens: 4096) uri = URI("#{@config.effective_base_url}/v1/messages") parsed = http_post(uri, { model:, max_tokens:, system:, tools:, messages: }, { "x-api-key" => @config.api_key, "anthropic-version" => "2023-06-01" }) { content: parsed[:content] || [], usage: parsed[:usage] } end |
#chat_stream(system:, messages:, tools:, model:, max_tokens: 4096, &on_event) ⇒ Object
Streaming variant — yields :text_delta, text: "..." events. Returns the complete content blocks array (same format as chat).
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/mana/backends/anthropic.rb', line 26 def chat_stream(system:, messages:, tools:, model:, max_tokens: 4096, &on_event) uri = URI("#{@config.effective_base_url}/v1/messages") content_blocks = [] current_block = nil usage = {} # Anthropic streams SSE events that incrementally build content blocks. # We reassemble them into the same format that chat() returns. http_post_stream(uri, { model:, max_tokens:, system:, tools:, messages:, stream: true }, { "x-api-key" => @config.api_key, "anthropic-version" => "2023-06-01" }) do |event| case event[:type] when "message_start" usage[:input_tokens] = event.dig(:message, :usage, :input_tokens) when "message_delta" usage[:output_tokens] = event.dig(:usage, :output_tokens) when "content_block_start" current_block = event[:content_block].dup # Tool input arrives as JSON fragments — accumulate as a string, parse on stop current_block[:input] = +"" if current_block[:type] == "tool_use" when "content_block_delta" delta = event[:delta] if delta[:type] == "text_delta" current_block[:text] = (current_block[:text] || +"") << delta[:text] on_event&.call(type: :text_delta, text: delta[:text]) elsif delta[:type] == "input_json_delta" current_block[:input] << delta[:partial_json] end when "content_block_stop" # Parse the accumulated JSON string into a Ruby hash for tool_use blocks if current_block && current_block[:type] == "tool_use" current_block[:input] = begin JSON.parse(current_block[:input], symbolize_names: true) rescue JSON::ParserError {} end end content_blocks << current_block if current_block current_block = nil end end { content: content_blocks, usage: usage.empty? ? nil : usage } end |