Class: Esp::Providers::Anthropic

Inherits:
Object
  • Object
show all
Defined in:
lib/esp/providers/anthropic.rb

Overview

The Anthropic Messages API implementation of the provider contract. It translates the neutral transcript to Messages-API shape, prompt-caches the stable tools+system preamble, and normalizes the response back. The client is injected for tests; the real one is built lazily so no key is needed until a live run.

Constant Summary collapse

DEFAULT_MODEL =
'claude-sonnet-4-6'.freeze
MAX_TOKENS =
16_000
ENV_KEY =
'ANTHROPIC_API_KEY'.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client: nil, model: DEFAULT_MODEL, max_tokens: MAX_TOKENS) ⇒ Anthropic

Returns a new instance of Anthropic.



18
19
20
21
22
# File 'lib/esp/providers/anthropic.rb', line 18

def initialize(client: nil, model: DEFAULT_MODEL, max_tokens: MAX_TOKENS)
  @client = client
  @model = model
  @max_tokens = max_tokens
end

Class Method Details

.configured?Boolean

“Configured” = the SDK has a key to authenticate with.

Returns:

  • (Boolean)


14
15
16
# File 'lib/esp/providers/anthropic.rb', line 14

def self.configured?
  !ENV.fetch(ENV_KEY, '').to_s.empty?
end

Instance Method Details

#complete(system:, tools:, messages:) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/esp/providers/anthropic.rb', line 24

def complete(system:, tools:, messages:)
  response = client.messages.create(
    model: @model,
    max_tokens: @max_tokens,
    thinking: { type: 'adaptive' },
    # tools render before system, so caching the system block caches the
    # whole (stable) tools + system preamble.
    system_: [{ type: 'text', text: system, cache_control: { type: 'ephemeral' } }],
    # `tools` already arrives in the {name, description, input_schema}
    # shape the Messages API wants.
    tools: tools,
    messages: messages.map { |message| native_message(message) }
  )
  blocks = response.content
  text = blocks.select { |b| b.type == :text }.map(&:text).join("\n")
  tool_calls = blocks.select { |b| b.type == :tool_use }
                     .map { |b| { id: b.id, name: b.name.to_s, input: b.input || {} } }
  Completion.new(text: text, tool_calls: tool_calls, raw: { role: 'assistant', content: blocks })
end