Class: Legion::Extensions::Llm::Anthropic::Helpers::Callable

Inherits:
Object
  • Object
show all
Defined in:
lib/legion/extensions/llm/anthropic/helpers/callable.rb

Overview

Callable wrapper for an Anthropic provider instance. Implements the fleet dispatch operations (chat, stream_chat, embed, count_tokens) by delegating to a per-instance Anthropic::Provider, plus the disconnect and normalize_dispatch_error(error:) contracts required by Inventory::CallableHandle and Routing::ProviderOutcome.

Dispatch errors propagate unmodified so the coordinator can classify them through normalize_dispatch_error.

CRITICAL: Anthropic 529 overloaded_error is ALWAYS :overloaded. It is NEVER :instance_unavailable. Only explicit connection failures at the transport layer map to :connection_failure (which the discovery harness may escalate to :instance_unavailable).

Constant Summary collapse

CHAT_PROVIDER_KEYS =

Provider dispatch kwargs the 0.8.0 base funnel accepts by name. temperature is not one of them (05 O4) — it lives only in Canonical::Params. Any other fleet param is merged into the provider params: passthrough as canonical Params.

%i[tools params headers schema thinking tool_prefs].freeze
EMBED_PROVIDER_KEYS =
%i[dimensions params headers].freeze

Instance Method Summary collapse

Constructor Details

#initialize(instance_cfg:, logger:) ⇒ Callable

Returns a new instance of Callable.



35
36
37
38
39
40
# File 'lib/legion/extensions/llm/anthropic/helpers/callable.rb', line 35

def initialize(instance_cfg:, logger:)
  @instance_cfg = instance_cfg
  @logger = logger
  @provider_mutex = Mutex.new
  @disconnected = false
end

Instance Method Details

#chat(messages, model:, **rest) ⇒ Object



53
54
55
56
57
58
59
60
# File 'lib/legion/extensions/llm/anthropic/helpers/callable.rb', line 53

def chat(messages, model:, **rest)
  # Canonical boundary (N x N law): fleet dispatch delivers
  # Canonical::Message objects only. Native/Hash shapes are the
  # bypass class (the 2026-08-19 incident) — reject loudly, never coerce.
  provider.enforce_canonical_messages!(messages)
  provider.chat(messages, model:,
                          **dispatch_kwargs(rest, known: CHAT_PROVIDER_KEYS))
end

#count_tokens(messages:, model:, **rest) ⇒ Object



73
74
75
# File 'lib/legion/extensions/llm/anthropic/helpers/callable.rb', line 73

def count_tokens(messages:, model:, **rest)
  provider.count_tokens(messages: messages, model:, params: rest)
end

#disconnectObject



77
78
79
80
81
82
83
84
# File 'lib/legion/extensions/llm/anthropic/helpers/callable.rb', line 77

def disconnect
  @provider_mutex.synchronize do
    @disconnected = true
    @provider&.disconnect
    @provider = nil
  end
  @logger.debug { '[anthropic][callable] disconnected' }
end

#disconnected?Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/legion/extensions/llm/anthropic/helpers/callable.rb', line 49

def disconnected?
  @disconnected
end

#embed(text:, model:, **rest) ⇒ Object



68
69
70
71
# File 'lib/legion/extensions/llm/anthropic/helpers/callable.rb', line 68

def embed(text:, model:, **rest)
  provider.embed(text: text, model:,
                           **dispatch_kwargs(rest, known: EMBED_PROVIDER_KEYS))
end

#normalize_dispatch_error(error:) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/legion/extensions/llm/anthropic/helpers/callable.rb', line 86

def normalize_dispatch_error(error:)
  reason = error.message.to_s[0, 512]

  kind = case error
         when Faraday::ConnectionFailed
           :connection_failure
         when Faraday::TimeoutError
           :timeout
         when Faraday::ClientError
           classify_client_error(error: error)
         when Faraday::ServerError
           classify_server_error(error: error)
         when Legion::Extensions::Llm::OverloadedError
           :overloaded
         else
           :provider_error
         end

  Legion::Extensions::Llm::Routing::ProviderOutcome.new(
    kind:   kind,
    reason: reason.empty? ? 'unknown dispatch error' : reason
  )
end

#providerObject

The wrapped per-instance provider (built lazily on first dispatch).



43
44
45
46
47
# File 'lib/legion/extensions/llm/anthropic/helpers/callable.rb', line 43

def provider
  @provider_mutex.synchronize do
    @provider ||= build_provider
  end
end

#stream_chat(messages, model:, **rest) ⇒ Object



62
63
64
65
66
# File 'lib/legion/extensions/llm/anthropic/helpers/callable.rb', line 62

def stream_chat(messages, model:, **rest, &)
  provider.enforce_canonical_messages!(messages)
  provider.stream_chat(messages, model:,
                                 **dispatch_kwargs(rest, known: CHAT_PROVIDER_KEYS), &)
end