mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-13 14:16:21 +00:00
fix: do not load the anthropic package on import
`serena.analytics` imported `anthropic.types` at module level for two type annotations, so every `import serena.cli` / `import serena.agent` paid for loading the whole anthropic package (2-4 s on the reporter's Windows machine) even with the default CHAR_COUNT token estimator. That delay can push MCP startup past a client's initial tool-discovery window. The import now lives behind `TYPE_CHECKING`; `AnthropicTokenCount` already imported `anthropic` lazily in `__init__`, and the request body is a plain dict (what `MessageParam` produces at runtime anyway). Tests: importing serena.cli / serena.agent / serena.analytics in a fresh interpreter leaves `anthropic` out of `sys.modules`; the Anthropic estimator still sends the expected count_tokens request. Fixes #2012
This commit is contained in:
1 parent
922cac9da4
commit
16322651bb
3 files changed
+38
-2
No files matched your search
@@ -13,6 +13,8 @@ Status of the `main` branch. Changes prior to the next official version change w
|
||||
|
||||
* General:
|
||||
- Fix: MCP `initialize` now reports Serena's version instead of the installed mcp SDK version (#1889)
|
||||
- Fix: importing Serena no longer loads the `anthropic` package unless the Anthropic token counter is
|
||||
actually used; the unconditional import added seconds to CLI/MCP startup on some machines (#2012)
|
||||
- Fix: Parallel agents auto-registering projects could overwrite each other's changes to the global
|
||||
project list in `serena_config.yml`
|
||||
- Fix: `TextUtils.insert_text_at_position` returned a wrong position when the inserted text merged
|
||||
|
||||
@@ -9,10 +9,15 @@ from collections import defaultdict
|
||||
from copy import copy
|
||||
from dataclasses import asdict, dataclass
|
||||
from enum import Enum
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from anthropic.types import MessageParam, MessageTokensCount
|
||||
from dotenv import load_dotenv
|
||||
|
||||
if TYPE_CHECKING:
|
||||
# Imported for annotations only: loading the anthropic package costs seconds on some
|
||||
# machines (see #2012) and is only needed when the Anthropic token counter is used.
|
||||
from anthropic.types import MessageTokensCount
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -64,7 +69,7 @@ class AnthropicTokenCount(TokenCountEstimator):
|
||||
def _send_count_tokens_request(self, text: str) -> MessageTokensCount:
|
||||
return self._anthropic_client.messages.count_tokens(
|
||||
model=self._model_name,
|
||||
messages=[MessageParam(role="user", content=text)],
|
||||
messages=[{"role": "user", "content": text}],
|
||||
)
|
||||
|
||||
def estimate_token_count(self, text: str) -> int:
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
"""The anthropic package must only be loaded when the Anthropic token counter is used (#2012)."""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from serena.analytics import AnthropicTokenCount
|
||||
|
||||
|
||||
@pytest.mark.parametrize("module", ["serena.cli", "serena.agent", "serena.analytics"])
|
||||
def test_importing_serena_does_not_load_anthropic(module: str) -> None:
|
||||
code = f"import sys, {module}; print('anthropic' in sys.modules)"
|
||||
result = subprocess.run([sys.executable, "-c", code], capture_output=True, text=True, check=True, timeout=120)
|
||||
assert result.stdout.strip() == "False", f"importing {module} loaded the anthropic package"
|
||||
|
||||
|
||||
def test_anthropic_token_count_sends_a_plain_user_message() -> None:
|
||||
estimator = AnthropicTokenCount.__new__(AnthropicTokenCount)
|
||||
estimator._model_name = "claude-sonnet-4-20250514"
|
||||
estimator._anthropic_client = MagicMock()
|
||||
estimator._anthropic_client.messages.count_tokens.return_value = MagicMock(input_tokens=7)
|
||||
|
||||
assert estimator.estimate_token_count("hello") == 7
|
||||
estimator._anthropic_client.messages.count_tokens.assert_called_once_with(
|
||||
model="claude-sonnet-4-20250514",
|
||||
messages=[{"role": "user", "content": "hello"}],
|
||||
)
|
||||
Reference in new issue
Block a user