Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion bwh_hive/bwh_hive/doctype/hive_settings/hive_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"default_agent_template_slug",
"skills_repo",
"anthropic_api_key",
"claude_code_oauth_token",
"agent_prompts_section",
"agent_spec_prompt",
"agent_implement_prompt",
Expand Down Expand Up @@ -170,11 +171,17 @@
"label": "Skills Repo"
},
{
"description": "Injected into boxes as ANTHROPIC_API_KEY for Claude Code.",
"description": "Injected into boxes as ANTHROPIC_API_KEY for Claude Code (API billing).",
"fieldname": "anthropic_api_key",
"fieldtype": "Password",
"label": "Anthropic API Key"
},
{
"description": "Claude subscription token from `claude setup-token`. Injected as CLAUDE_CODE_OAUTH_TOKEN. Used only when no Anthropic API Key is set — lets boxes auth via a Claude subscription instead of API billing.",
"fieldname": "claude_code_oauth_token",
"fieldtype": "Password",
"label": "Claude Code OAuth Token"
},
{
"collapsible": 1,
"fieldname": "agent_prompts_section",
Expand Down
10 changes: 9 additions & 1 deletion bwh_hive/bwh_hive/orchestrator/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ def build_boot_env(task: Document) -> dict:
spec_run_timeout = max(spec_min - 5, 5) * 60
impl_run_timeout = max(impl_min - 5, 5) * 60

# Claude auth: an Anthropic API key (API billing) OR a subscription OAuth token from
# `claude setup-token`. The box's claude falls back to the OAuth token when
# ANTHROPIC_API_KEY is empty, so only forward the token when no API key is set —
# never both, to avoid an ambiguous auth mode.
anthropic_api_key = settings.get_password("anthropic_api_key", raise_exception=False) or ""
oauth_token = settings.get_password("claude_code_oauth_token", raise_exception=False) or ""

env = {
"AGENT_MODE": "1",
"HIVE_BASE_URL": frappe.utils.get_url(),
Expand All @@ -134,7 +141,8 @@ def build_boot_env(task: Document) -> dict:
"TARGET_APP_REPO": project.get("target_app_repo") or "",
"TARGET_APP_BRANCH": project.get("target_app_branch") or "develop",
"SKILLS_REPO": skills_repo or "",
"ANTHROPIC_API_KEY": settings.get_password("anthropic_api_key", raise_exception=False) or "",
"ANTHROPIC_API_KEY": anthropic_api_key,
"CLAUDE_CODE_OAUTH_TOKEN": oauth_token if not anthropic_api_key else "",
"SPEC_RUN_TIMEOUT": spec_run_timeout,
"IMPL_RUN_TIMEOUT": impl_run_timeout,
}
Expand Down
Loading