Bluestrikeai commited on
Commit
e0d601d
Β·
verified Β·
1 Parent(s): e2eb22f

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +185 -0
app.py ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import time
4
+ import json
5
+ import subprocess
6
+ import gradio as gr
7
+ from openai import OpenAI
8
+ from duckduckgo_search import DDGS
9
+
10
+ # --- OpenRouter Setup ---
11
+ OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY", "your-openrouter-key")
12
+ client = OpenAI(
13
+ base_url="https://openrouter.ai/api/v1",
14
+ api_key=OPENROUTER_API_KEY,
15
+ )
16
+
17
+ # --- Model Definitions ---
18
+ MODEL_RESEARCHER = "z-ai/glm-4.5-air"
19
+ MODEL_PLANNER = "arcee-ai/trinity-large-preview"
20
+ MODEL_FRONTEND = "qwen/qwen3-coder"
21
+ MODEL_BACKEND = "minimax/minimax-m2.5"
22
+
23
+ WORKSPACE_DIR = "/app/workspace"
24
+ preview_process = None
25
+
26
+ # --- Helper Functions ---
27
+ def extract_code(text, lang="javascript"):
28
+ """Extracts code blocks from markdown responses."""
29
+ pattern = rf"```{lang}\n(.*?)\n```"
30
+ matches = re.findall(pattern, text, re.DOTALL)
31
+ if matches:
32
+ return matches[0]
33
+
34
+ # Fallback to any code block
35
+ pattern_any = r"```.*?\n(.*?)\n```"
36
+ matches_any = re.findall(pattern_any, text, re.DOTALL)
37
+ return matches_any[0] if matches_any else text
38
+
39
+ def web_search(query):
40
+ """Real-time web search for the Researcher AI"""
41
+ try:
42
+ results = DDGS().text(query, max_results=3)
43
+ return "\n".join([f"- {r['title']}: {r['body']}" for r in results])
44
+ except Exception as e:
45
+ return f"Web search failed: {e}"
46
+
47
+ def run_openrouter(model, system_prompt, user_prompt):
48
+ """Wrapper for OpenRouter API calls"""
49
+ response = client.chat.completions.create(
50
+ model=model,
51
+ messages=[
52
+ {"role": "system", "content": system_prompt},
53
+ {"role": "user", "content": user_prompt}
54
+ ]
55
+ )
56
+ return response.choices[0].message.content
57
+
58
+ # --- Multi-Agent Pipeline ---
59
+ def generate_website(prompt):
60
+ global preview_process
61
+ logs = []
62
+
63
+ yield "Step 1: 🌐 Researcher (GLM-4.5-Air) gathering real-time data...", "", ""
64
+
65
+ # 1. RESEARCHER
66
+ search_context = web_search(prompt)
67
+ research_prompt = f"User Request: {prompt}\nReal-time Web Context: {search_context}\nSummarize the requirements, target audience, and modern tech trends for this app."
68
+ research_data = run_openrouter(
69
+ MODEL_RESEARCHER,
70
+ "You are an expert tech researcher. Analyze the user request and web data.",
71
+ research_prompt
72
+ )
73
+ logs.append("βœ… Research completed.")
74
+ yield "\n".join(logs), "Step 2: πŸ—οΈ Planner (Trinity-Large) designing architecture...", ""
75
+
76
+ # 2. PLANNER
77
+ plan_prompt = f"Based on this research: {research_data}\nCreate a full stack architecture plan. Define the React frontend components and Express backend endpoints."
78
+ architecture_plan = run_openrouter(
79
+ MODEL_PLANNER,
80
+ "You are a Lead Solutions Architect. Output a clear, structured technical design.",
81
+ plan_prompt
82
+ )
83
+ logs.append("βœ… Architecture planned.")
84
+ yield "\n".join(logs), "Step 3: πŸ’» Frontend Coder (Qwen3-Coder) building UI...", ""
85
+
86
+ # 3. FRONTEND CODER
87
+ fe_prompt = f"Architecture: {architecture_plan}\nWrite a complete React App using standard React and Tailwind. Output two things: 1. A package.json file wrapped in ```json ... ``` containing required dependencies. 2. A complete App.jsx wrapped in ```javascript ... ```."
88
+ frontend_code_raw = run_openrouter(
89
+ MODEL_FRONTEND,
90
+ "You are an Expert React Developer. Generate functional, modern React code.",
91
+ fe_prompt
92
+ )
93
+ app_jsx = extract_code(frontend_code_raw, "javascript")
94
+ package_json = extract_code(frontend_code_raw, "json")
95
+
96
+ # Save Frontend files
97
+ os.makedirs(os.path.join(WORKSPACE_DIR, "frontend", "src"), exist_ok=True)
98
+ with open(os.path.join(WORKSPACE_DIR, "frontend", "package.json"), "w") as f:
99
+ f.write(package_json)
100
+ with open(os.path.join(WORKSPACE_DIR, "frontend", "src", "App.jsx"), "w") as f:
101
+ f.write(app_jsx)
102
+
103
+ logs.append("βœ… Frontend generated and saved.")
104
+ yield "\n".join(logs), "Step 4: πŸ” Backend Coder (MiniMax-M2.5) building secure API...", ""
105
+
106
+ # 4. BACKEND CODER & INSTRUCTION GUIDE
107
+ be_prompt = f"Architecture: {architecture_plan}\nWrite a secure Express.js backend. Provide the server code wrapped in ```javascript ... ```. Then, provide a detailed Markdown guide wrapped in ```markdown ... ``` explaining exactly where the user needs to add their Postgres/MongoDB strings, Stripe Secret Keys, and Clerk/Auth0 tokens."
108
+ backend_code_raw = run_openrouter(
109
+ MODEL_BACKEND,
110
+ "You are a Senior Security & Backend Engineer.",
111
+ be_prompt
112
+ )
113
+ server_js = extract_code(backend_code_raw, "javascript")
114
+ setup_guide = extract_code(backend_code_raw, "markdown")
115
+
116
+ # Save Backend files
117
+ os.makedirs(os.path.join(WORKSPACE_DIR, "backend"), exist_ok=True)
118
+ with open(os.path.join(WORKSPACE_DIR, "backend", "server.js"), "w") as f:
119
+ f.write(server_js)
120
+ with open(os.path.join(WORKSPACE_DIR, "SETUP_GUIDE.md"), "w") as f:
121
+ f.write(setup_guide)
122
+
123
+ logs.append("βœ… Backend and Setup Guide generated.")
124
+ yield "\n".join(logs), "Step 5: βš™οΈ Installing Dependencies & Starting Live Preview...", setup_guide
125
+
126
+ # 5. EXECUTION & DEPENDENCY DOWNLOAD
127
+ try:
128
+ # Install dependencies
129
+ subprocess.run(["npm", "install"], cwd=os.path.join(WORKSPACE_DIR, "frontend"), check=True)
130
+ logs.append("βœ… AI successfully downloaded dependencies.")
131
+ yield "\n".join(logs), "Starting Server...", setup_guide
132
+
133
+ # Kill previous process if it exists
134
+ if preview_process:
135
+ preview_process.kill()
136
+
137
+ # Normally you would use a bundler like Vite. To keep it robust for this example,
138
+ # we start a simple HTTP server or a lightweight bundler command if defined in package.json.
139
+ # Assuming AI creates standard start scripts:
140
+ preview_process = subprocess.Popen(
141
+ ["npm", "start"],
142
+ cwd=os.path.join(WORKSPACE_DIR, "frontend"),
143
+ env=dict(os.environ, PORT="3000")
144
+ )
145
+
146
+ # Give server time to boot
147
+ time.sleep(5)
148
+
149
+ logs.append("πŸš€ Live preview is running!")
150
+ iframe_html = f'<iframe src="https://{os.getenv("SPACE_HOST", "localhost")}:3000" width="100%" height="600px" style="border:1px solid #ccc; border-radius: 8px;"></iframe>'
151
+
152
+ yield "\n".join(logs), iframe_html, setup_guide
153
+
154
+ except Exception as e:
155
+ logs.append(f"❌ Execution Error: {str(e)}")
156
+ yield "\n".join(logs), "Failed to start live preview.", setup_guide
157
+
158
+
159
+ # --- UI Setup (Gradio) ---
160
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
161
+ gr.Markdown("# πŸš€ Multi-Agent AI Full-Stack Builder")
162
+ gr.Markdown("Powered by `z-ai/glm-4.5-air` (Researcher), `arcee-ai/trinity-large` (Architect), `qwen/qwen3-coder` (Frontend), and `minimax-m2.5` (Backend).")
163
+
164
+ with gr.Row():
165
+ with gr.Column(scale=1):
166
+ prompt_input = gr.Textbox(lines=4, placeholder="E.g., Build a SaaS dashboard for an AI writing tool with Stripe subscriptions...", label="App Idea")
167
+ build_btn = gr.Button("Build Application", variant="primary")
168
+ status_box = gr.Textbox(label="Agent Status Logs", lines=10, interactive=False)
169
+
170
+ with gr.Column(scale=2):
171
+ gr.Markdown("### Live Website Preview")
172
+ preview_box = gr.HTML("<div style='text-align:center; padding: 50px; border:1px dashed gray;'>Preview will appear here once built.</div>")
173
+
174
+ with gr.Row():
175
+ gr.Markdown("### Setup Guide (DB, Auth & Payments)")
176
+ guide_box = gr.Markdown("Setup instructions will appear here.")
177
+
178
+ build_btn.click(
179
+ fn=generate_website,
180
+ inputs=[prompt_input],
181
+ outputs=[status_box, preview_box, guide_box]
182
+ )
183
+
184
+ if __name__ == "__main__":
185
+ demo.launch(server_name="0.0.0.0", server_port=7860)