feat: task lane persistence + sidebar cleanup #121

Merged
chihlasm merged 49 commits from feat/task-lane-persistence into main 2026-03-29 16:59:41 +00:00
Showing only changes of commit c6772c6607 - Show all commits

View File

@@ -165,6 +165,24 @@ class GeminiProvider(AIProvider):
return text, input_tokens, output_tokens
# Singleton client cache — avoids creating new HTTP connections per call
_anthropic_clients: dict[str, "anthropic.AsyncAnthropic"] = {}
def _get_anthropic_client(api_key: str, timeout: int = 45) -> "anthropic.AsyncAnthropic":
"""Return a cached AsyncAnthropic client, creating one if needed."""
import anthropic
cache_key = f"{api_key[:8]}:{timeout}"
if cache_key not in _anthropic_clients:
_anthropic_clients[cache_key] = anthropic.AsyncAnthropic(
api_key=api_key,
timeout=timeout,
max_retries=1,
)
return _anthropic_clients[cache_key]
class AnthropicProvider(AIProvider):
"""Anthropic Claude provider using the anthropic SDK."""
@@ -179,13 +197,7 @@ class AnthropicProvider(AIProvider):
messages: list[dict[str, str]],
max_tokens: int = 4096,
) -> tuple[str, int, int]:
import anthropic
client = anthropic.AsyncAnthropic(
api_key=self._api_key,
timeout=self._timeout,
max_retries=1,
)
client = _get_anthropic_client(self._api_key, self._timeout)
response = await client.messages.create(
model=self._model,