Yuvan666 commited on
Commit
4ed4526
·
0 Parent(s):

fix: Add dotenv, robust API key loading, and v2.0 Info-Driven Architecture

Browse files
Files changed (3) hide show
  1. order_agent_worker.py +219 -0
  2. order_worker_info.py +41 -0
  3. requirements.txt +10 -0
order_agent_worker.py ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ALTYZEN Order Validation Worker
3
+ """
4
+
5
+ import os
6
+ import json
7
+ import time
8
+ import asyncio
9
+ import logging
10
+ import httpx
11
+ from typing import Dict, Any, Optional
12
+
13
+ from order_worker_info import IDENTITY, MISSION, NATURE, RESOURCES, CONFLICT_PROTOCOL
14
+
15
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
16
+ logger = logging.getLogger(__name__)
17
+
18
+ from dotenv import load_dotenv, find_dotenv
19
+ # Try loading from standard .env
20
+ load_dotenv()
21
+ # Also try loading from specific integration file if main fails
22
+ load_dotenv(r"c:\Users\Administrator\3D Objects\ALTYZEN\env.agi.integration")
23
+
24
+ # Validate API Key immediately
25
+ api_key = os.getenv("OPENROUTER_API_KEY")
26
+ if not api_key:
27
+ logger.critical("❌ CRITICAL: OPENROUTER_API_KEY NOT FOUND in environment! LLM calls will fail.")
28
+ else:
29
+ logger.info(f"✅ API Key found: {api_key[:5]}...{api_key[-4:]}")
30
+
31
+ MODELS = {
32
+ "brain": "tngtech/deepseek-r1t-chimera:free",
33
+ "eyes": "qwen/qwen-2.5-vl-7b-instruct:free",
34
+ "hands": "kwaipilot/kat-coder-pro:free",
35
+ "guard": "deepseek/deepseek-r1-0528:free",
36
+ }
37
+
38
+ OPENROUTER_URL = "https://openrouter.ai/api/v1/chat/completions"
39
+
40
+ SYSTEM_PROMPT = f"""
41
+ {IDENTITY}
42
+
43
+ MISSION:
44
+ {MISSION}
45
+
46
+ NATURE:
47
+ {NATURE}
48
+
49
+ RESOURCES:
50
+ {RESOURCES}
51
+
52
+ CONFLICT PROTOCOL:
53
+ {CONFLICT_PROTOCOL}
54
+ """
55
+
56
+
57
+ class AgentOrgans:
58
+ def __init__(self, api_key: str):
59
+ self.api_key = api_key
60
+ self.page = None
61
+ self.browser = None
62
+ self.context = None
63
+
64
+ async def call_llm(self, organ: str, prompt: str) -> str:
65
+ model = MODELS.get(organ, MODELS["guard"])
66
+
67
+ headers = {
68
+ "Authorization": f"Bearer {self.api_key}",
69
+ "Content-Type": "application/json",
70
+ "HTTP-Referer": "https://altyzen.com",
71
+ "X-Title": f"Altyzen-Worker-{organ.upper()}"
72
+ }
73
+
74
+ payload = {
75
+ "model": model,
76
+ "messages": [
77
+ {"role": "system", "content": SYSTEM_PROMPT},
78
+ {"role": "user", "content": prompt}
79
+ ],
80
+ "temperature": 0.1,
81
+ "max_tokens": 2000
82
+ }
83
+
84
+ try:
85
+ async with httpx.AsyncClient(timeout=60.0) as client:
86
+ resp = await client.post(OPENROUTER_URL, json=payload, headers=headers)
87
+ if resp.status_code == 200:
88
+ return resp.json()["choices"][0]["message"]["content"]
89
+ return f"ERROR: {resp.status_code}"
90
+ except Exception as e:
91
+ return f"ERROR: {e}"
92
+
93
+ async def initialize(self, proxy_config: Optional[Dict] = None) -> bool:
94
+ try:
95
+ from playwright.async_api import async_playwright
96
+ pw = await async_playwright().start()
97
+ context_args = {"viewport": {"width": 1280, "height": 720}}
98
+ if proxy_config:
99
+ context_args["proxy"] = proxy_config
100
+ self.browser = await pw.chromium.launch(headless=True)
101
+ self.context = await self.browser.new_context(**context_args)
102
+ self.page = await self.context.new_page()
103
+ return True
104
+ except Exception as e:
105
+ logger.error(f"Init failed: {e}")
106
+ return False
107
+
108
+ async def close(self):
109
+ if self.browser:
110
+ await self.browser.close()
111
+
112
+
113
+ async def get_rotating_proxy() -> Optional[Dict]:
114
+ webshare_key = os.getenv("WEBSHARE_API_KEY", "")
115
+ if not webshare_key:
116
+ return None
117
+ try:
118
+ async with httpx.AsyncClient(timeout=10.0) as client:
119
+ resp = await client.get(
120
+ "https://proxy.webshare.io/api/v2/proxy/list/?mode=direct&page=1&page_size=1",
121
+ headers={"Authorization": f"Token {webshare_key}"}
122
+ )
123
+ if resp.status_code == 200:
124
+ data = resp.json()
125
+ if data.get("results"):
126
+ p = data["results"][0]
127
+ return {
128
+ "server": f"http://{p['proxy_address']}:{p['port']}",
129
+ "username": p["username"],
130
+ "password": p["password"]
131
+ }
132
+ except:
133
+ pass
134
+ return None
135
+
136
+
137
+ async def get_a11y_tree(page) -> str:
138
+ try:
139
+ snapshot = await page.accessibility.snapshot()
140
+ return json.dumps(snapshot, indent=2)[:3000] if snapshot else ""
141
+ except:
142
+ return ""
143
+
144
+
145
+ async def validate_order(order_data: Dict[str, Any]) -> Dict[str, Any]:
146
+ start_time = time.time()
147
+ email = order_data.get("email", "")
148
+ phone = order_data.get("phone", "")
149
+ zip_code = order_data.get("zip", "")
150
+ city = order_data.get("city", "")
151
+ state = order_data.get("state", "")
152
+
153
+ api_key = os.getenv("OPENROUTER_API_KEY")
154
+ if not api_key:
155
+ return {"decision": "ERROR", "error": "No API key"}
156
+
157
+ organs = AgentOrgans(api_key)
158
+ proxy = await get_rotating_proxy()
159
+
160
+ if not await organs.initialize(proxy):
161
+ return {"decision": "ERROR", "error": "Browser init failed"}
162
+
163
+ try:
164
+ task = f"Validate: Email={email}, Phone={phone}, Geo={zip_code},{city},{state}. Return JSON with decision, email_valid, phone_valid, geo_match."
165
+
166
+ result = None
167
+ for _ in range(10):
168
+ a11y = await get_a11y_tree(organs.page)
169
+ url = organs.page.url
170
+
171
+ prompt = f"URL: {url}\nA11y: {a11y[:1500]}\nTask: {task}\nWhat next? If done, return JSON."
172
+ response = await organs.call_llm("brain", prompt)
173
+
174
+ if '{"decision":' in response:
175
+ try:
176
+ start = response.find("{")
177
+ end = response.rfind("}") + 1
178
+ result = json.loads(response[start:end])
179
+ break
180
+ except:
181
+ pass
182
+
183
+ if "NAVIGATE:" in response.upper():
184
+ url = response.split(":", 1)[1].strip().split()[0]
185
+ await organs.page.goto(url, timeout=30000)
186
+ elif "CLICK:" in response.upper():
187
+ target = response.split(":", 1)[1].strip()
188
+ try:
189
+ await organs.page.click(f"text={target[:30]}", timeout=5000)
190
+ except:
191
+ pass
192
+ elif "TYPE:" in response.upper() and "INTO" in response.upper():
193
+ parts = response.split("INTO")
194
+ text = parts[0].replace("TYPE:", "").strip()
195
+ try:
196
+ await organs.page.fill("input:visible", text, timeout=5000)
197
+ except:
198
+ pass
199
+
200
+ await asyncio.sleep(1)
201
+
202
+ await organs.close()
203
+
204
+ if result:
205
+ return {
206
+ "order_id": order_data.get("order_id", "UNKNOWN"),
207
+ "decision": result.get("decision", "UNKNOWN"),
208
+ "email_valid": result.get("email_valid", False),
209
+ "phone_valid": result.get("phone_valid", False),
210
+ "geo_match": result.get("geo_match", False),
211
+ "reasoning": result.get("reasoning", ""),
212
+ "execution_time_ms": int((time.time() - start_time) * 1000)
213
+ }
214
+
215
+ return {"order_id": order_data.get("order_id"), "decision": "MANUAL_REVIEW"}
216
+
217
+ except Exception as e:
218
+ await organs.close()
219
+ return {"decision": "ERROR", "error": str(e)}
order_worker_info.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ORDER WORKER INFO (Worker - The Warrior)
3
+ """
4
+
5
+ IDENTITY = """
6
+ I am the Order Validation Field Agent (Worker).
7
+ I am the Executor and Problem Solver.
8
+ I operate in the wild (the internet).
9
+ I am Resourceful, Persistent, and Observant.
10
+ """
11
+
12
+ MISSION = """
13
+ My goal is to execute the validation tasks given by HQ.
14
+ I must navigate to real websites, interact with them, and find the truth.
15
+ I must overcome obstacles (popups, captchas, errors) to get the data.
16
+ I report EXACTLY what I see, not what HQ wants to hear.
17
+ """
18
+
19
+ NATURE = """
20
+ Adaptive: If a selector fails, I search. If a site fails, I scroll.
21
+ Survivor: If a popup blocks me, I close it. I do not stop.
22
+ Observant: I look at the screen (A11y/Vision) before I click.
23
+ Honest: If I cannot do it, I say I cannot, I do not lie.
24
+ Cautious: If HQ asks me to do something unsafe, I refuse.
25
+ """
26
+
27
+ RESOURCES = """
28
+ Brain (Chimera): To decide How do I click this or How do I clear this popup.
29
+ Eyes (Gemini): To SEE the screenshot and read the page structure (A11y).
30
+ Hands (Playwright): To Move, Click, Type, Scroll, Wait.
31
+ Proxy (Webshare): My shield. I NEVER go out without it.
32
+ Guard (Self-Correction): If I get stuck in a loop, Guard tells me to try a new path.
33
+ """
34
+
35
+ CONFLICT_PROTOCOL = """
36
+ Scenario: HQ says Click X, but X looks like a Delete All button.
37
+ My Reaction: I DO NOT CLICK.
38
+ Action: I call the Guard.
39
+ Guard, HQ asked to click X, but it looks dangerous. Judge this.
40
+ Verdict: I follow the Guards safety instruction.
41
+ """
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ fastapi>=0.104.0
2
+ uvicorn>=0.24.0
3
+ pydantic>=2.0.0
4
+ httpx>=0.25.0
5
+ browser-use>=0.1.0
6
+ playwright>=1.40.0
7
+ langchain-openai>=0.0.5
8
+ openai>=1.3.0
9
+ Pillow>=10.0.0
10
+ python-dotenv>=1.0.0