deerflow2/backend/tests
taka6745 eaaa100c10 fix(oauth): inject billing header for Claude oAuth Models (#1442)
* fix(oauth): inject billing header for non-Haiku model access

The Anthropic Messages API requires a billing identification block
in the system prompt when using Claude Code OAuth tokens (sk-ant-oat*)
to access non-Haiku models (Opus, Sonnet). Without it, the API returns
a generic 400 "Error" with no actionable detail.

This was discovered by intercepting Claude Code CLI requests — the CLI
injects an `x-anthropic-billing-header` text block as the first system
prompt entry on every request. Third-party consumers of the same OAuth
tokens must do the same.

Changes:
- Add `_apply_oauth_billing()` to `ClaudeChatModel` that prepends the
  billing header block to the system prompt when `_is_oauth` is True
- Add `metadata.user_id` with device/session identifiers (required by
  the API alongside the billing header)
- Called from `_get_request_payload()` before prompt caching runs

Verified with Claude Max OAuth tokens against all three model tiers:
- claude-opus-4-6: 200 OK
- claude-sonnet-4-6: 200 OK
- claude-haiku-4-5-20251001: 200 OK (was already working)

Closes #1245

* fix(oauth): address review feedback on billing header injection

- Make OAUTH_BILLING_HEADER configurable via ANTHROPIC_BILLING_HEADER env var
- Normalize billing block to always be first in system list (strip + reinsert)
- Guard metadata with isinstance check for non-dict values
- Replace os.uname() with socket.gethostname() for Windows compat
- Fix docstrings to say "all OAuth requests" instead of "non-Haiku"
- Move inline imports to module level (fixes ruff I001)
- Add 9 unit tests for _apply_oauth_billing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 08:49:34 +08:00
..
conftest.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_acp_config.py feat(acp): add env field to ACPAgentConfig for subprocess env injection (#1447) 2026-03-27 20:03:30 +08:00
test_aio_sandbox_provider.py Fix Windows backend test compatibility (#1384) 2026-03-26 17:39:16 +08:00
test_app_config_reload.py fix(config): reload AppConfig when config path or mtime changes (#1239) 2026-03-22 20:34:01 +08:00
test_artifacts_router.py fix(gateway): enforce safe download for active artifact MIME types to mitigate stored XSS (#1389) 2026-03-26 17:44:25 +08:00
test_channel_file_attachments.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_channels.py fix(telegram): fix reply ordering race condition (#1231) 2026-03-22 19:38:27 +08:00
test_checkpointer.py fix: normalize structured LLM content in serialization and memory updater (#1215) 2026-03-22 17:29:29 +08:00
test_checkpointer_none_fix.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_claude_provider_oauth_billing.py fix(oauth): inject billing header for Claude oAuth Models (#1442) 2026-03-28 08:49:34 +08:00
test_cli_auth_providers.py feat(harness): integration ACP agent tool (#1344) 2026-03-26 14:20:18 +08:00
test_client.py Fix Windows backend test compatibility (#1384) 2026-03-26 17:39:16 +08:00
test_client_e2e.py feat(harness): integration ACP agent tool (#1344) 2026-03-26 14:20:18 +08:00
test_client_live.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_config_version.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_credential_loader.py feat: add Claude Code OAuth and Codex CLI as LLM providers (#1166) 2026-03-22 22:39:50 +08:00
test_custom_agent.py feat(memory): Introduce configurable memory storage abstraction (#1353) 2026-03-27 07:41:06 +08:00
test_dangling_tool_call_middleware.py test: add unit tests for DanglingToolCallMiddleware (#1305) 2026-03-26 00:20:08 +08:00
test_docker_sandbox_mode_detection.py Fix Windows backend test compatibility (#1384) 2026-03-26 17:39:16 +08:00
test_feishu_parser.py feat(harness): integration ACP agent tool (#1344) 2026-03-26 14:20:18 +08:00
test_guardrail_middleware.py feat(guardrails): add pre-tool-call authorization middleware with pluggable providers (#1240) 2026-03-23 18:07:33 +08:00
test_harness_boundary.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_infoquest_client.py feat(harness): integration ACP agent tool (#1344) 2026-03-26 14:20:18 +08:00
test_invoke_acp_agent_tool.py feat(acp): add env field to ACPAgentConfig for subprocess env injection (#1447) 2026-03-27 20:03:30 +08:00
test_lead_agent_model_resolution.py fix(config): fix summarization model alias resolution (#1378) 2026-03-26 14:48:45 +08:00
test_local_sandbox_encoding.py feat(harness): integration ACP agent tool (#1344) 2026-03-26 14:20:18 +08:00
test_loop_detection_middleware.py fix(middleware): use HumanMessage in LoopDetectionMiddleware for Anthropic compat (#1300) 2026-03-25 08:00:01 +08:00
test_mcp_client_config.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_mcp_oauth.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_mcp_sync_wrapper.py feat(harness): integration ACP agent tool (#1344) 2026-03-26 14:20:18 +08:00
test_memory_prompt_injection.py feat(harness): integration ACP agent tool (#1344) 2026-03-26 14:20:18 +08:00
test_memory_storage.py feat(memory): Introduce configurable memory storage abstraction (#1353) 2026-03-27 07:41:06 +08:00
test_memory_updater.py feat(memory): Introduce configurable memory storage abstraction (#1353) 2026-03-27 07:41:06 +08:00
test_memory_upload_filtering.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_model_config.py feat(codex): support explicit OpenAI Responses API config (#1235) 2026-03-22 20:39:26 +08:00
test_model_factory.py feat(harness): integration ACP agent tool (#1344) 2026-03-26 14:20:18 +08:00
test_patched_minimax.py fix: improve MiniMax code plan integration (#1169) 2026-03-20 17:18:59 +08:00
test_patched_openai.py fix(LLM): fixing Gemini thinking + tool calls via OpenAI gateway (#1180) (#1205) 2026-03-26 15:07:05 +08:00
test_present_file_tool_core_logic.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_provisioner_kubeconfig.py feat(subagents): make subagent timeout configurable via config.yaml (#897) 2026-02-25 08:39:29 +08:00
test_readability.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_reflection_resolvers.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_sandbox_tools_security.py feat(harness): integration ACP agent tool (#1344) 2026-03-26 14:20:18 +08:00
test_serialize_message_content.py feat(harness): integration ACP agent tool (#1344) 2026-03-26 14:20:18 +08:00
test_skills_archive_root.py refactor: extract shared skill installer and upload manager to harness (#1202) 2026-03-25 16:28:33 +08:00
test_skills_installer.py Fix Windows backend test compatibility (#1384) 2026-03-26 17:39:16 +08:00
test_skills_loader.py feat(harness): integration ACP agent tool (#1344) 2026-03-26 14:20:18 +08:00
test_skills_parser.py test: add unit tests for skills parser (#1308) 2026-03-25 10:17:40 +08:00
test_skills_validation.py test: add unit tests for skill frontmatter validation (#1309) 2026-03-27 20:20:31 +08:00
test_subagent_executor.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_subagent_limit_middleware.py test: add unit tests for SubagentLimitMiddleware (#1306) 2026-03-25 10:20:16 +08:00
test_subagent_timeout_config.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_suggestions_router.py fix(gateway): accept output_text suggestion blocks (#1238) 2026-03-22 19:59:54 +08:00
test_task_tool_core_logic.py fix(task): avoid blocking in task tool polling (#1320) 2026-03-27 17:12:40 +08:00
test_thread_data_middleware.py Fix Windows backend test compatibility (#1384) 2026-03-26 17:39:16 +08:00
test_threads_router.py fix(threads): clean up local thread data after thread deletion (#1262) 2026-03-24 00:36:08 +08:00
test_title_generation.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_title_middleware_core_logic.py fix: add sync after_model to TitleMiddleware (#1190) 2026-03-19 15:46:31 +08:00
test_todo_middleware.py test: add unit tests for TodoMiddleware (#1307) 2026-03-26 00:20:50 +08:00
test_token_usage.py feat(harness): integration ACP agent tool (#1344) 2026-03-26 14:20:18 +08:00
test_tool_error_handling_middleware.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_tool_search.py feat(harness): integration ACP agent tool (#1344) 2026-03-26 14:20:18 +08:00
test_tracing_config.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_uploads_manager.py Fix Windows backend test compatibility (#1384) 2026-03-26 17:39:16 +08:00
test_uploads_middleware_core_logic.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
test_uploads_router.py fix(sandbox): Relax upload permissions for aio sandbox sync (#1409) 2026-03-27 17:37:44 +08:00