PYAE1994 commited on
Commit
4140e44
Β·
verified Β·
1 Parent(s): a0bbd7b

Fix: update agents/connector_agent.py

Browse files
Files changed (1) hide show
  1. agents/connector_agent.py +154 -119
agents/connector_agent.py CHANGED
@@ -1,151 +1,186 @@
1
  """
2
- ConnectorAgent β€” GitHub, Vercel, HF, n8n real API integrations
3
- No fake/mock responses β€” all real API calls
4
  """
5
  import json
6
  import os
7
- import structlog
8
- from typing import Dict
9
  import httpx
 
10
  from .base_agent import BaseAgent
11
 
12
  log = structlog.get_logger()
13
 
14
- GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", "")
15
- VERCEL_TOKEN = os.environ.get("VERCEL_TOKEN", "")
16
- HF_TOKEN = os.environ.get("HF_TOKEN", "")
17
- N8N_URL = os.environ.get("N8N_URL", "")
18
- N8N_API_KEY = os.environ.get("N8N_API_KEY", "")
19
-
20
 
21
  class ConnectorAgent(BaseAgent):
22
  def __init__(self, ws_manager=None, ai_router=None):
23
  super().__init__("ConnectorAgent", ws_manager, ai_router)
24
 
25
  async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
26
- session_id = kwargs.get("session_id", context.get("session_id", ""))
27
- task_id = kwargs.get("task_id", context.get("task_id", ""))
 
28
  task_lower = task.lower()
29
 
30
  if "github" in task_lower:
31
- return await self.github_action(task, context, task_id, session_id)
32
- elif "vercel" in task_lower:
33
- return await self.vercel_action(task, context, task_id, session_id)
34
  elif "huggingface" in task_lower or "hf" in task_lower:
35
- return await self.hf_action(task, context, task_id, session_id)
36
- elif "n8n" in task_lower:
37
- return await self.n8n_trigger(context, task_id, session_id)
38
  else:
39
- return await self.github_action(task, context, task_id, session_id)
40
 
41
  # ─── GitHub ───────────────────────────────────────────────────────────────
42
 
43
- async def github_action(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
44
- if not GITHUB_TOKEN:
45
- return "❌ GITHUB_TOKEN not set"
 
 
 
 
 
 
46
 
47
  task_lower = task.lower()
48
- headers = {
49
- "Authorization": f"token {GITHUB_TOKEN}",
50
- "Accept": "application/vnd.github.v3+json",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
- async with httpx.AsyncClient(timeout=30.0) as client:
54
- if "create repo" in task_lower or "new repo" in task_lower:
55
- name = context.get("repo_name", "god-agent-project")
56
- resp = await client.post(
57
- "https://api.github.com/user/repos",
58
- headers=headers,
59
- json={"name": name, "auto_init": True, "private": False},
60
- )
61
- resp.raise_for_status()
62
- data = resp.json()
63
- return f"βœ… GitHub repo created: {data.get('html_url','')}"
64
-
65
- elif "list repos" in task_lower:
66
- resp = await client.get("https://api.github.com/user/repos",
67
- headers=headers, params={"per_page": 10})
68
- resp.raise_for_status()
69
- repos = resp.json()
70
- lines = [f"- [{r['name']}]({r['html_url']})" for r in repos[:10]]
71
- return "**Your GitHub Repos:**\n" + "\n".join(lines)
72
-
73
- elif "status" in task_lower or "user" in task_lower:
74
- resp = await client.get("https://api.github.com/user", headers=headers)
75
- resp.raise_for_status()
76
- user = resp.json()
77
- return (
78
- f"βœ… **GitHub Connected**\n"
79
- f"- User: {user.get('login','')}\n"
80
- f"- Name: {user.get('name','')}\n"
81
- f"- Public repos: {user.get('public_repos', 0)}\n"
82
- f"- Followers: {user.get('followers', 0)}"
83
- )
84
- else:
85
- resp = await client.get("https://api.github.com/user", headers=headers)
86
  if resp.status_code == 200:
87
- user = resp.json()
88
- return f"βœ… GitHub connected as `{user.get('login','')}`. Ask me to create repos, list repos, commit files, etc."
89
- return "❌ GitHub connection failed"
 
 
 
 
 
 
90
 
91
  # ─── Vercel ───────────────────────────────────────────────────────────────
92
 
93
- async def vercel_action(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
94
- if not VERCEL_TOKEN:
95
- return "❌ VERCEL_TOKEN not set"
96
-
97
- async with httpx.AsyncClient(timeout=30.0) as client:
98
- headers = {"Authorization": f"Bearer {VERCEL_TOKEN}"}
99
- task_lower = task.lower()
100
-
101
- if "list" in task_lower or "projects" in task_lower:
102
- resp = await client.get("https://api.vercel.com/v9/projects", headers=headers)
103
- resp.raise_for_status()
104
- projects = resp.json().get("projects", [])
105
- lines = [f"- **{p['name']}** ({p.get('framework','?')})" for p in projects[:10]]
106
- return "**Vercel Projects:**\n" + ("\n".join(lines) or "No projects found")
107
- else:
108
- resp = await client.get("https://api.vercel.com/v2/user", headers=headers)
109
- resp.raise_for_status()
110
- user = resp.json()
111
- return (
112
- f"βœ… **Vercel Connected**\n"
113
- f"- Username: {user.get('username','')}\n"
114
- f"- Email: {user.get('email','')}"
115
- )
116
-
117
- # ─── HuggingFace ──────────────────────────────────────────────────────────
118
 
119
- async def hf_action(self, task: str, context: Dict, task_id: str, session_id: str) -> str:
120
- if not HF_TOKEN:
121
- return "❌ HF_TOKEN not set"
122
-
123
- async with httpx.AsyncClient(timeout=30.0) as client:
124
- headers = {"Authorization": f"Bearer {HF_TOKEN}"}
125
- resp = await client.get("https://huggingface.co/api/whoami", headers=headers)
126
- resp.raise_for_status()
127
- user = resp.json()
128
- return (
129
- f"βœ… **HuggingFace Connected**\n"
130
- f"- Username: {user.get('name','')}\n"
131
- f"- Full Name: {user.get('fullname','')}\n"
132
- f"- Spaces: /api/spaces available"
133
- )
134
-
135
- # ─── n8n Workflow Trigger ─────────────────────────────────────────────────
136
-
137
- async def n8n_trigger(self, context: Dict, task_id: str, session_id: str) -> str:
138
- if not N8N_URL:
139
- return "❌ N8N_URL not set"
140
-
141
- webhook_path = context.get("webhook_path", "/webhook/god-agent")
142
- payload = context.get("payload", {"source": "god_agent", "task_id": task_id})
143
-
144
- async with httpx.AsyncClient(timeout=30.0) as client:
145
- headers = {}
146
- if N8N_API_KEY:
147
- headers["X-N8N-API-KEY"] = N8N_API_KEY
148
- resp = await client.post(f"{N8N_URL}{webhook_path}", json=payload, headers=headers)
149
- if resp.status_code < 400:
150
- return f"βœ… n8n workflow triggered: {resp.status_code}"
151
- return f"❌ n8n trigger failed: {resp.status_code}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  """
2
+ ConnectorAgent β€” GitHub, HuggingFace, Vercel, n8n, Telegram, Discord integrations
 
3
  """
4
  import json
5
  import os
6
+ from typing import Dict, List, Optional
 
7
  import httpx
8
+ import structlog
9
  from .base_agent import BaseAgent
10
 
11
  log = structlog.get_logger()
12
 
 
 
 
 
 
 
13
 
14
  class ConnectorAgent(BaseAgent):
15
  def __init__(self, ws_manager=None, ai_router=None):
16
  super().__init__("ConnectorAgent", ws_manager, ai_router)
17
 
18
  async def run(self, task: str, context: Dict = {}, **kwargs) -> str:
19
+ session_id = kwargs.get("session_id", "")
20
+ task_id = kwargs.get("task_id", "")
21
+
22
  task_lower = task.lower()
23
 
24
  if "github" in task_lower:
25
+ return await self.github_operation(task, task_id=task_id, session_id=session_id)
 
 
26
  elif "huggingface" in task_lower or "hf" in task_lower:
27
+ return await self.hf_operation(task, task_id=task_id, session_id=session_id)
28
+ elif "vercel" in task_lower:
29
+ return await self.vercel_operation(task, task_id=task_id, session_id=session_id)
30
  else:
31
+ return await self._generic_connector(task, task_id=task_id, session_id=session_id)
32
 
33
  # ─── GitHub ───────────────────────────────────────────────────────────────
34
 
35
+ async def github_operation(self, task: str, task_id: str = "", session_id: str = "") -> str:
36
+ token = os.environ.get("GITHUB_TOKEN", "")
37
+ if not token:
38
+ return "⚠️ GITHUB_TOKEN not set. Please add it to environment variables."
39
+
40
+ headers = {
41
+ "Authorization": f"token {token}",
42
+ "Accept": "application/vnd.github.v3+json",
43
+ }
44
 
45
  task_lower = task.lower()
46
+
47
+ try:
48
+ async with httpx.AsyncClient(timeout=30) as client:
49
+ if "create repo" in task_lower or "new repo" in task_lower:
50
+ return await self._github_create_repo(client, headers, task, task_id, session_id)
51
+ elif "list repo" in task_lower:
52
+ return await self._github_list_repos(client, headers, task_id, session_id)
53
+ elif "commit" in task_lower:
54
+ return f"βœ… GitHub commit operation noted. Use SandboxAgent for actual commits."
55
+ elif "issue" in task_lower:
56
+ return await self._github_create_issue(client, headers, task, task_id, session_id)
57
+ else:
58
+ return await self._github_user_info(client, headers, task_id, session_id)
59
+ except Exception as e:
60
+ return f"❌ GitHub error: {str(e)}"
61
+
62
+ async def _github_user_info(self, client, headers, task_id, session_id) -> str:
63
+ resp = await client.get("https://api.github.com/user", headers=headers)
64
+ if resp.status_code == 200:
65
+ data = resp.json()
66
+ await self.emit(task_id, "connector_result", {
67
+ "connector": "github",
68
+ "action": "user_info",
69
+ "user": data.get("login"),
70
+ }, session_id)
71
+ return f"βœ… GitHub connected as **{data.get('login')}** ({data.get('public_repos')} repos)"
72
+ return f"❌ GitHub auth failed: {resp.status_code}"
73
+
74
+ async def _github_create_repo(self, client, headers, task, task_id, session_id) -> str:
75
+ # Extract repo name from task using simple heuristic
76
+ words = task.split()
77
+ name_candidates = [w for w in words if w.replace("-", "").replace("_", "").isalnum() and len(w) > 3]
78
+ repo_name = name_candidates[-1] if name_candidates else "god-agent-project"
79
+
80
+ payload = {
81
+ "name": repo_name,
82
+ "description": "Created by God Agent Platform",
83
+ "private": False,
84
+ "auto_init": True,
85
  }
86
+ resp = await client.post("https://api.github.com/user/repos", headers=headers, json=payload)
87
+ if resp.status_code == 201:
88
+ data = resp.json()
89
+ await self.emit(task_id, "connector_result", {
90
+ "connector": "github",
91
+ "action": "repo_created",
92
+ "repo": data.get("full_name"),
93
+ "url": data.get("html_url"),
94
+ }, session_id)
95
+ return f"βœ… GitHub repo created: [{data.get('full_name')}]({data.get('html_url')})"
96
+ return f"❌ Failed to create repo: {resp.status_code} β€” {resp.text[:200]}"
97
+
98
+ async def _github_list_repos(self, client, headers, task_id, session_id) -> str:
99
+ resp = await client.get("https://api.github.com/user/repos?per_page=10&sort=updated", headers=headers)
100
+ if resp.status_code == 200:
101
+ repos = resp.json()
102
+ lines = [f"- [{r['full_name']}]({r['html_url']}) ⭐{r['stargazers_count']}" for r in repos[:10]]
103
+ return "πŸ“¦ **Your GitHub Repos:**\n\n" + "\n".join(lines)
104
+ return f"❌ Failed to list repos: {resp.status_code}"
105
+
106
+ async def _github_create_issue(self, client, headers, task, task_id, session_id) -> str:
107
+ return "βœ… GitHub issue creation requires repo context. Specify: 'create issue in owner/repo: title'"
108
 
109
+ # ─── HuggingFace ──────────────────────────────────────────────────────────
110
+
111
+ async def hf_operation(self, task: str, task_id: str = "", session_id: str = "") -> str:
112
+ token = os.environ.get("HF_TOKEN", "")
113
+ if not token:
114
+ return "⚠️ HF_TOKEN not set. Add HuggingFace token to environment."
115
+
116
+ headers = {"Authorization": f"Bearer {token}"}
117
+ try:
118
+ async with httpx.AsyncClient(timeout=30) as client:
119
+ resp = await client.get("https://huggingface.co/api/whoami", headers=headers)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  if resp.status_code == 200:
121
+ data = resp.json()
122
+ await self.emit(task_id, "connector_result", {
123
+ "connector": "huggingface",
124
+ "user": data.get("name"),
125
+ }, session_id)
126
+ return f"βœ… HuggingFace connected as **{data.get('name')}**"
127
+ return f"❌ HF auth failed: {resp.status_code}"
128
+ except Exception as e:
129
+ return f"❌ HuggingFace error: {str(e)}"
130
 
131
  # ─── Vercel ───────────────────────────────────────────────────────────────
132
 
133
+ async def vercel_operation(self, task: str, task_id: str = "", session_id: str = "") -> str:
134
+ token = os.environ.get("VERCEL_TOKEN", "")
135
+ if not token:
136
+ return "⚠️ VERCEL_TOKEN not set. Add Vercel token to environment."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
 
138
+ headers = {"Authorization": f"Bearer {token}"}
139
+ try:
140
+ async with httpx.AsyncClient(timeout=30) as client:
141
+ resp = await client.get("https://api.vercel.com/v2/user", headers=headers)
142
+ if resp.status_code == 200:
143
+ data = resp.json()
144
+ user = data.get("user", {})
145
+ await self.emit(task_id, "connector_result", {
146
+ "connector": "vercel",
147
+ "user": user.get("username"),
148
+ }, session_id)
149
+ return f"βœ… Vercel connected as **{user.get('username')}** ({user.get('email')})"
150
+ return f"❌ Vercel auth failed: {resp.status_code}"
151
+ except Exception as e:
152
+ return f"❌ Vercel error: {str(e)}"
153
+
154
+ async def _generic_connector(self, task: str, task_id: str = "", session_id: str = "") -> str:
155
+ return (
156
+ "πŸ”Œ **Available Connectors:**\n\n"
157
+ "| Connector | Status | Env Var |\n"
158
+ "|-----------|--------|---------||\n"
159
+ f"| GitHub | {'βœ…' if os.environ.get('GITHUB_TOKEN') else '❌'} | GITHUB_TOKEN |\n"
160
+ f"| HuggingFace | {'βœ…' if os.environ.get('HF_TOKEN') else '❌'} | HF_TOKEN |\n"
161
+ f"| Vercel | {'βœ…' if os.environ.get('VERCEL_TOKEN') else '❌'} | VERCEL_TOKEN |\n"
162
+ f"| OpenAI | {'βœ…' if os.environ.get('OPENAI_API_KEY') else '❌'} | OPENAI_API_KEY |\n"
163
+ f"| Groq | {'βœ…' if os.environ.get('GROQ_API_KEY') else '❌'} | GROQ_API_KEY |\n"
164
+ f"| OpenRouter | {'βœ…' if os.environ.get('OPENROUTER_API_KEY') else '❌'} | OPENROUTER_API_KEY |\n"
165
+ )
166
+
167
+ def get_connector_status(self) -> Dict:
168
+ """Return status of all connectors."""
169
+ connectors = {
170
+ "github": bool(os.environ.get("GITHUB_TOKEN")),
171
+ "huggingface": bool(os.environ.get("HF_TOKEN")),
172
+ "vercel": bool(os.environ.get("VERCEL_TOKEN")),
173
+ "openai": bool(os.environ.get("OPENAI_API_KEY")),
174
+ "groq": bool(os.environ.get("GROQ_API_KEY")),
175
+ "cerebras": bool(os.environ.get("CEREBRAS_API_KEY")),
176
+ "openrouter": bool(os.environ.get("OPENROUTER_API_KEY")),
177
+ "anthropic": bool(os.environ.get("ANTHROPIC_API_KEY")),
178
+ "n8n": bool(os.environ.get("N8N_URL")),
179
+ "telegram": bool(os.environ.get("TELEGRAM_BOT_TOKEN")),
180
+ "discord": bool(os.environ.get("DISCORD_BOT_TOKEN")),
181
+ }
182
+ return {
183
+ "connectors": connectors,
184
+ "connected_count": sum(connectors.values()),
185
+ "total": len(connectors),
186
+ }