mirror of
https://github.com/we-promise/sure.git
synced 2026-06-01 00:39:01 +00:00
Surface fixes raised by Codex + CodeRabbit on PR 1/5:
- Provider::Anthropic#chat_response now accepts (and ignores) a
`messages:` kwarg. Assistant::Responder passes both `messages:`
(OpenAI-shape) and `conversation_history:` (raw Message records) for
cross-provider parity, so the previous signature raised
ArgumentError on the first chat turn through the Anthropic provider.
- Provider::Anthropic#supports_model? bypasses the `claude` prefix
gate when a custom base_url is configured, mirroring the OpenAI
provider. Bedrock-shaped IDs like
`anthropic.claude-sonnet-4-5-20250929-v1:0` and
`claude-opus-4@20250514` are otherwise rejected by
Assistant::Provided#get_model_provider and the chat dies.
- Setting.anthropic_access_token is now in
EncryptedSettingFields::ENCRYPTED_FIELDS so the Anthropic API key
is encrypted at rest like every other provider secret. Previously
plaintext while siblings (openai_access_token, twelve_data_api_key,
external_assistant_token) were ciphertext.
- Chat.default_model falls back to whichever provider is actually
configured. Previously, with LLM_PROVIDER=anthropic but no
Anthropic credentials, the default model resolved to a Claude ID
that no registered provider supported, so chats failed even when
OpenAI was fully configured. Adds Provider::{Anthropic,Openai}#configured?
class methods for the readable callsite.
- Provider::Anthropic.effective_model uses
`ENV["ANTHROPIC_MODEL"].presence || Setting.anthropic_model` so the
Setting lookup is only performed when the env var is absent — the
previous `ENV.fetch(KEY, default)` evaluated the default arg
eagerly on every call.
- Provider::Anthropic::ChatConfig#anthropic_input_schema strips both
`:strict` and `"strict"` keys so JSON-decoded schemas with string
keys cannot leak the OpenAI-only flag through to Anthropic.
Test coverage added: supports_model? bypass on custom endpoints,
chat_response messages: kwarg compatibility, default_model fallback
in the three credential combinations, configured? against ENV +
Setting, strict-flag stripping for both key types, and a
`Setting.expects(:anthropic_model).never` assertion proving the
ENV-precedence test now exercises the lazy path.
All 4365 tests pass (1 pre-existing libvips env error unrelated).
95 lines
3.0 KiB
Ruby
95 lines
3.0 KiB
Ruby
require "test_helper"
|
|
|
|
class Provider::Anthropic::ChatConfigTest < ActiveSupport::TestCase
|
|
test "builds request with default max_tokens and prompt message" do
|
|
config = Provider::Anthropic::ChatConfig.new(prompt: "hello")
|
|
|
|
req = config.build_request(model: "claude-sonnet-4-6")
|
|
|
|
assert_equal "claude-sonnet-4-6", req[:model]
|
|
assert_equal 4096, req[:max_tokens]
|
|
assert_equal [ { role: "user", content: "hello" } ], req[:messages]
|
|
assert_nil req[:system_]
|
|
assert_nil req[:tools]
|
|
end
|
|
|
|
test "honors caller-provided default_max_tokens" do
|
|
config = Provider::Anthropic::ChatConfig.new(prompt: "hi", default_max_tokens: 8192)
|
|
|
|
req = config.build_request(model: "claude-sonnet-4-6")
|
|
|
|
assert_equal 8192, req[:max_tokens]
|
|
end
|
|
|
|
test "wraps instructions as cacheable system block" do
|
|
config = Provider::Anthropic::ChatConfig.new(prompt: "hi", instructions: "Be terse.")
|
|
|
|
req = config.build_request(model: "claude-sonnet-4-6")
|
|
|
|
assert_equal [ {
|
|
type: "text",
|
|
text: "Be terse.",
|
|
cache_control: { type: "ephemeral" }
|
|
} ], req[:system_]
|
|
end
|
|
|
|
test "converts function definitions to Anthropic tool blocks and caches the last one" do
|
|
config = Provider::Anthropic::ChatConfig.new(
|
|
prompt: "hi",
|
|
functions: [
|
|
{
|
|
name: "get_net_worth",
|
|
description: "Returns net worth",
|
|
params_schema: { type: "object", properties: {}, required: [], additionalProperties: false },
|
|
strict: true
|
|
},
|
|
{
|
|
name: "get_accounts",
|
|
description: "Returns accounts",
|
|
params_schema: { type: "object", properties: {}, required: [], additionalProperties: false },
|
|
strict: true
|
|
}
|
|
]
|
|
)
|
|
|
|
req = config.build_request(model: "claude-sonnet-4-6")
|
|
|
|
assert_equal 2, req[:tools].size
|
|
assert_equal "get_net_worth", req[:tools][0][:name]
|
|
assert_equal "Returns net worth", req[:tools][0][:description]
|
|
assert_equal({ type: "object", properties: {}, required: [], additionalProperties: false }, req[:tools][0][:input_schema])
|
|
assert_nil req[:tools][0][:cache_control]
|
|
|
|
assert_equal({ type: "ephemeral" }, req[:tools][1][:cache_control])
|
|
|
|
# Anthropic schemas must not carry the OpenAI-specific `strict` flag.
|
|
req[:tools].each { |t| assert_not t[:input_schema].key?(:strict) }
|
|
end
|
|
|
|
test "strips both symbol and string-keyed `strict` flags from input_schema" do
|
|
config = Provider::Anthropic::ChatConfig.new(
|
|
prompt: "hi",
|
|
functions: [
|
|
{
|
|
name: "fn_with_string_strict",
|
|
description: "schema arrived from JSON.parse with string keys",
|
|
params_schema: {
|
|
"type" => "object",
|
|
"properties" => {},
|
|
"required" => [],
|
|
"additionalProperties" => false,
|
|
"strict" => true
|
|
},
|
|
strict: true
|
|
}
|
|
]
|
|
)
|
|
|
|
req = config.build_request(model: "claude-sonnet-4-6")
|
|
|
|
schema = req[:tools].first[:input_schema]
|
|
assert_not schema.key?(:strict)
|
|
assert_not schema.key?("strict")
|
|
end
|
|
end
|