An API key is no longer required if base_url is pointed to a non-default endpoint

This commit is contained in:
2026-05-04 11:11:06 -05:00
parent 410c57f8d5
commit fac1629417
6 changed files with 153 additions and 9 deletions

View File

@@ -199,7 +199,7 @@ def test_client_cache_identity_uses_timeout(monkeypatch):
def test_missing_api_key_error_is_provider_neutral():
client = OpenAICompatibleStructuredLLMClient()
with pytest.raises(AuditaLLMError, match="AUDITA_VALIDATION_LLM_API_KEY"):
with pytest.raises(AuditaLLMError, match="OpenRouter endpoint"):
client.run_structured(
stage_name="test-stage",
messages=[{"role": "user", "content": "Hello"}],
@@ -208,6 +208,32 @@ def test_missing_api_key_error_is_provider_neutral():
)
def test_missing_api_key_is_allowed_for_nondefault_endpoint(monkeypatch):
create_calls, openai_inits = _install_fake_llm_modules(monkeypatch)
client = OpenAICompatibleStructuredLLMClient()
client.run_structured(
stage_name="test-stage",
messages=[{"role": "user", "content": "Hello"}],
response_model=DummyResponseModel,
config=_config(
api_key=None,
model="meta-llama/Llama-3.1-8B-Instruct",
base_url="http://localhost:8000/v1",
),
)
assert openai_inits == [{"api_key": None, "base_url": "http://localhost:8000/v1", "timeout": 600}]
assert create_calls == [
{
"model": "meta-llama/Llama-3.1-8B-Instruct",
"messages": [{"role": "user", "content": "Hello"}],
"response_model": DummyResponseModel,
"max_retries": 3,
}
]
def test_client_initialization_is_safe_under_concurrent_calls(monkeypatch):
_, openai_inits = _install_fake_llm_modules(monkeypatch)
client = OpenAICompatibleStructuredLLMClient()

View File

@@ -220,6 +220,16 @@ def test_validation_llm_api_key_env_is_read():
assert config.validation_llm_api_key == "validation-key"
def test_blank_validation_llm_api_key_override_disables_primary_fallback():
config = AuditaConfig.from_sources(
env={"AUDITA_LLM_API_KEY": "primary-key"},
overrides=ConfigOverrides(validation_llm_api_key=" "),
)
assert config.validation_llm_api_key == ""
assert config.validation_llm_config().api_key == ""
def test_effective_validation_fields_fall_back_to_primary_settings():
config = AuditaConfig.from_sources(
env={

View File

@@ -391,7 +391,7 @@ def test_process_transcript_result_missing_api_key_writes_failed_report(tmp_path
work_dir_retention="never",
)
with pytest.raises(AuditaLLMError, match="AUDITA_LLM_API_KEY"):
with pytest.raises(AuditaLLMError, match="OpenRouter endpoint"):
process_transcript_result(_transcript(), _glossary(), config)
run_dir = next((tmp_path / "work").iterdir())
@@ -413,6 +413,101 @@ def test_process_transcript_result_missing_api_key_writes_failed_report(tmp_path
assert report["work_dir"] == str(run_dir)
assert "AUDITA_LLM_API_KEY" in report["error"]
assert "OPENROUTER_API_KEY" in report["error"]
assert "OpenRouter endpoint" in report["error"]
def test_process_transcript_result_allows_missing_api_key_for_nondefault_proposal_endpoint(tmp_path):
llm_client = FakeStructuredLLMClient(
[
{"corrections": []},
{"corrections": []},
{"corrections": []},
{"corrections": []},
{"corrections": []},
]
)
config = AuditaConfig.from_sources(
env={},
overrides=ConfigOverrides(
base_url="http://localhost:8000/v1",
model="meta-llama/Llama-3.1-8B-Instruct",
work_dir=tmp_path / "work",
work_dir_retention="always",
),
)
result = process_transcript_result(_transcript(), _glossary(), config, llm_client=llm_client)
assert result.report.status == "success"
assert llm_client.calls[0]["config"].api_key is None
assert llm_client.calls[0]["config"].base_url == "http://localhost:8000/v1"
def test_process_transcript_result_allows_missing_validation_api_key_for_nondefault_validation_endpoint(tmp_path):
llm_client = FakeStructuredLLMClient(
{
"grammar:proposal": {
"corrections": [
{
"id": 1,
"original_text": "hello world",
"corrected_text": "Hello world.",
"confidence": 0.95,
}
]
},
"grammar:grammar_only_guard": {
"validations": [
{
"correction_index": 0,
"approved": True,
"confidence": 0.98,
"reason": "ok",
}
]
},
"grammar:meaning_reversal_review": {
"validations": [
{
"correction_index": 0,
"approved": True,
"confidence": 0.99,
"reason": "ok",
}
]
},
}
)
config = AuditaConfig.from_sources(
env={"OPENROUTER_API_KEY": "primary-key"},
overrides=ConfigOverrides(
work_dir=tmp_path / "work",
work_dir_retention="always",
validation_llm_api_key=" ",
validation_base_url="http://localhost:9000/v1",
validation_model="meta-llama/Llama-3.1-8B-Instruct",
),
)
result = process_transcript_result(
parse_source_transcript_json(
"""
[
{"speaker": "Eric", "start": 0.0, "end": 1.0, "text": "hello world"}
]
"""
),
_glossary(),
config,
module_keys=["grammar"],
llm_client=llm_client,
)
assert result.transcript[0].text == "Hello world."
calls_by_stage = {call["stage_name"]: call["config"] for call in llm_client.calls}
assert calls_by_stage["grammar:proposal"].api_key == "primary-key"
assert calls_by_stage["grammar:grammar_only_guard"].api_key == ""
assert calls_by_stage["grammar:grammar_only_guard"].base_url == "http://localhost:9000/v1"
def test_process_transcript_result_preserves_partial_progress_when_later_module_fails(tmp_path):