Class: Providers::Anthropic
- Inherits:
-
Object
- Object
- Providers::Anthropic
show all
- Includes:
- HTTParty
- Defined in:
- lib/providers/anthropic.rb
Defined Under Namespace
Classes: AuthenticationError, Error, RateLimitError, ServerError, TokenFormatError, TransientError
Constant Summary
collapse
- TOKEN_PREFIX =
"sk-ant-oat01-"
- TOKEN_MIN_LENGTH =
80
- API_VERSION =
"2023-06-01"
- REQUIRED_BETA =
"oauth-2025-04-20"
- VALIDATION_MODEL =
"claude-sonnet-4-20250514"
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize(token = nil) ⇒ Anthropic
Returns a new instance of Anthropic.
69
70
71
|
# File 'lib/providers/anthropic.rb', line 69
def initialize(token = nil)
@token = token || self.class.fetch_token
end
|
Instance Attribute Details
#token ⇒ Object
Returns the value of attribute token.
67
68
69
|
# File 'lib/providers/anthropic.rb', line 67
def token
@token
end
|
Class Method Details
.fetch_token ⇒ Object
35
36
37
38
39
40
41
42
43
44
45
|
# File 'lib/providers/anthropic.rb', line 35
def fetch_token
token = Rails.application.credentials.dig(:anthropic, :subscription_token)
raise AuthenticationError, <<~MSG.strip if token.blank?
No Anthropic subscription token found in credentials.
Run: bin/rails credentials:edit
Add:
anthropic:
subscription_token: sk-ant-oat01-YOUR_TOKEN_HERE
MSG
token
end
|
.validate! ⇒ Object
28
29
30
31
32
33
|
# File 'lib/providers/anthropic.rb', line 28
def validate!
token = fetch_token
validate_token_format!(token)
validate_token_api!(token)
true
end
|
.validate_token_api!(token) ⇒ Object
61
62
63
64
|
# File 'lib/providers/anthropic.rb', line 61
def validate_token_api!(token)
provider = new(token)
provider.validate_credentials!
end
|
Instance Method Details
#count_tokens(model:, messages:, **options) ⇒ Integer
Count tokens in a message payload without creating a message. Uses the free Anthropic token counting endpoint.
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
# File 'lib/providers/anthropic.rb', line 95
def count_tokens(model:, messages:, **options)
body = {model: model, messages: messages}.merge(options)
response = self.class.post(
"/v1/messages/count_tokens",
body: body.to_json,
headers:
)
result = handle_response(response)
result["input_tokens"]
rescue Errno::ECONNRESET, Net::ReadTimeout, Net::OpenTimeout, SocketError, EOFError => e
raise TransientError, "#{e.class}: #{e.message}"
end
|
#create_message(model:, messages:, max_tokens:, **options) ⇒ Object
73
74
75
76
77
78
79
80
81
82
83
84
85
|
# File 'lib/providers/anthropic.rb', line 73
def create_message(model:, messages:, max_tokens:, **options)
body = {model: model, messages: messages, max_tokens: max_tokens}.merge(options)
response = self.class.post(
"/v1/messages",
body: body.to_json,
headers:
)
handle_response(response)
rescue Errno::ECONNRESET, Net::ReadTimeout, Net::OpenTimeout, SocketError, EOFError => e
raise TransientError, "#{e.class}: #{e.message}"
end
|
#validate_credentials! ⇒ Object
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
# File 'lib/providers/anthropic.rb', line 110
def validate_credentials!
response = self.class.post(
"/v1/messages",
body: {
model: VALIDATION_MODEL,
messages: [{role: "user", content: "Hi"}],
max_tokens: 1
}.to_json,
headers:
)
case response.code
when 200
true
when 401
raise AuthenticationError,
"Token rejected by Anthropic API (401). Re-run `claude setup-token` and update credentials."
when 403
raise AuthenticationError,
"Token not authorized for API access (403). This credential may be restricted to Claude Code only."
else
handle_response(response)
end
end
|