-
Notifications
You must be signed in to change notification settings - Fork 14
Claude Code: run on a Claude subscription (setup-token) + model/thinking passthroughs #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2906,6 +2906,10 @@ def _base_url_env_items(self) -> list[tuple[str, str]]: | |
| def _langfuse_env_items(self) -> list[tuple[str, str]]: | ||
| return [] | ||
|
|
||
| def _agent_env_items(self) -> list[tuple[str, str]]: | ||
| """Agent-specific container env vars; overridden per runner.""" | ||
| return [] | ||
|
|
||
| def _prepare_agent_home(self, home_dir: Path) -> None: | ||
| return | ||
|
|
||
|
|
@@ -2948,6 +2952,7 @@ def _build_external_docker_base_command( | |
| *self._api_env_items(), | ||
| *self._base_url_env_items(), | ||
| *self._langfuse_env_items(), | ||
| *self._agent_env_items(), | ||
| ]: | ||
| command.extend(["-e", f"{key}={value}"]) | ||
| command.append(self.image_name) | ||
|
|
@@ -3245,15 +3250,31 @@ def _langfuse_env_items(self) -> list[tuple[str, str]]: | |
| ("LANGFUSE_BASE_URL", self._langfuse_container_base_url() or ""), | ||
| ] | ||
|
|
||
| def _agent_env_items(self) -> list[tuple[str, str]]: | ||
| # 0 is meaningful (disables thinking on models that allow it), so only | ||
| # None is "unset". | ||
| if self.config.agent.claude.max_thinking_tokens is None: | ||
| return [] | ||
| return [("MAX_THINKING_TOKENS", str(self.config.agent.claude.max_thinking_tokens))] | ||
|
|
||
| def _prepare_agent_home(self, home_dir: Path) -> None: | ||
| if not self.config.agent.langfuse.enabled: | ||
| settings = self._claude_settings() | ||
| if not settings: | ||
| return | ||
| hook = {"hooks": [{"type": "command", "command": CLAUDE_LANGFUSE_HOOK_COMMAND}]} | ||
| settings = {"hooks": {"Stop": [hook], "SessionEnd": [hook]}} | ||
| settings_path = home_dir / "settings.json" | ||
| settings_path.write_text(json.dumps(settings, indent=2) + "\n", encoding="utf-8") | ||
| settings_path.chmod(0o666) | ||
|
|
||
| def _claude_settings(self) -> dict[str, object]: | ||
| """Compose the container's ~/.claude/settings.json from config.""" | ||
| settings: dict[str, object] = {} | ||
| if self.config.agent.claude.always_thinking is not None: | ||
| settings["alwaysThinkingEnabled"] = self.config.agent.claude.always_thinking | ||
| if self.config.agent.langfuse.enabled: | ||
| hook = {"hooks": [{"type": "command", "command": CLAUDE_LANGFUSE_HOOK_COMMAND}]} | ||
| settings["hooks"] = {"Stop": [hook], "SessionEnd": [hook]} | ||
| return settings | ||
|
|
||
| @staticmethod | ||
| def _list_native_session_files(home_dir: Path) -> list[Path]: | ||
| projects_dir = home_dir / "projects" | ||
|
|
@@ -3336,6 +3357,12 @@ def _base_url_env_items(self) -> list[tuple[str, str]]: | |
| ] | ||
|
|
||
| def _api_env_items(self) -> list[tuple[str, str]]: | ||
| token = self.config.get_claude_oauth_token() if self.config.claude_host_auth_active() else None | ||
| if token: | ||
| # Subscription auth: pass only the long-lived OAuth token, never an | ||
| # API key — ANTHROPIC_API_KEY silently takes precedence over | ||
| # subscription credentials inside Claude Code and would bill the API. | ||
| return [("CLAUDE_CODE_OAUTH_TOKEN", token)] | ||
| api_key = self.config.get_api_key() or ("none" if self.config.get_base_url() else "") | ||
| if not api_key: | ||
| return [] | ||
|
|
@@ -3398,6 +3425,11 @@ def _build_shell_command( | |
| permission_mode = self._permission_mode() | ||
| if permission_mode: | ||
| claude_command.extend(["--permission-mode", permission_mode]) | ||
| if self.config.model.reasoning_effort: | ||
| claude_command.extend(["--effort", self.config.model.reasoning_effort]) | ||
| fallback_model = self.config.get_claude_fallback_model() | ||
| if fallback_model: | ||
| claude_command.extend(["--fallback-model", fallback_model]) | ||
|
Comment on lines
+3428
to
+3432
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
These passthroughs are only appended by Useful? React with 👍 / 👎. |
||
| if self.config.developer_instructions: | ||
| claude_command.extend(["--append-system-prompt", self.config.developer_instructions]) | ||
| if resume_session_id: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agent.claude.oauth_tokenis returned verbatim here, unlike API keys and env token aliases that go through_normalize_api_key. If a config uses a placeholder such asoauth_token: none/dummywhile an API key is configured,claude_host_auth_active()treats that placeholder as a real subscription token and_api_env_items()then withholdsANTHROPIC_API_KEY, so Claude runs fail authentication; the same raw value also trips the base_url conflict validator. Please normalize the configured token before treating it as present.Useful? React with 👍 / 👎.