main
py 74 lines 2.22 KB
Raw
1 from __future__ import annotations
2
3 import json
4 import os
5 from pathlib import Path
6 from typing import Any
7
8 from plugins._orchestrator.helpers.adapters.base import TerminalAgentAdapter
9
10
11 _ENV_KEYS = {
12 "ANTHROPIC_API_KEY",
13 "DEEPSEEK_API_KEY",
14 "GEMINI_API_KEY",
15 "GH_TOKEN",
16 "GITHUB_TOKEN",
17 "GOOGLE_API_KEY",
18 "GROQ_API_KEY",
19 "OPENAI_API_KEY",
20 "OPENROUTER_API_KEY",
21 "XAI_API_KEY",
22 }
23
24 _SECRET_KEYS = {"access_token", "api_key", "refresh_token", "token"}
25
26
27 class OpenCodeAdapter(TerminalAgentAdapter):
28 id = "opencode"
29 title = "OpenCode"
30 binary = "opencode"
31 install_hint = "curl -fsSL https://opencode.ai/install | bash"
32 description = "OpenCode CLI in non-interactive run mode."
33
34 def auth_status(self, config: dict[str, Any] | None = None) -> dict[str, Any]:
35 env_var = next((name for name in sorted(_ENV_KEYS) if os.environ.get(name)), "")
36 if env_var:
37 return {"connected": True, "mode": "env", "auth_path": env_var}
38
39 path = _auth_path()
40 try:
41 if _auth_store_has_credentials(path):
42 return {"connected": True, "mode": "external", "auth_path": str(path)}
43 except OSError as exc:
44 return {"connected": False, "mode": "", "auth_path": "", "error": str(exc)}
45
46 return {"connected": False, "mode": "", "auth_path": str(path)}
47
48
49 def _auth_path() -> Path:
50 data_home = os.environ.get("XDG_DATA_HOME", "").strip()
51 root = Path(data_home).expanduser() if data_home else Path.home() / ".local" / "share"
52 return root / "opencode" / "auth.json"
53
54
55 def _auth_store_has_credentials(path: Path) -> bool:
56 if not path.is_file() or path.stat().st_size <= 0:
57 return False
58 try:
59 data = json.loads(path.read_text(encoding="utf-8"))
60 except ValueError:
61 return False
62 return _contains_secret(data)
63
64
65 def _contains_secret(value: Any) -> bool:
66 if isinstance(value, dict):
67 for key, item in value.items():
68 if str(key) in _SECRET_KEYS and isinstance(item, str) and item.strip():
69 return True
70 if _contains_secret(item):
71 return True
72 if isinstance(value, list):
73 return any(_contains_secret(item) for item in value)
74 return False