main
py 78 lines 2.64 KB
Raw
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 _API_KEY_ENV_VARS = ("GEMINI_API_KEY", "GOOGLE_API_KEY")
11
12
13 class GeminiCliAdapter(TerminalAgentAdapter):
14 id = "gemini"
15 title = "Gemini CLI"
16 binary = "gemini"
17 install_hint = "npm install -g @google/gemini-cli"
18 description = "Google Gemini CLI in headless single-prompt mode."
19
20 def _home(self) -> Path:
21 configured = os.environ.get("GEMINI_CLI_HOME", "").strip()
22 root = Path(configured).expanduser() if configured else Path.home()
23 return root / ".gemini"
24
25 def auth_status(self, config: dict[str, Any] | None = None) -> dict[str, Any]:
26 env_var = next((name for name in _API_KEY_ENV_VARS if os.environ.get(name)), "")
27 if env_var:
28 return {"connected": True, "mode": "env", "auth_path": env_var}
29
30 credentials = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", "").strip()
31 if credentials and _nonempty_file(Path(credentials).expanduser()):
32 return {
33 "connected": True,
34 "mode": "env",
35 "auth_path": "GOOGLE_APPLICATION_CREDENTIALS",
36 }
37
38 home = self._home()
39 for path in (home / "gemini-credentials.json", home / "oauth_creds.json"):
40 if _nonempty_file(path):
41 return {"connected": True, "mode": "external", "auth_path": str(path)}
42
43 if _env_file_has_key(home / ".env"):
44 return {"connected": True, "mode": "external", "auth_path": str(home / ".env")}
45
46 adc = _adc_path()
47 if _nonempty_file(adc):
48 return {"connected": True, "mode": "external", "auth_path": str(adc)}
49
50 return {"connected": False, "mode": "", "auth_path": str(home)}
51
52
53 def _adc_path() -> Path:
54 configured = os.environ.get("CLOUDSDK_CONFIG", "").strip()
55 root = Path(configured).expanduser() if configured else Path.home() / ".config" / "gcloud"
56 return root / "application_default_credentials.json"
57
58
59 def _nonempty_file(path: Path) -> bool:
60 try:
61 return path.is_file() and path.stat().st_size > 0
62 except OSError:
63 return False
64
65
66 def _env_file_has_key(path: Path) -> bool:
67 try:
68 lines = path.read_text(encoding="utf-8", errors="ignore").splitlines()
69 except OSError:
70 return False
71 for line in lines:
72 raw = line.strip()
73 if not raw or raw.startswith("#") or "=" not in raw:
74 continue
75 key, value = raw.split("=", 1)
76 if key.strip() in _API_KEY_ENV_VARS and value.strip().strip("'\""):
77 return True
78 return False