From 34a5c5d8ac939cb23818914a43a1ae03a8eeaf8b Mon Sep 17 00:00:00 2001 From: Abhishek Krishna Date: Sun, 26 Apr 2026 22:22:14 +0530 Subject: [PATCH] feat(types): widen SdkBeta to accept arbitrary anthropic-beta values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #845. `SdkBeta` was `Literal["context-1m-2025-08-07"]`, so any other beta flag was rejected by type checkers even though the runtime path (`subprocess_cli.py: cmd.extend(["--betas", ",".join(self._options.betas)])`) was already happy to forward arbitrary strings. That blocked callers from opting into header-only betas like `token-efficient-tools-2025-02-19`, which on tool-heavy agent loops materially reduces output tokens. Widen the alias to `Literal["context-1m-2025-08-07"] | str` — known values still autocomplete in editors, anything else passes through. This is purely additive: no existing usage breaks, no runtime behavior changes, and the `Literal` arm keeps documenting the value the SDK explicitly supports today. Update the `betas` docstring to reflect the relaxed contract and to point out `token-efficient-tools-2025-02-19` as a representative example. Add two `_build_command` regression tests in `tests/test_transport.py`: - `test_build_command_forwards_known_beta` — guards the existing literal value end-to-end. - `test_build_command_forwards_arbitrary_beta` — passes a known + unknown beta side-by-side and asserts they reach `--betas` in order, joined as the CLI expects. `+51 / -2`. `ruff check` and `ruff format --check` clean. --- src/claude_agent_sdk/types.py | 17 +++++++++++++++-- tests/test_transport.py | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/claude_agent_sdk/types.py b/src/claude_agent_sdk/types.py index b4860270..2eda4454 100644 --- a/src/claude_agent_sdk/types.py +++ b/src/claude_agent_sdk/types.py @@ -26,7 +26,12 @@ ] # SDK Beta features - see https://docs.anthropic.com/en/api/beta-headers -SdkBeta = Literal["context-1m-2025-08-07"] +# +# The known literal values surface in IDE autocomplete; the trailing ``str`` +# keeps the alias open so callers can opt into beta features that ship only +# as ``anthropic-beta`` header values (e.g. ``token-efficient-tools-2025-02-19``) +# without waiting on the SDK to enumerate them. +SdkBeta = Literal["context-1m-2025-08-07"] | str # Agent definitions SettingSource = Literal["user", "project", "local"] @@ -1543,10 +1548,18 @@ class ClaudeAgentOptions: betas: list[SdkBeta] = field(default_factory=list) """Enable beta features. - Currently supported: + Each entry is forwarded to the CLI via ``--betas`` and ultimately ends up + in the ``anthropic-beta`` request header. Known values surface in editor + autocomplete; arbitrary strings are also accepted so callers can opt into + new beta features without waiting on a SDK release. + + Currently surfaced as a known literal: - ``"context-1m-2025-08-07"`` — Enable 1M token context window (Sonnet 4/4.5 only). + Other beta header values that ship from the API (for example + ``"token-efficient-tools-2025-02-19"``) may be passed through directly. + See https://docs.anthropic.com/en/api/beta-headers. """ diff --git a/tests/test_transport.py b/tests/test_transport.py index efe0e2c9..8ff162d1 100644 --- a/tests/test_transport.py +++ b/tests/test_transport.py @@ -186,6 +186,42 @@ def test_build_command_with_dont_ask_permission_mode(self): assert "--permission-mode" in cmd assert "dontAsk" in cmd + def test_build_command_forwards_known_beta(self): + """Known SdkBeta literals reach ``--betas``.""" + transport = SubprocessCLITransport( + prompt="test", + options=make_options(betas=["context-1m-2025-08-07"]), + ) + + cmd = transport._build_command() + assert "--betas" in cmd + assert cmd[cmd.index("--betas") + 1] == "context-1m-2025-08-07" + + def test_build_command_forwards_arbitrary_beta(self): + """Arbitrary beta strings flow through unchanged. + + Regression for #845: ``SdkBeta`` was previously a closed + ``Literal["context-1m-2025-08-07"]`` so callers could not opt + into header-only betas like ``token-efficient-tools-2025-02-19`` + without bypassing the type. The alias was widened to also accept + ``str``; this guards the wire-level pass-through that users rely on. + """ + transport = SubprocessCLITransport( + prompt="test", + options=make_options( + betas=[ + "context-1m-2025-08-07", + "token-efficient-tools-2025-02-19", + ] + ), + ) + + cmd = transport._build_command() + assert "--betas" in cmd + assert cmd[cmd.index("--betas") + 1] == ( + "context-1m-2025-08-07,token-efficient-tools-2025-02-19" + ) + def test_build_command_with_fallback_model(self): """Test building CLI command with fallback_model option.""" transport = SubprocessCLITransport(