ApolloAIs commited on
Commit
bb0b94a
·
verified ·
1 Parent(s): 9be6b43

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +39 -107
main.py CHANGED
@@ -1,138 +1,70 @@
1
  import os
2
- import json
3
- from fastapi import FastAPI, Request
4
- from fastapi.staticfiles import StaticFiles
5
  import uvicorn
6
- from playwright.async_api import async_playwright
7
  from litellm import acompletion
8
 
9
  # --- CONFIG ---
10
  os.environ["GEMINI_API_KEY"] = os.getenv("GEMINI_API_KEY", "")
11
- SPACE_HOST = os.getenv("MY_SPACE_HOST", "")
12
- STATIC_DIR = "static"
13
 
14
  app = FastAPI()
15
 
16
- if not os.path.exists(STATIC_DIR):
17
- os.makedirs(STATIC_DIR)
18
-
19
- app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
20
-
21
- # --- TOOLS ---
22
- async def take_screenshot(url: str) -> str:
23
- """Navigates to a URL and takes a screenshot. Returns the URL to view it."""
24
- filepath = f"{STATIC_DIR}/screenshot.png"
25
- async with async_playwright() as p:
26
- browser = await p.chromium.launch(headless=True)
27
- page = await browser.new_page()
28
- await page.goto(url)
29
- await page.screenshot(path=filepath, full_page=True)
30
- await browser.close()
31
-
32
- return f"Screenshot successful. View it here: https://{SPACE_HOST}/static/screenshot.png"
33
-
34
- tools = [
35
- {
36
- "type": "function",
37
- "function": {
38
- "name": "take_screenshot",
39
- "description": "Takes a screenshot of a URL.",
40
- "parameters": {
41
- "type": "object",
42
- "properties": {
43
- "url": {"type": "string", "description": "The URL to screenshot"}
44
- },
45
- "required": ["url"]
46
- }
47
- }
48
- }
49
- ]
50
-
51
  system_prompt = (
52
- "You are an expert coding/devops agent. Users interact via a WhatsApp bridge. "
53
- "Keep replies concise and under 1000 chars. Explain before acting. "
54
- "If you take a screenshot, provide the URL clearly."
55
  )
56
 
57
  # --- NATIVE AGENT ENGINE ---
58
  async def run_agent(prompt: str) -> str:
59
- messages = [
60
- {"role": "system", "content": system_prompt},
61
- {"role": "user", "content": prompt}
62
- ]
63
-
64
  try:
65
  response = await acompletion(
66
  model="gemini/gemini-2.5-pro",
67
- messages=messages,
68
- tools=tools,
 
 
69
  temperature=0.2
70
  )
71
-
72
- msg = response.choices[0].message
73
-
74
- # Check if the LLM wants to use the screenshot tool
75
- if hasattr(msg, 'tool_calls') and msg.tool_calls:
76
- assistant_msg = {"role": "assistant", "content": msg.content or ""}
77
- assistant_msg["tool_calls"] = [
78
- {
79
- "id": tc.id,
80
- "type": "function",
81
- "function": {
82
- "name": tc.function.name,
83
- "arguments": tc.function.arguments
84
- }
85
- } for tc in msg.tool_calls
86
- ]
87
- messages.append(assistant_msg)
88
-
89
- # Execute the tool
90
- for tool_call in msg.tool_calls:
91
- if tool_call.function.name == "take_screenshot":
92
- args = json.loads(tool_call.function.arguments)
93
- result = await take_screenshot(args["url"])
94
-
95
- messages.append({
96
- "role": "tool",
97
- "tool_call_id": tool_call.id,
98
- "name": "take_screenshot",
99
- "content": result
100
- })
101
-
102
- # Get the final answer after the screenshot
103
- final_response = await acompletion(
104
- model="gemini/gemini-2.5-pro",
105
- messages=messages,
106
- temperature=0.2
107
- )
108
- return final_response.choices[0].message.content
109
-
110
- return msg.content or "No response generated."
111
  except Exception as e:
112
  return f"Agent Error: {str(e)}"
113
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  # --- ENDPOINTS ---
115
  @app.get("/health")
116
  async def health_check():
117
  return {"status": "alive"}
118
 
119
- @app.api_route("/webhook", methods=["GET", "POST"])
120
- async def wa_webhook(request: Request):
121
- user_msg = request.query_params.get("message", "")
122
 
123
- if request.method == "POST":
124
- try:
125
- data = await request.json()
126
- user_msg = data.get("message", user_msg)
127
- except:
128
- pass
129
-
130
- if user_msg.lower().startswith("claw "):
131
- prompt = user_msg[5:].strip()
132
- response_text = await run_agent(prompt)
133
- return {"replies": [{"message": response_text}]}
134
-
135
- return {"replies": []}
136
 
137
  if __name__ == "__main__":
138
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
1
  import os
2
+ import httpx
3
+ from fastapi import FastAPI, Request, BackgroundTasks
 
4
  import uvicorn
 
5
  from litellm import acompletion
6
 
7
  # --- CONFIG ---
8
  os.environ["GEMINI_API_KEY"] = os.getenv("GEMINI_API_KEY", "")
9
+ TELEGRAM_TOKEN = os.getenv("TELEGRAM_TOKEN", "")
10
+ TELEGRAM_API_URL = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}"
11
 
12
  app = FastAPI()
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  system_prompt = (
15
+ "You are an expert coding/devops agent. "
16
+ "Keep replies concise and under 1000 chars. Use Markdown formatting."
 
17
  )
18
 
19
  # --- NATIVE AGENT ENGINE ---
20
  async def run_agent(prompt: str) -> str:
 
 
 
 
 
21
  try:
22
  response = await acompletion(
23
  model="gemini/gemini-2.5-pro",
24
+ messages=[
25
+ {"role": "system", "content": system_prompt},
26
+ {"role": "user", "content": prompt}
27
+ ],
28
  temperature=0.2
29
  )
30
+ return response.choices[0].message.content or "No response generated."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  except Exception as e:
32
  return f"Agent Error: {str(e)}"
33
 
34
+ # --- BACKGROUND TASK: PROCESS AND REPLY ---
35
+ async def process_and_reply(chat_id: int, text: str):
36
+ response_text = await run_agent(text)
37
+
38
+ # Send the final response back to Telegram
39
+ async with httpx.AsyncClient() as client:
40
+ await client.post(
41
+ f"{TELEGRAM_API_URL}/sendMessage",
42
+ json={
43
+ "chat_id": chat_id,
44
+ "text": response_text,
45
+ "parse_mode": "Markdown"
46
+ }
47
+ )
48
+
49
  # --- ENDPOINTS ---
50
  @app.get("/health")
51
  async def health_check():
52
  return {"status": "alive"}
53
 
54
+ @app.post("/webhook")
55
+ async def telegram_webhook(request: Request, background_tasks: BackgroundTasks):
56
+ data = await request.json()
57
 
58
+ # Extract the message from Telegram's JSON payload
59
+ if "message" in data and "text" in data["message"]:
60
+ chat_id = data["message"]["chat"]["id"]
61
+ user_msg = data["message"]["text"]
62
+
63
+ # Run the AI generation in the background so we can instantly reply "OK" to Telegram
64
+ background_tasks.add_task(process_and_reply, chat_id, user_msg)
65
+
66
+ # Telegram requires an immediate 200 OK so it doesn't get stuck in a retry loop
67
+ return {"status": "ok"}
 
 
 
68
 
69
  if __name__ == "__main__":
70
  uvicorn.run(app, host="0.0.0.0", port=7860)