| 1 | from __future__ import annotations |
| 2 | |
| 3 | import os |
| 4 | from pathlib import Path |
| 5 | from typing import Any |
| 6 | |
| 7 | from plugins._orchestrator.helpers.adapters.base import TerminalAgentAdapter |
| 8 | |
| 9 | |
| 10 | class ClaudeCodeAdapter(TerminalAgentAdapter): |
| 11 | id = "claude" |
| 12 | title = "Claude Code" |
| 13 | binary = "claude" |
| 14 | install_hint = "npm install -g @anthropic-ai/claude-code" |
| 15 | description = "Anthropic Claude Code CLI in non-interactive print mode." |
| 16 | |
| 17 | def _credentials_path(self) -> Path: |
| 18 | config_dir = os.environ.get("CLAUDE_CONFIG_DIR", "").strip() |
| 19 | root = Path(config_dir).expanduser() if config_dir else Path.home() / ".claude" |
| 20 | return root / ".credentials.json" |
| 21 | |
| 22 | def auth_status(self, config: dict[str, Any] | None = None) -> dict[str, Any]: |
| 23 | if os.environ.get("ANTHROPIC_API_KEY"): |
| 24 | return { |
| 25 | "connected": True, |
| 26 | "mode": "env", |
| 27 | "auth_path": "ANTHROPIC_API_KEY", |
| 28 | } |
| 29 | credentials = self._credentials_path() |
| 30 | try: |
| 31 | if credentials.is_file() and credentials.stat().st_size > 0: |
| 32 | return { |
| 33 | "connected": True, |
| 34 | "mode": "external", |
| 35 | "auth_path": str(credentials), |
| 36 | } |
| 37 | except OSError as exc: |
| 38 | return { |
| 39 | "connected": False, |
| 40 | "mode": "", |
| 41 | "auth_path": "", |
| 42 | "error": str(exc), |
| 43 | } |
| 44 | if not self.is_installed(config): |
| 45 | return {"connected": False, "mode": "", "auth_path": ""} |
| 46 | return {"connected": False, "mode": "", "auth_path": ""} |
| 47 | |
| 48 | def can_disconnect(self, config: dict[str, Any] | None = None) -> bool: |
| 49 | return not os.environ.get("ANTHROPIC_API_KEY") and self._credentials_path().is_file() |
| 50 | |
| 51 | def disconnect(self, config: dict[str, Any] | None = None) -> dict[str, Any]: |
| 52 | if os.environ.get("ANTHROPIC_API_KEY"): |
| 53 | return { |
| 54 | "removed": False, |
| 55 | "message": "ANTHROPIC_API_KEY is set in the environment.", |
| 56 | } |
| 57 | path = self._credentials_path() |
| 58 | if path.exists(): |
| 59 | path.unlink() |
| 60 | return {"removed": True, "mode": "external"} |
| 61 | return {"removed": False, "message": "No Claude Code credentials found."} |