diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 761918a311..04f4c03ca9 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -116,8 +116,10 @@ const openHandsHandlers = [ "anthropic/claude-3.5", "anthropic/claude-sonnet-4-20250514", "anthropic/claude-sonnet-4-5-20250929", + "anthropic/claude-haiku-4-5-20251001", "openhands/claude-sonnet-4-20250514", "openhands/claude-sonnet-4-5-20250929", + "openhands/claude-haiku-4-5-20251001", "sambanova/Meta-Llama-3.1-8B-Instruct", ]), ), diff --git a/frontend/src/utils/verified-models.ts b/frontend/src/utils/verified-models.ts index 173619cb33..12453c6c86 100644 --- a/frontend/src/utils/verified-models.ts +++ b/frontend/src/utils/verified-models.ts @@ -16,6 +16,7 @@ export const VERIFIED_MODELS = [ "claude-3-7-sonnet-20250219", "claude-sonnet-4-20250514", "claude-sonnet-4-5-20250929", + "claude-haiku-4-5-20251001", "claude-opus-4-20250514", "claude-opus-4-1-20250805", "gemini-2.5-pro", @@ -55,6 +56,7 @@ export const VERIFIED_ANTHROPIC_MODELS = [ "claude-3-7-sonnet-20250219", "claude-sonnet-4-20250514", "claude-sonnet-4-5-20250929", + "claude-haiku-4-5-20251001", "claude-opus-4-20250514", "claude-opus-4-1-20250805", ]; @@ -72,6 +74,7 @@ export const VERIFIED_MISTRAL_MODELS = [ export const VERIFIED_OPENHANDS_MODELS = [ "claude-sonnet-4-20250514", "claude-sonnet-4-5-20250929", + "claude-haiku-4-5-20251001", "gpt-5-2025-08-07", "gpt-5-mini-2025-08-07", "claude-opus-4-20250514", diff --git a/openhands-cli/pyproject.toml b/openhands-cli/pyproject.toml index 421903007a..59635e31e7 100644 --- a/openhands-cli/pyproject.toml +++ b/openhands-cli/pyproject.toml @@ -100,5 +100,5 @@ disallow_untyped_defs = true ignore_missing_imports = true [tool.uv.sources] -openhands-sdk = { git = "https://github.com/All-Hands-AI/agent-sdk.git", subdirectory = "openhands/sdk", rev = "50b094a92817e448ec4352d2950df4f19edd5a9f" } -openhands-tools = { git = "https://github.com/All-Hands-AI/agent-sdk.git", subdirectory = "openhands/tools", rev = "50b094a92817e448ec4352d2950df4f19edd5a9f" } +openhands-sdk = { git = "https://github.com/All-Hands-AI/agent-sdk.git", subdirectory = "openhands/sdk", rev = "4ffaa97a9a438b913b73696e192b5575419407bc" } +openhands-tools = { git = "https://github.com/All-Hands-AI/agent-sdk.git", subdirectory = "openhands/tools", rev = "4ffaa97a9a438b913b73696e192b5575419407bc" } diff --git a/openhands-cli/uv.lock b/openhands-cli/uv.lock index 75fd133eb0..3c03f9dc41 100644 --- a/openhands-cli/uv.lock +++ b/openhands-cli/uv.lock @@ -1281,7 +1281,7 @@ wheels = [ [[package]] name = "litellm" version = "1.77.7" -source = { git = "https://github.com/BerriAI/litellm.git?rev=v1.77.7.dev9#763d2f8ccdd8412dbe6d4ac0e136d9ac34dcd4c0" } +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, { name = "click" }, @@ -1296,6 +1296,10 @@ dependencies = [ { name = "tiktoken" }, { name = "tokenizers" }, ] +sdist = { url = "https://files.pythonhosted.org/packages/5a/4b/4e9a204462687ca3796cc0fdaefbd624d7b2216edd4ad243d60a3b95127e/litellm-1.77.7.tar.gz", hash = "sha256:e3398fb2575b98726e787c0a1481daed5938d58cafdcd96fbca80c312221af3e", size = 10401706, upload-time = "2025-10-05T00:22:37.646Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/50/53df2244d4aca2af73d2f2c6ad21c731cf24bd0dbe89d896184a1eaa874f/litellm-1.77.7-py3-none-any.whl", hash = "sha256:1b3a1b17bd521a0ad25226fb62a912602c803922aabb4a16adf83834673be574", size = 9223061, upload-time = "2025-10-05T00:22:34.112Z" }, +] [[package]] name = "macholib" @@ -1652,8 +1656,8 @@ dev = [ [package.metadata] requires-dist = [ - { name = "openhands-sdk", git = "https://github.com/All-Hands-AI/agent-sdk.git?subdirectory=openhands%2Fsdk&rev=50b094a92817e448ec4352d2950df4f19edd5a9f" }, - { name = "openhands-tools", git = "https://github.com/All-Hands-AI/agent-sdk.git?subdirectory=openhands%2Ftools&rev=50b094a92817e448ec4352d2950df4f19edd5a9f" }, + { name = "openhands-sdk", git = "https://github.com/All-Hands-AI/agent-sdk.git?subdirectory=openhands%2Fsdk&rev=4ffaa97a9a438b913b73696e192b5575419407bc" }, + { name = "openhands-tools", git = "https://github.com/All-Hands-AI/agent-sdk.git?subdirectory=openhands%2Ftools&rev=4ffaa97a9a438b913b73696e192b5575419407bc" }, { name = "prompt-toolkit", specifier = ">=3" }, { name = "typer", specifier = ">=0.17.4" }, ] @@ -1676,8 +1680,8 @@ dev = [ [[package]] name = "openhands-sdk" -version = "1.0.0" -source = { git = "https://github.com/All-Hands-AI/agent-sdk.git?subdirectory=openhands%2Fsdk&rev=50b094a92817e448ec4352d2950df4f19edd5a9f#50b094a92817e448ec4352d2950df4f19edd5a9f" } +version = "1.0.0a1" +source = { git = "https://github.com/All-Hands-AI/agent-sdk.git?subdirectory=openhands%2Fsdk&rev=4ffaa97a9a438b913b73696e192b5575419407bc#4ffaa97a9a438b913b73696e192b5575419407bc" } dependencies = [ { name = "fastmcp" }, { name = "httpx" }, @@ -1691,8 +1695,8 @@ dependencies = [ [[package]] name = "openhands-tools" -version = "1.0.0" -source = { git = "https://github.com/All-Hands-AI/agent-sdk.git?subdirectory=openhands%2Ftools&rev=50b094a92817e448ec4352d2950df4f19edd5a9f#50b094a92817e448ec4352d2950df4f19edd5a9f" } +version = "1.0.0a1" +source = { git = "https://github.com/All-Hands-AI/agent-sdk.git?subdirectory=openhands%2Ftools&rev=4ffaa97a9a438b913b73696e192b5575419407bc#4ffaa97a9a438b913b73696e192b5575419407bc" } dependencies = [ { name = "bashlex" }, { name = "binaryornot" }, diff --git a/openhands/cli/utils.py b/openhands/cli/utils.py index f61cfb1298..ac9175d625 100644 --- a/openhands/cli/utils.py +++ b/openhands/cli/utils.py @@ -166,6 +166,7 @@ VERIFIED_OPENAI_MODELS = [ VERIFIED_ANTHROPIC_MODELS = [ 'claude-sonnet-4-20250514', 'claude-sonnet-4-5-20250929', + 'claude-haiku-4-5-20251001', 'claude-opus-4-20250514', 'claude-opus-4-1-20250805', 'claude-3-7-sonnet-20250219', @@ -188,6 +189,7 @@ VERIFIED_MISTRAL_MODELS = [ VERIFIED_OPENHANDS_MODELS = [ 'claude-sonnet-4-20250514', 'claude-sonnet-4-5-20250929', + 'claude-haiku-4-5-20251001', 'gpt-5-2025-08-07', 'gpt-5-mini-2025-08-07', 'claude-opus-4-20250514', diff --git a/openhands/llm/llm.py b/openhands/llm/llm.py index e85cf82d12..9589ec94e3 100644 --- a/openhands/llm/llm.py +++ b/openhands/llm/llm.py @@ -148,10 +148,12 @@ class LLM(RetryMixin, DebugMixin): logger.debug( f'Gemini model {self.config.model} with reasoning_effort {self.config.reasoning_effort} mapped to thinking {kwargs.get("thinking")}' ) - elif 'claude-sonnet-4-5' in self.config.model: - kwargs.pop( - 'reasoning_effort', None - ) # don't send reasoning_effort to Claude Sonnet 4.5 + elif any( + k in self.config.model + for k in ('claude-sonnet-4-5', 'claude-haiku-4-5-20251001') + ): + # don't send reasoning_effort to specific Claude Sonnet/Haiku 4.5 variants + kwargs.pop('reasoning_effort', None) else: kwargs['reasoning_effort'] = self.config.reasoning_effort kwargs.pop( @@ -511,6 +513,7 @@ class LLM(RetryMixin, DebugMixin): 'claude-3.7-sonnet', 'claude-sonnet-4', 'claude-sonnet-4-5-20250929', + 'claude-haiku-4-5-20251001', ] if any(model in self.config.model for model in sonnet_models): self.config.max_output_tokens = 64000 # litellm set max to 128k, but that requires a header to be set @@ -819,9 +822,14 @@ class LLM(RetryMixin, DebugMixin): message.force_string_serializer = True if 'kimi-k2-instruct' in self.config.model and 'groq' in self.config.model: message.force_string_serializer = True - if 'openrouter/anthropic/claude-sonnet-4' in self.config.model: - message.force_string_serializer = True - if 'openrouter/anthropic/claude-sonnet-4-5-20250929' in self.config.model: + if any( + k in self.config.model + for k in ( + 'openrouter/anthropic/claude-sonnet-4', + 'openrouter/anthropic/claude-sonnet-4-5-20250929', + 'openrouter/anthropic/claude-haiku-4-5-20251001', + ) + ): message.force_string_serializer = True # let pydantic handle the serialization diff --git a/openhands/llm/model_features.py b/openhands/llm/model_features.py index 0265701237..954cee00fd 100644 --- a/openhands/llm/model_features.py +++ b/openhands/llm/model_features.py @@ -104,6 +104,7 @@ REASONING_EFFORT_PATTERNS: list[str] = [ # DeepSeek reasoning family 'deepseek-r1-0528*', 'claude-sonnet-4-5*', + 'claude-haiku-4-5*', ] PROMPT_CACHE_PATTERNS: list[str] = [